From 33ffd3a37ad85a4f505ed6d3d4f25fa1c9d9ea8d Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Tue, 25 Nov 2025 20:40:46 -0800 Subject: [PATCH] first iteration --- .github/copilot-instructions.md | 294 +- .github/copilot-instructions.md.backup | 222 + .vscode/extensions.json | 4 +- .vscode/settings.json | 182 +- .vscode/tasks.json | 114 +- QuanTAlib.sln | 116 +- Tests/Tests.csproj | 56 - Tests/UpdateTestBase.cs | 91 - Tests/test_Trady.cs | 108 - Tests/test_Tulip.cs | 88 - Tests/test_core.cs | 251 - Tests/test_eventing.cs | 160 - Tests/test_iTBar.cs | 172 - Tests/test_quantower.cs | 168 - Tests/test_skender.stock.cs | 354 - Tests/test_talib.cs | 130 - Tests/test_updates_averages.cs | 529 - Tests/test_updates_errors.cs | 259 - Tests/test_updates_momentum.cs | 292 - Tests/test_updates_oscillators.cs | 182 - Tests/test_updates_statistics.cs | 160 - Tests/test_updates_volatility.cs | 223 - Tests/test_updates_volume.cs | 386 - build.sh | 3 - docs/.nojekyll | 1 - docs/.playground/mermaidtest.md | 21 - docs/Progress.md | 313 - docs/_sidebar.md | 113 - docs/essays/realtime.md | 43 - docs/img/dotpeek.png | Bin 177156 -> 0 bytes docs/img/emaweights.svg | 434 - docs/img/quotes.gif | Bin 780780 -> 0 bytes docs/img/structure.md | 29 - docs/index.html | 142 - docs/indicators/averages/afirma/afirma.md | 27 - docs/indicators/averages/afirma/analysis.md | 60 - docs/indicators/averages/afirma/calc.md | 67 - docs/indicators/averages/afirma/charts.dib | 63 - docs/indicators/averages/afirma/charts.md | 3 - .../averages/afirma/img/AFIRMA6_B.svg | 330 - .../averages/afirma/img/AFIRMA6_Chirp.svg | 330 - .../averages/afirma/img/AFIRMA6_ChirpG.svg | 348 - .../averages/afirma/img/AFIRMA6_Complex.svg | 333 - .../averages/afirma/img/AFIRMA6_Gauss.svg | 327 - .../averages/afirma/img/AFIRMA6_HF.svg | 330 - .../averages/afirma/img/AFIRMA6_Impulse.svg | 338 - .../averages/afirma/img/AFIRMA6_ImpulseHF.svg | 320 - .../averages/afirma/img/AFIRMA6_Market.svg | 357 - .../averages/afirma/img/AFIRMA6_Sawtooth.svg | 355 - .../afirma/img/AFIRMA6_SawtoothHF.svg | 332 - .../averages/afirma/img/AFIRMA6_Sine.svg | 330 - .../averages/afirma/img/AFIRMA6_SineG.svg | 346 - .../averages/afirma/img/AFIRMA6_Spike.svg | 338 - .../averages/afirma/img/AFIRMA6_Triangle.svg | 355 - .../averages/afirma/img/AFIRMA6_White.svg | 335 - docs/indicators/averages/alma/alma.md | 53 - docs/indicators/averages/alma/analysis.md | 51 - docs/indicators/averages/alma/calc.md | 45 - docs/indicators/averages/alma/charts.dib | 62 - docs/indicators/averages/alma/charts.md | 3 - .../indicators/averages/alma/img/ALMA10_B.svg | 330 - .../averages/alma/img/ALMA10_Chirp.svg | 330 - .../averages/alma/img/ALMA10_ChirpG.svg | 348 - .../averages/alma/img/ALMA10_Complex.svg | 333 - .../averages/alma/img/ALMA10_Gauss.svg | 327 - .../averages/alma/img/ALMA10_HF.svg | 330 - .../averages/alma/img/ALMA10_Impulse.svg | 338 - .../averages/alma/img/ALMA10_ImpulseHF.svg | 320 - .../averages/alma/img/ALMA10_Market.svg | 357 - .../averages/alma/img/ALMA10_Sawtooth.svg | 355 - .../averages/alma/img/ALMA10_SawtoothHF.svg | 332 - .../averages/alma/img/ALMA10_Sine.svg | 330 - .../averages/alma/img/ALMA10_SineG.svg | 346 - .../averages/alma/img/ALMA10_Spike.svg | 338 - .../averages/alma/img/ALMA10_Triangle.svg | 355 - .../averages/alma/img/ALMA10_White.svg | 335 - .../averages/convolution/convolution.md | 0 docs/indicators/averages/dema/analysis.md | 65 - docs/indicators/averages/dema/calc.md | 48 - docs/indicators/averages/dema/charts.dib | 60 - docs/indicators/averages/dema/charts.md | 3 - docs/indicators/averages/dema/dema.md | 59 - .../indicators/averages/dema/img/DEMA10_B.svg | 330 - .../averages/dema/img/DEMA10_Chirp.svg | 330 - .../averages/dema/img/DEMA10_ChirpG.svg | 348 - .../averages/dema/img/DEMA10_Complex.svg | 333 - .../averages/dema/img/DEMA10_Gauss.svg | 327 - .../averages/dema/img/DEMA10_HF.svg | 330 - .../averages/dema/img/DEMA10_Impulse.svg | 342 - .../averages/dema/img/DEMA10_ImpulseHF.svg | 320 - .../averages/dema/img/DEMA10_Market.svg | 357 - .../averages/dema/img/DEMA10_Sawtooth.svg | 362 - .../averages/dema/img/DEMA10_SawtoothHF.svg | 332 - .../averages/dema/img/DEMA10_Sine.svg | 332 - .../averages/dema/img/DEMA10_SineG.svg | 346 - .../averages/dema/img/DEMA10_Spike.svg | 339 - .../averages/dema/img/DEMA10_Triangle.svg | 355 - .../averages/dema/img/DEMA10_White.svg | 335 - docs/indicators/averages/dsma/analysis.md | 0 docs/indicators/averages/dsma/calc.md | 0 docs/indicators/averages/dsma/charts.dib | 61 - docs/indicators/averages/dsma/charts.md | 3 - docs/indicators/averages/dsma/dsma.md | 62 - .../indicators/averages/dsma/img/DSMA10_B.svg | 330 - .../averages/dsma/img/DSMA10_Chirp.svg | 330 - .../averages/dsma/img/DSMA10_ChirpG.svg | 348 - .../averages/dsma/img/DSMA10_Complex.svg | 333 - .../averages/dsma/img/DSMA10_Gauss.svg | 327 - .../averages/dsma/img/DSMA10_HF.svg | 330 - .../averages/dsma/img/DSMA10_Impulse.svg | 338 - .../averages/dsma/img/DSMA10_ImpulseHF.svg | 320 - .../averages/dsma/img/DSMA10_Market.svg | 357 - .../averages/dsma/img/DSMA10_Sawtooth.svg | 355 - .../averages/dsma/img/DSMA10_SawtoothHF.svg | 332 - .../averages/dsma/img/DSMA10_Sine.svg | 330 - .../averages/dsma/img/DSMA10_SineG.svg | 346 - .../averages/dsma/img/DSMA10_Spike.svg | 338 - .../averages/dsma/img/DSMA10_Triangle.svg | 355 - .../averages/dsma/img/DSMA10_White.svg | 335 - docs/indicators/averages/dwma/analysis.md | 0 docs/indicators/averages/dwma/calc.md | 0 docs/indicators/averages/dwma/charts.dib | 60 - docs/indicators/averages/dwma/charts.md | 3 - docs/indicators/averages/dwma/dwma.md | 0 .../indicators/averages/dwma/img/DWMA10_B.svg | 330 - .../averages/dwma/img/DWMA10_Chirp.svg | 330 - .../averages/dwma/img/DWMA10_ChirpG.svg | 348 - .../averages/dwma/img/DWMA10_Complex.svg | 333 - .../averages/dwma/img/DWMA10_Gauss.svg | 327 - .../averages/dwma/img/DWMA10_HF.svg | 330 - .../averages/dwma/img/DWMA10_Impulse.svg | 338 - .../averages/dwma/img/DWMA10_ImpulseHF.svg | 320 - .../averages/dwma/img/DWMA10_Market.svg | 357 - .../averages/dwma/img/DWMA10_Sawtooth.svg | 355 - .../averages/dwma/img/DWMA10_SawtoothHF.svg | 332 - .../averages/dwma/img/DWMA10_Sine.svg | 330 - .../averages/dwma/img/DWMA10_SineG.svg | 346 - .../averages/dwma/img/DWMA10_Spike.svg | 338 - .../averages/dwma/img/DWMA10_Triangle.svg | 355 - .../averages/dwma/img/DWMA10_White.svg | 335 - docs/indicators/averages/ema/analysis.md | 0 docs/indicators/averages/ema/calc.md | 0 docs/indicators/averages/ema/calculation.md | 55 - docs/indicators/averages/ema/charts.dib | 60 - docs/indicators/averages/ema/charts.md | 3 - docs/indicators/averages/ema/ema.md | 4 - docs/indicators/averages/ema/img/EMA10_B.svg | 330 - .../averages/ema/img/EMA10_Chirp.svg | 330 - .../averages/ema/img/EMA10_ChirpG.svg | 348 - .../averages/ema/img/EMA10_Complex.svg | 333 - .../averages/ema/img/EMA10_Gauss.svg | 327 - docs/indicators/averages/ema/img/EMA10_HF.svg | 330 - .../averages/ema/img/EMA10_Impulse.svg | 338 - .../averages/ema/img/EMA10_ImpulseHF.svg | 320 - .../averages/ema/img/EMA10_Market.svg | 357 - .../averages/ema/img/EMA10_Sawtooth.svg | 355 - .../averages/ema/img/EMA10_SawtoothHF.svg | 332 - .../averages/ema/img/EMA10_Sine.svg | 330 - .../averages/ema/img/EMA10_SineG.svg | 346 - .../averages/ema/img/EMA10_Spike.svg | 338 - .../averages/ema/img/EMA10_Triangle.svg | 355 - .../averages/ema/img/EMA10_White.svg | 335 - docs/indicators/averages/ema/quality.md | 48 - docs/indicators/averages/epma/epma.md | 0 docs/indicators/averages/frama/frama.md | 0 docs/indicators/averages/fwma/fwma.md | 0 docs/indicators/averages/gma/gma.md | 0 docs/indicators/averages/hma/hma.md | 0 docs/indicators/averages/htit/htit.md | 0 docs/indicators/averages/hwma/hwma.md | 0 docs/indicators/averages/jma/calc.md | 48 - docs/indicators/averages/jma/jma.md | 0 docs/indicators/averages/kama/kama.md | 0 docs/indicators/averages/ltma/ltma.md | 0 docs/indicators/averages/maaf/maaf.md | 0 docs/indicators/averages/mama/mama.md | 0 docs/indicators/averages/mgdi/mgdi.md | 0 docs/indicators/averages/mma/mma.md | 0 docs/indicators/averages/pwma/pwma.md | 0 docs/indicators/averages/qema/qema.md | 0 docs/indicators/averages/rema/rema.md | 0 docs/indicators/averages/rma/rma.md | 0 docs/indicators/averages/sinema/sinema.md | 0 docs/indicators/averages/sma/calc.md | 0 docs/indicators/averages/sma/charts.dib | 60 - docs/indicators/averages/sma/charts.md | 3 - docs/indicators/averages/sma/img/SMA10_B.svg | 330 - .../averages/sma/img/SMA10_Chirp.svg | 330 - .../averages/sma/img/SMA10_ChirpG.svg | 348 - .../averages/sma/img/SMA10_Complex.svg | 333 - .../averages/sma/img/SMA10_Gauss.svg | 327 - docs/indicators/averages/sma/img/SMA10_HF.svg | 330 - .../averages/sma/img/SMA10_Impulse.svg | 338 - .../averages/sma/img/SMA10_ImpulseHF.svg | 320 - .../averages/sma/img/SMA10_Market.svg | 357 - .../averages/sma/img/SMA10_Sawtooth.svg | 355 - .../averages/sma/img/SMA10_SawtoothHF.svg | 332 - .../averages/sma/img/SMA10_Sine.svg | 330 - .../averages/sma/img/SMA10_SineG.svg | 346 - .../averages/sma/img/SMA10_Spike.svg | 338 - .../averages/sma/img/SMA10_Triangle.svg | 355 - .../averages/sma/img/SMA10_White.svg | 335 - docs/indicators/averages/sma/sma.md | 0 docs/indicators/averages/smma/smma.md | 0 docs/indicators/averages/t3/t3.md | 0 docs/indicators/averages/tema/analysis.md | 0 docs/indicators/averages/tema/calc.md | 52 - docs/indicators/averages/tema/charts.dib | 60 - docs/indicators/averages/tema/charts.md | 3 - .../indicators/averages/tema/img/TEMA10_B.svg | 330 - .../averages/tema/img/TEMA10_Chirp.svg | 334 - .../averages/tema/img/TEMA10_ChirpG.svg | 352 - .../averages/tema/img/TEMA10_Complex.svg | 334 - .../averages/tema/img/TEMA10_Gauss.svg | 327 - .../averages/tema/img/TEMA10_HF.svg | 330 - .../averages/tema/img/TEMA10_Impulse.svg | 346 - .../averages/tema/img/TEMA10_ImpulseHF.svg | 320 - .../averages/tema/img/TEMA10_Market.svg | 357 - .../averages/tema/img/TEMA10_Sawtooth.svg | 364 - .../averages/tema/img/TEMA10_SawtoothHF.svg | 336 - .../averages/tema/img/TEMA10_Sine.svg | 334 - .../averages/tema/img/TEMA10_SineG.svg | 347 - .../averages/tema/img/TEMA10_Spike.svg | 339 - .../averages/tema/img/TEMA10_Triangle.svg | 355 - .../averages/tema/img/TEMA10_White.svg | 335 - docs/indicators/averages/tema/tema.md | 0 docs/indicators/averages/trima/trima.md | 0 docs/indicators/averages/vidya/vidya.md | 0 docs/indicators/averages/wma/wma.md | 0 docs/indicators/averages/zlema/zlema.md | 0 docs/indicators/indicators.md | 208 - docs/indicators/momentum/adx/description.md | 43 - docs/indicators/momentum/adxr/description.md | 43 - docs/indicators/momentum/apo/description.md | 43 - docs/indicators/momentum/dmi/description.md | 43 - docs/indicators/momentum/dmx/description.md | 20 - docs/indicators/momentum/dpo/description.md | 43 - docs/indicators/momentum/mom/description.md | 43 - docs/indicators/momentum/pmo/description.md | 43 - docs/indicators/momentum/po/description.md | 43 - docs/indicators/momentum/ppo/description.md | 48 - docs/indicators/momentum/prs/description.md | 48 - docs/indicators/momentum/roc/description.md | 48 - docs/indicators/momentum/trix/description.md | 48 - docs/indicators/momentum/tsi/description.md | 48 - docs/indicators/momentum/vel/description.md | 43 - .../indicators/momentum/vortex/description.md | 48 - docs/indicators/oscillators/ac/ac.md | 0 docs/indicators/oscillators/ao/ao.md | 0 docs/indicators/oscillators/aroon/aroon.md | 0 docs/indicators/oscillators/bop/bop.md | 0 docs/indicators/oscillators/cci/cci.md | 0 docs/indicators/oscillators/cfo/cfo.md | 0 docs/indicators/oscillators/cmo/cmo.md | 0 docs/indicators/oscillators/rsi/rsi.md | 0 docs/indicators/oscillators/rsx/rsx.md | 0 .../statistics/curvature/curvature.md | 0 docs/indicators/statistics/entropy/entropy.md | 0 .../statistics/kurtosis/kurtosis.md | 0 docs/indicators/statistics/list.md | 52 - docs/indicators/statistics/max/max.md | 0 docs/indicators/statistics/median/median.md | 0 docs/indicators/statistics/min/min.md | 0 docs/indicators/statistics/mode/mode.md | 0 .../statistics/percentile/percentile.md | 0 docs/indicators/statistics/skew/skew.md | 0 docs/indicators/statistics/slope/slope.md | 0 docs/indicators/statistics/stddev/stddev.md | 0 .../statistics/variance/variance.md | 0 docs/indicators/statistics/zscore/zscore.md | 0 docs/indicators/volatility/atr/atr.md | 0 docs/indicators/volatility/hv/hv.md | 0 docs/indicators/volatility/jvolty/jvolty.md | 0 docs/indicators/volatility/rv/rv.md | 0 docs/indicators/volatility/rvi/calc.md | 50 - docs/indicators/volatility/rvi/rvi.md | 0 docs/indicators/volatility/tr/tr.md | 0 docs/indicators/volatility/ui/ui.md | 0 docs/indicators/volatility/vc/vc.md | 0 docs/indicators/volatility/vov/vov.md | 0 docs/indicators/volatility/vr/vr.md | 0 docs/indicators/volatility/vs/vs.md | 0 docs/indicators/volume/adl/adl.md | 0 docs/indicators/volume/adosc/adosc.md | 0 docs/indicators/volume/aobv/aobv.md | 0 docs/indicators/volume/cmf/cmf.md | 0 docs/indicators/volume/eom/eom.md | 0 docs/indicators/volume/kvo/kvo.md | 0 docs/indicators/volume/mfi/mfi.md | 0 docs/indicators/volume/nvi/nvi.md | 0 docs/indicators/volume/obv/obv.md | 0 docs/indicators/volume/pvi/pvi.md | 0 docs/indicators/volume/pvo/pvo.md | 0 docs/indicators/volume/pvol/pvol.md | 0 docs/indicators/volume/pvr/pvr.md | 0 docs/indicators/volume/pvt/pvt.md | 0 docs/indicators/volume/tvi/tvi.md | 0 docs/readme.md | 47 - docs/setup/dotpeek.md | 46 - docs/setup/quantower.md | 1 - docs/setup/vscode.md | 89 - ilspy/TradingPlatform.BusinessLayer.cs | 114089 +++++++++++++++ lib/_list.md | 173 - lib/averages/Afirma.cs | 187 - lib/averages/Alma.cs | 115 - lib/averages/Convolution.cs | 141 - lib/averages/Dema.cs | 102 - lib/averages/Dsma.cs | 166 - lib/averages/Dwma.cs | 85 - lib/averages/Ema.cs | 150 - lib/averages/Epma.cs | 119 - lib/averages/Frama.cs | 146 - lib/averages/Fwma.cs | 113 - lib/averages/Gma.cs | 113 - lib/averages/Hma.cs | 122 - lib/averages/Htit.cs | 184 - lib/averages/Hwma.cs | 156 - lib/averages/Jma.cs | 178 - lib/averages/Kama.cs | 134 - lib/averages/Ltma.cs | 122 - lib/averages/Maaf.cs | 163 - lib/averages/Mama.cs | 211 - lib/averages/Mgdi.cs | 113 - lib/averages/Mma.cs | 117 - lib/averages/Pwma.cs | 136 - lib/averages/Qema.cs | 114 - lib/averages/Rema.cs | 136 - lib/averages/Rma.cs | 136 - lib/averages/Sinema.cs | 111 - lib/averages/Sma.cs | 99 - lib/averages/Smma.cs | 113 - lib/averages/T3.cs | 178 - lib/averages/Tema.cs | 125 - lib/averages/Trima.cs | 111 - lib/averages/Vidya.cs | 135 - lib/averages/Wma.cs | 103 - lib/averages/Zlema.cs | 112 - lib/averages/_list.md | 36 - lib/class_types.md | 86 - lib/core/AbstractBarBase.cs | 129 - lib/core/SimdExtensions.cs | 280 + lib/core/abstractBase.cs | 159 - lib/core/circularbuffer.cs | 443 - lib/core/formatters.cs | 97 - lib/core/tbar.cs | 95 +- lib/core/tbarseries.cs | 187 +- lib/core/tseries.cs | 188 +- lib/core/tvalue.cs | 58 +- lib/errors/Huber.cs | 130 - lib/errors/Mae.cs | 109 - lib/errors/Mapd.cs | 117 - lib/errors/Mape.cs | 117 - lib/errors/Mase.cs | 153 - lib/errors/Mda.cs | 119 - lib/errors/Me.cs | 117 - lib/errors/Mpe.cs | 118 - lib/errors/Mse.cs | 118 - lib/errors/Msle.cs | 121 - lib/errors/Rae.cs | 120 - lib/errors/Rmse.cs | 119 - lib/errors/Rmsle.cs | 122 - lib/errors/Rse.cs | 124 - lib/errors/Rsquared.cs | 124 - lib/errors/Smape.cs | 126 - lib/errors/_list.md | 16 - lib/feeds/CsvFeed.cs | 196 + lib/feeds/GbmFeed.cs | 76 - lib/feeds/IFeed.cs | 35 + lib/feeds/gbm.cs | 211 + lib/momentum/Adx.cs | 177 - lib/momentum/Adxr.cs | 83 - lib/momentum/Apo.cs | 59 - lib/momentum/Dmi.cs | 147 - lib/momentum/Dmx.cs | 92 - lib/momentum/Dpo.cs | 105 - lib/momentum/Macd.cs | 113 - lib/momentum/Mom.cs | 74 - lib/momentum/Pmo.cs | 101 - lib/momentum/Po.cs | 79 - lib/momentum/Ppo.cs | 84 - lib/momentum/Prs.cs | 83 - lib/momentum/Roc.cs | 79 - lib/momentum/Trix.cs | 86 - lib/momentum/Vel.cs | 88 - lib/momentum/Vortex.cs | 161 - lib/momentum/_list.md | 19 - lib/oscillators/Ac.cs | 70 - lib/oscillators/Ao.cs | 70 - lib/oscillators/Aroon.cs | 119 - lib/oscillators/Bop.cs | 65 - lib/oscillators/Cci.cs | 100 - lib/oscillators/Cfo.cs | 116 - lib/oscillators/Chop.cs | 110 - lib/oscillators/Cmo.cs | 117 - lib/oscillators/Cog.cs | 100 - lib/oscillators/Coppock.cs | 115 - lib/oscillators/Crsi.cs | 97 - lib/oscillators/Cti.cs | 109 - lib/oscillators/Dosc.cs | 74 - lib/oscillators/Efi.cs | 102 - lib/oscillators/Fisher.cs | 94 - lib/oscillators/Rsi.cs | 116 - lib/oscillators/Rsx.cs | 131 - lib/oscillators/Smi.cs | 118 - lib/oscillators/Srsi.cs | 131 - lib/oscillators/Stc.cs | 145 - lib/oscillators/Stoch.cs | 123 - lib/oscillators/Tsi.cs | 111 - lib/oscillators/Uo.cs | 161 - lib/oscillators/Willr.cs | 86 - lib/oscillators/_list.md | 32 - lib/patterns/_list.md | 11 - lib/quantalib.csproj | 14 +- lib/statistics/Beta.cs | 159 - lib/statistics/Corr.cs | 163 - lib/statistics/Covar.cs | 142 - lib/statistics/Curvature.cs | 199 - lib/statistics/Entropy.cs | 145 - lib/statistics/Granger.cs | 272 - lib/statistics/Hurst.cs | 193 - lib/statistics/Kendall.cs | 182 - lib/statistics/Kurtosis.cs | 154 - lib/statistics/Max.cs | 160 - lib/statistics/Median.cs | 157 - lib/statistics/Min.cs | 158 - lib/statistics/Mode.cs | 162 - lib/statistics/Percentile.cs | 171 - lib/statistics/Skew.cs | 153 - lib/statistics/Slope.cs | 199 - lib/statistics/Spearman.cs | 224 - lib/statistics/Stddev.cs | 143 - lib/statistics/Theil.cs | 167 - lib/statistics/Tsf.cs | 185 - lib/statistics/Variance.cs | 142 - lib/statistics/Zscore.cs | 140 - lib/statistics/_list.md | 26 - lib/volatility/Adr.cs | 82 - lib/volatility/Ap.cs | 119 - lib/volatility/Atr.cs | 132 - lib/volatility/Atrp.cs | 84 - lib/volatility/Atrs.cs | 158 - lib/volatility/Bband.cs | 142 - lib/volatility/Ccv.cs | 129 - lib/volatility/Ce.cs | 156 - lib/volatility/Cv.cs | 137 - lib/volatility/Cvi.cs | 118 - lib/volatility/Dchn.cs | 100 - lib/volatility/Ewma.cs | 140 - lib/volatility/Fcb.cs | 158 - lib/volatility/Gkv.cs | 126 - lib/volatility/Hlv.cs | 129 - lib/volatility/Hv.cs | 169 - lib/volatility/Jvolty.cs | 218 - lib/volatility/Natr.cs | 94 - lib/volatility/Pch.cs | 102 - lib/volatility/Pv.cs | 93 - lib/volatility/Rsv.cs | 93 - lib/volatility/Rv.cs | 152 - lib/volatility/Rvi.cs | 133 - lib/volatility/Sv.cs | 105 - lib/volatility/Tr.cs | 101 - lib/volatility/Ui.cs | 113 - lib/volatility/Vc.cs | 163 - lib/volatility/Vov.cs | 130 - lib/volatility/Vr.cs | 134 - lib/volatility/Vs.cs | 154 - lib/volatility/Yzv.cs | 113 - lib/volatility/_list.md | 38 - lib/volume/Adl.cs | 112 - lib/volume/Adosc.cs | 137 - lib/volume/Aobv.cs | 132 - lib/volume/Cmf.cs | 128 - lib/volume/Eom.cs | 131 - lib/volume/Kvo.cs | 140 - lib/volume/Mfi.cs | 140 - lib/volume/Nvi.cs | 113 - lib/volume/Obv.cs | 116 - lib/volume/Pvi.cs | 112 - lib/volume/Pvo.cs | 110 - lib/volume/Pvol.cs | 107 - lib/volume/Pvr.cs | 108 - lib/volume/Pvt.cs | 104 - lib/volume/Tvi.cs | 111 - lib/volume/Vf.cs | 109 - lib/volume/Vp.cs | 104 - lib/volume/Vwap.cs | 92 - lib/volume/Vwma.cs | 91 - lib/volume/_list.md | 22 - notebooks/Htit.dib | 198 - notebooks/Skender.dib | 45 - notebooks/Tulip.dib | 28 - notebooks/casting.dib | 919 - notebooks/charting.dib | 82 - notebooks/core.dib | 68 - notebooks/ema.dib | 63 - notebooks/jma.dib | 98 - notebooks/means.dib | 28 - notebooks/talib.dib | 29 - notebooks/test.dib | 35 - notebooks/trady.dib | 25 - notebooks/validation.dib | 43 - quantower/Averages/AfirmaIndicator.cs | 80 - quantower/Averages/AlmaIndicator.cs | 74 - quantower/Averages/DemaIndicator.cs | 68 - quantower/Averages/DsmaIndicator.cs | 72 - quantower/Averages/DwmaIndicator.cs | 68 - quantower/Averages/EmaIndicator.cs | 70 - quantower/Averages/EpmaIndicator.cs | 68 - quantower/Averages/FramaIndicator.cs | 68 - quantower/Averages/FwmaIndicator.cs | 68 - quantower/Averages/GmaIndicator.cs | 68 - quantower/Averages/HmaIndicator.cs | 68 - quantower/Averages/HtitIndicator.cs | 65 - quantower/Averages/HwmaIndicator.cs | 84 - quantower/Averages/JmaIndicator.cs | 74 - quantower/Averages/KamaIndicator.cs | 74 - quantower/Averages/LtmaIndicator.cs | 68 - quantower/Averages/MaafIndicator.cs | 71 - quantower/Averages/MamaIndicator.cs | 77 - quantower/Averages/MgdiIndicator.cs | 71 - quantower/Averages/MmaIndicator.cs | 68 - quantower/Averages/PwmaIndicator.cs | 68 - quantower/Averages/RemaIndicator.cs | 71 - quantower/Averages/RmaIndicator.cs | 68 - quantower/Averages/SinemaIndicator.cs | 68 - quantower/Averages/SmaIndicator.cs | 71 - quantower/Averages/SmmaIndicator.cs | 68 - quantower/Averages/T3Indicator.cs | 74 - quantower/Averages/TemaIndicator.cs | 68 - quantower/Averages/TrimaIndicator.cs | 68 - quantower/Averages/VidyaIndicator.cs | 74 - quantower/Averages/WmaIndicator.cs | 69 - quantower/Averages/ZlemaIndicator.cs | 71 - quantower/Averages/_Averages.csproj | 30 - quantower/Experiments/ConvolutionIndicator.cs | 97 - quantower/Experiments/FlowIndicator.cs | 83 - quantower/Experiments/QemaIndicator.cs | 77 - quantower/Experiments/TestIndicator.cs | 63 - quantower/Experiments/_Experiments.csproj | 30 - quantower/IndicatorExtensions.cs | 219 - quantower/Momentum/AdxIndicator.cs | 53 - quantower/Momentum/AdxrIndicator.cs | 55 - quantower/Momentum/ApoIndicator.cs | 71 - quantower/Momentum/DmiIndicator.cs | 59 - quantower/Momentum/DmxIndicator.cs | 68 - quantower/Momentum/DpoIndicator.cs | 67 - quantower/Momentum/MacdIndicator.cs | 146 - quantower/Momentum/MomIndicator.cs | 67 - quantower/Momentum/PmoIndicator.cs | 70 - quantower/Momentum/PoIndicator.cs | 75 - quantower/Momentum/PpoIndicator.cs | 75 - quantower/Momentum/RocIndicator.cs | 76 - quantower/Momentum/TrixIndicator.cs | 67 - quantower/Momentum/VelIndicator.cs | 82 - quantower/Momentum/VortexIndicator.cs | 71 - quantower/Momentum/_Momentum.csproj | 30 - quantower/Oscillators/CtiIndicator.cs | 71 - quantower/Oscillators/RsiIndicator.cs | 67 - quantower/Oscillators/RsxIndicator.cs | 67 - quantower/Oscillators/_Oscillators.csproj | 30 - quantower/Statistics/CurvatureIndicator.cs | 63 - quantower/Statistics/EntropyIndicator.cs | 57 - quantower/Statistics/KurtosisIndicator.cs | 58 - quantower/Statistics/MaxIndicator.cs | 61 - quantower/Statistics/MedianIndicator.cs | 58 - quantower/Statistics/MinIndicator.cs | 61 - quantower/Statistics/ModeIndicator.cs | 58 - quantower/Statistics/PercentileIndicator.cs | 61 - quantower/Statistics/SkewIndicator.cs | 58 - quantower/Statistics/SlopeIndicator.cs | 82 - quantower/Statistics/StddevIndicator.cs | 61 - quantower/Statistics/VarianceIndicator.cs | 61 - quantower/Statistics/ZscoreIndicator.cs | 58 - quantower/Statistics/_Statistics.csproj | 30 - quantower/Volatility/AtrIndicator.cs | 53 - quantower/Volatility/CmoIndicator.cs | 71 - quantower/Volatility/CviIndicator.cs | 54 - quantower/Volatility/HistoricalIndicator.cs | 44 - quantower/Volatility/JbandsIndicator.cs | 67 - quantower/Volatility/JvoltyIndicator.cs | 57 - quantower/Volatility/RealizedIndicator.cs | 44 - quantower/Volatility/RviIndicator.cs | 41 - quantower/Volatility/_Volatility.csproj | 30 - quantower/Volume/ObvIndicator.cs | 51 - quantower/Volume/_Volume.csproj | 30 - tests/QuanTAlib.Tests/CsvFeedTests.cs | 254 + tests/QuanTAlib.Tests/GBMTests.cs | 283 + tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj | 36 + tests/QuanTAlib.Tests/SimdExtensionsTests.cs | 249 + tests/QuanTAlib.Tests/TBarSeriesTests.cs | 58 + tests/QuanTAlib.Tests/TBarTests.cs | 64 + tests/QuanTAlib.Tests/TSeriesTests.cs | 49 + tests/QuanTAlib.Tests/TValueTests.cs | 51 + tests/QuanTAlib.Tests/daily_IBM.csv | 101 + 594 files changed, 117007 insertions(+), 80111 deletions(-) create mode 100644 .github/copilot-instructions.md.backup delete mode 100644 Tests/Tests.csproj delete mode 100644 Tests/UpdateTestBase.cs delete mode 100644 Tests/test_Trady.cs delete mode 100644 Tests/test_Tulip.cs delete mode 100644 Tests/test_core.cs delete mode 100644 Tests/test_eventing.cs delete mode 100644 Tests/test_iTBar.cs delete mode 100644 Tests/test_quantower.cs delete mode 100644 Tests/test_skender.stock.cs delete mode 100644 Tests/test_talib.cs delete mode 100644 Tests/test_updates_averages.cs delete mode 100644 Tests/test_updates_errors.cs delete mode 100644 Tests/test_updates_momentum.cs delete mode 100644 Tests/test_updates_oscillators.cs delete mode 100644 Tests/test_updates_statistics.cs delete mode 100644 Tests/test_updates_volatility.cs delete mode 100644 Tests/test_updates_volume.cs delete mode 100644 build.sh delete mode 100644 docs/.nojekyll delete mode 100644 docs/.playground/mermaidtest.md delete mode 100644 docs/Progress.md delete mode 100644 docs/_sidebar.md delete mode 100644 docs/essays/realtime.md delete mode 100644 docs/img/dotpeek.png delete mode 100644 docs/img/emaweights.svg delete mode 100644 docs/img/quotes.gif delete mode 100644 docs/img/structure.md delete mode 100644 docs/index.html delete mode 100644 docs/indicators/averages/afirma/afirma.md delete mode 100644 docs/indicators/averages/afirma/analysis.md delete mode 100644 docs/indicators/averages/afirma/calc.md delete mode 100644 docs/indicators/averages/afirma/charts.dib delete mode 100644 docs/indicators/averages/afirma/charts.md delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_B.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_HF.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Market.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg delete mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_White.svg delete mode 100644 docs/indicators/averages/alma/alma.md delete mode 100644 docs/indicators/averages/alma/analysis.md delete mode 100644 docs/indicators/averages/alma/calc.md delete mode 100644 docs/indicators/averages/alma/charts.dib delete mode 100644 docs/indicators/averages/alma/charts.md delete mode 100644 docs/indicators/averages/alma/img/ALMA10_B.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Chirp.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Complex.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Gauss.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_HF.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Impulse.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Market.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Sine.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_SineG.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Spike.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_Triangle.svg delete mode 100644 docs/indicators/averages/alma/img/ALMA10_White.svg delete mode 100644 docs/indicators/averages/convolution/convolution.md delete mode 100644 docs/indicators/averages/dema/analysis.md delete mode 100644 docs/indicators/averages/dema/calc.md delete mode 100644 docs/indicators/averages/dema/charts.dib delete mode 100644 docs/indicators/averages/dema/charts.md delete mode 100644 docs/indicators/averages/dema/dema.md delete mode 100644 docs/indicators/averages/dema/img/DEMA10_B.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Chirp.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Complex.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Gauss.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_HF.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Impulse.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Market.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Sine.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_SineG.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Spike.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_Triangle.svg delete mode 100644 docs/indicators/averages/dema/img/DEMA10_White.svg delete mode 100644 docs/indicators/averages/dsma/analysis.md delete mode 100644 docs/indicators/averages/dsma/calc.md delete mode 100644 docs/indicators/averages/dsma/charts.dib delete mode 100644 docs/indicators/averages/dsma/charts.md delete mode 100644 docs/indicators/averages/dsma/dsma.md delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_B.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Chirp.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Complex.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Gauss.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_HF.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Impulse.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Market.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Sine.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_SineG.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Spike.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_Triangle.svg delete mode 100644 docs/indicators/averages/dsma/img/DSMA10_White.svg delete mode 100644 docs/indicators/averages/dwma/analysis.md delete mode 100644 docs/indicators/averages/dwma/calc.md delete mode 100644 docs/indicators/averages/dwma/charts.dib delete mode 100644 docs/indicators/averages/dwma/charts.md delete mode 100644 docs/indicators/averages/dwma/dwma.md delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_B.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Chirp.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Complex.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Gauss.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_HF.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Impulse.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Market.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Sine.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_SineG.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Spike.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_Triangle.svg delete mode 100644 docs/indicators/averages/dwma/img/DWMA10_White.svg delete mode 100644 docs/indicators/averages/ema/analysis.md delete mode 100644 docs/indicators/averages/ema/calc.md delete mode 100644 docs/indicators/averages/ema/calculation.md delete mode 100644 docs/indicators/averages/ema/charts.dib delete mode 100644 docs/indicators/averages/ema/charts.md delete mode 100644 docs/indicators/averages/ema/ema.md delete mode 100644 docs/indicators/averages/ema/img/EMA10_B.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Chirp.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Complex.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Gauss.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_HF.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Impulse.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Market.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Sine.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_SineG.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Spike.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_Triangle.svg delete mode 100644 docs/indicators/averages/ema/img/EMA10_White.svg delete mode 100644 docs/indicators/averages/ema/quality.md delete mode 100644 docs/indicators/averages/epma/epma.md delete mode 100644 docs/indicators/averages/frama/frama.md delete mode 100644 docs/indicators/averages/fwma/fwma.md delete mode 100644 docs/indicators/averages/gma/gma.md delete mode 100644 docs/indicators/averages/hma/hma.md delete mode 100644 docs/indicators/averages/htit/htit.md delete mode 100644 docs/indicators/averages/hwma/hwma.md delete mode 100644 docs/indicators/averages/jma/calc.md delete mode 100644 docs/indicators/averages/jma/jma.md delete mode 100644 docs/indicators/averages/kama/kama.md delete mode 100644 docs/indicators/averages/ltma/ltma.md delete mode 100644 docs/indicators/averages/maaf/maaf.md delete mode 100644 docs/indicators/averages/mama/mama.md delete mode 100644 docs/indicators/averages/mgdi/mgdi.md delete mode 100644 docs/indicators/averages/mma/mma.md delete mode 100644 docs/indicators/averages/pwma/pwma.md delete mode 100644 docs/indicators/averages/qema/qema.md delete mode 100644 docs/indicators/averages/rema/rema.md delete mode 100644 docs/indicators/averages/rma/rma.md delete mode 100644 docs/indicators/averages/sinema/sinema.md delete mode 100644 docs/indicators/averages/sma/calc.md delete mode 100644 docs/indicators/averages/sma/charts.dib delete mode 100644 docs/indicators/averages/sma/charts.md delete mode 100644 docs/indicators/averages/sma/img/SMA10_B.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Chirp.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Complex.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Gauss.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_HF.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Impulse.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Market.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Sine.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_SineG.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Spike.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_Triangle.svg delete mode 100644 docs/indicators/averages/sma/img/SMA10_White.svg delete mode 100644 docs/indicators/averages/sma/sma.md delete mode 100644 docs/indicators/averages/smma/smma.md delete mode 100644 docs/indicators/averages/t3/t3.md delete mode 100644 docs/indicators/averages/tema/analysis.md delete mode 100644 docs/indicators/averages/tema/calc.md delete mode 100644 docs/indicators/averages/tema/charts.dib delete mode 100644 docs/indicators/averages/tema/charts.md delete mode 100644 docs/indicators/averages/tema/img/TEMA10_B.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Chirp.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_ChirpG.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Complex.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Gauss.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_HF.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Impulse.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Market.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Sine.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_SineG.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Spike.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_Triangle.svg delete mode 100644 docs/indicators/averages/tema/img/TEMA10_White.svg delete mode 100644 docs/indicators/averages/tema/tema.md delete mode 100644 docs/indicators/averages/trima/trima.md delete mode 100644 docs/indicators/averages/vidya/vidya.md delete mode 100644 docs/indicators/averages/wma/wma.md delete mode 100644 docs/indicators/averages/zlema/zlema.md delete mode 100644 docs/indicators/indicators.md delete mode 100644 docs/indicators/momentum/adx/description.md delete mode 100644 docs/indicators/momentum/adxr/description.md delete mode 100644 docs/indicators/momentum/apo/description.md delete mode 100644 docs/indicators/momentum/dmi/description.md delete mode 100644 docs/indicators/momentum/dmx/description.md delete mode 100644 docs/indicators/momentum/dpo/description.md delete mode 100644 docs/indicators/momentum/mom/description.md delete mode 100644 docs/indicators/momentum/pmo/description.md delete mode 100644 docs/indicators/momentum/po/description.md delete mode 100644 docs/indicators/momentum/ppo/description.md delete mode 100644 docs/indicators/momentum/prs/description.md delete mode 100644 docs/indicators/momentum/roc/description.md delete mode 100644 docs/indicators/momentum/trix/description.md delete mode 100644 docs/indicators/momentum/tsi/description.md delete mode 100644 docs/indicators/momentum/vel/description.md delete mode 100644 docs/indicators/momentum/vortex/description.md delete mode 100644 docs/indicators/oscillators/ac/ac.md delete mode 100644 docs/indicators/oscillators/ao/ao.md delete mode 100644 docs/indicators/oscillators/aroon/aroon.md delete mode 100644 docs/indicators/oscillators/bop/bop.md delete mode 100644 docs/indicators/oscillators/cci/cci.md delete mode 100644 docs/indicators/oscillators/cfo/cfo.md delete mode 100644 docs/indicators/oscillators/cmo/cmo.md delete mode 100644 docs/indicators/oscillators/rsi/rsi.md delete mode 100644 docs/indicators/oscillators/rsx/rsx.md delete mode 100644 docs/indicators/statistics/curvature/curvature.md delete mode 100644 docs/indicators/statistics/entropy/entropy.md delete mode 100644 docs/indicators/statistics/kurtosis/kurtosis.md delete mode 100644 docs/indicators/statistics/list.md delete mode 100644 docs/indicators/statistics/max/max.md delete mode 100644 docs/indicators/statistics/median/median.md delete mode 100644 docs/indicators/statistics/min/min.md delete mode 100644 docs/indicators/statistics/mode/mode.md delete mode 100644 docs/indicators/statistics/percentile/percentile.md delete mode 100644 docs/indicators/statistics/skew/skew.md delete mode 100644 docs/indicators/statistics/slope/slope.md delete mode 100644 docs/indicators/statistics/stddev/stddev.md delete mode 100644 docs/indicators/statistics/variance/variance.md delete mode 100644 docs/indicators/statistics/zscore/zscore.md delete mode 100644 docs/indicators/volatility/atr/atr.md delete mode 100644 docs/indicators/volatility/hv/hv.md delete mode 100644 docs/indicators/volatility/jvolty/jvolty.md delete mode 100644 docs/indicators/volatility/rv/rv.md delete mode 100644 docs/indicators/volatility/rvi/calc.md delete mode 100644 docs/indicators/volatility/rvi/rvi.md delete mode 100644 docs/indicators/volatility/tr/tr.md delete mode 100644 docs/indicators/volatility/ui/ui.md delete mode 100644 docs/indicators/volatility/vc/vc.md delete mode 100644 docs/indicators/volatility/vov/vov.md delete mode 100644 docs/indicators/volatility/vr/vr.md delete mode 100644 docs/indicators/volatility/vs/vs.md delete mode 100644 docs/indicators/volume/adl/adl.md delete mode 100644 docs/indicators/volume/adosc/adosc.md delete mode 100644 docs/indicators/volume/aobv/aobv.md delete mode 100644 docs/indicators/volume/cmf/cmf.md delete mode 100644 docs/indicators/volume/eom/eom.md delete mode 100644 docs/indicators/volume/kvo/kvo.md delete mode 100644 docs/indicators/volume/mfi/mfi.md delete mode 100644 docs/indicators/volume/nvi/nvi.md delete mode 100644 docs/indicators/volume/obv/obv.md delete mode 100644 docs/indicators/volume/pvi/pvi.md delete mode 100644 docs/indicators/volume/pvo/pvo.md delete mode 100644 docs/indicators/volume/pvol/pvol.md delete mode 100644 docs/indicators/volume/pvr/pvr.md delete mode 100644 docs/indicators/volume/pvt/pvt.md delete mode 100644 docs/indicators/volume/tvi/tvi.md delete mode 100644 docs/readme.md delete mode 100644 docs/setup/dotpeek.md delete mode 100644 docs/setup/quantower.md delete mode 100644 docs/setup/vscode.md create mode 100644 ilspy/TradingPlatform.BusinessLayer.cs delete mode 100644 lib/_list.md delete mode 100644 lib/averages/Afirma.cs delete mode 100644 lib/averages/Alma.cs delete mode 100644 lib/averages/Convolution.cs delete mode 100644 lib/averages/Dema.cs delete mode 100644 lib/averages/Dsma.cs delete mode 100644 lib/averages/Dwma.cs delete mode 100644 lib/averages/Ema.cs delete mode 100644 lib/averages/Epma.cs delete mode 100644 lib/averages/Frama.cs delete mode 100644 lib/averages/Fwma.cs delete mode 100644 lib/averages/Gma.cs delete mode 100644 lib/averages/Hma.cs delete mode 100644 lib/averages/Htit.cs delete mode 100644 lib/averages/Hwma.cs delete mode 100644 lib/averages/Jma.cs delete mode 100644 lib/averages/Kama.cs delete mode 100644 lib/averages/Ltma.cs delete mode 100644 lib/averages/Maaf.cs delete mode 100644 lib/averages/Mama.cs delete mode 100644 lib/averages/Mgdi.cs delete mode 100644 lib/averages/Mma.cs delete mode 100644 lib/averages/Pwma.cs delete mode 100644 lib/averages/Qema.cs delete mode 100644 lib/averages/Rema.cs delete mode 100644 lib/averages/Rma.cs delete mode 100644 lib/averages/Sinema.cs delete mode 100644 lib/averages/Sma.cs delete mode 100644 lib/averages/Smma.cs delete mode 100644 lib/averages/T3.cs delete mode 100644 lib/averages/Tema.cs delete mode 100644 lib/averages/Trima.cs delete mode 100644 lib/averages/Vidya.cs delete mode 100644 lib/averages/Wma.cs delete mode 100644 lib/averages/Zlema.cs delete mode 100644 lib/averages/_list.md delete mode 100644 lib/class_types.md delete mode 100644 lib/core/AbstractBarBase.cs create mode 100644 lib/core/SimdExtensions.cs delete mode 100644 lib/core/abstractBase.cs delete mode 100644 lib/core/circularbuffer.cs delete mode 100644 lib/core/formatters.cs delete mode 100644 lib/errors/Huber.cs delete mode 100644 lib/errors/Mae.cs delete mode 100644 lib/errors/Mapd.cs delete mode 100644 lib/errors/Mape.cs delete mode 100644 lib/errors/Mase.cs delete mode 100644 lib/errors/Mda.cs delete mode 100644 lib/errors/Me.cs delete mode 100644 lib/errors/Mpe.cs delete mode 100644 lib/errors/Mse.cs delete mode 100644 lib/errors/Msle.cs delete mode 100644 lib/errors/Rae.cs delete mode 100644 lib/errors/Rmse.cs delete mode 100644 lib/errors/Rmsle.cs delete mode 100644 lib/errors/Rse.cs delete mode 100644 lib/errors/Rsquared.cs delete mode 100644 lib/errors/Smape.cs delete mode 100644 lib/errors/_list.md create mode 100644 lib/feeds/CsvFeed.cs delete mode 100644 lib/feeds/GbmFeed.cs create mode 100644 lib/feeds/IFeed.cs create mode 100644 lib/feeds/gbm.cs delete mode 100644 lib/momentum/Adx.cs delete mode 100644 lib/momentum/Adxr.cs delete mode 100644 lib/momentum/Apo.cs delete mode 100644 lib/momentum/Dmi.cs delete mode 100644 lib/momentum/Dmx.cs delete mode 100644 lib/momentum/Dpo.cs delete mode 100644 lib/momentum/Macd.cs delete mode 100644 lib/momentum/Mom.cs delete mode 100644 lib/momentum/Pmo.cs delete mode 100644 lib/momentum/Po.cs delete mode 100644 lib/momentum/Ppo.cs delete mode 100644 lib/momentum/Prs.cs delete mode 100644 lib/momentum/Roc.cs delete mode 100644 lib/momentum/Trix.cs delete mode 100644 lib/momentum/Vel.cs delete mode 100644 lib/momentum/Vortex.cs delete mode 100644 lib/momentum/_list.md delete mode 100644 lib/oscillators/Ac.cs delete mode 100644 lib/oscillators/Ao.cs delete mode 100644 lib/oscillators/Aroon.cs delete mode 100644 lib/oscillators/Bop.cs delete mode 100644 lib/oscillators/Cci.cs delete mode 100644 lib/oscillators/Cfo.cs delete mode 100644 lib/oscillators/Chop.cs delete mode 100644 lib/oscillators/Cmo.cs delete mode 100644 lib/oscillators/Cog.cs delete mode 100644 lib/oscillators/Coppock.cs delete mode 100644 lib/oscillators/Crsi.cs delete mode 100644 lib/oscillators/Cti.cs delete mode 100644 lib/oscillators/Dosc.cs delete mode 100644 lib/oscillators/Efi.cs delete mode 100644 lib/oscillators/Fisher.cs delete mode 100644 lib/oscillators/Rsi.cs delete mode 100644 lib/oscillators/Rsx.cs delete mode 100644 lib/oscillators/Smi.cs delete mode 100644 lib/oscillators/Srsi.cs delete mode 100644 lib/oscillators/Stc.cs delete mode 100644 lib/oscillators/Stoch.cs delete mode 100644 lib/oscillators/Tsi.cs delete mode 100644 lib/oscillators/Uo.cs delete mode 100644 lib/oscillators/Willr.cs delete mode 100644 lib/oscillators/_list.md delete mode 100644 lib/patterns/_list.md delete mode 100644 lib/statistics/Beta.cs delete mode 100644 lib/statistics/Corr.cs delete mode 100644 lib/statistics/Covar.cs delete mode 100644 lib/statistics/Curvature.cs delete mode 100644 lib/statistics/Entropy.cs delete mode 100644 lib/statistics/Granger.cs delete mode 100644 lib/statistics/Hurst.cs delete mode 100644 lib/statistics/Kendall.cs delete mode 100644 lib/statistics/Kurtosis.cs delete mode 100644 lib/statistics/Max.cs delete mode 100644 lib/statistics/Median.cs delete mode 100644 lib/statistics/Min.cs delete mode 100644 lib/statistics/Mode.cs delete mode 100644 lib/statistics/Percentile.cs delete mode 100644 lib/statistics/Skew.cs delete mode 100644 lib/statistics/Slope.cs delete mode 100644 lib/statistics/Spearman.cs delete mode 100644 lib/statistics/Stddev.cs delete mode 100644 lib/statistics/Theil.cs delete mode 100644 lib/statistics/Tsf.cs delete mode 100644 lib/statistics/Variance.cs delete mode 100644 lib/statistics/Zscore.cs delete mode 100644 lib/statistics/_list.md delete mode 100644 lib/volatility/Adr.cs delete mode 100644 lib/volatility/Ap.cs delete mode 100644 lib/volatility/Atr.cs delete mode 100644 lib/volatility/Atrp.cs delete mode 100644 lib/volatility/Atrs.cs delete mode 100644 lib/volatility/Bband.cs delete mode 100644 lib/volatility/Ccv.cs delete mode 100644 lib/volatility/Ce.cs delete mode 100644 lib/volatility/Cv.cs delete mode 100644 lib/volatility/Cvi.cs delete mode 100644 lib/volatility/Dchn.cs delete mode 100644 lib/volatility/Ewma.cs delete mode 100644 lib/volatility/Fcb.cs delete mode 100644 lib/volatility/Gkv.cs delete mode 100644 lib/volatility/Hlv.cs delete mode 100644 lib/volatility/Hv.cs delete mode 100644 lib/volatility/Jvolty.cs delete mode 100644 lib/volatility/Natr.cs delete mode 100644 lib/volatility/Pch.cs delete mode 100644 lib/volatility/Pv.cs delete mode 100644 lib/volatility/Rsv.cs delete mode 100644 lib/volatility/Rv.cs delete mode 100644 lib/volatility/Rvi.cs delete mode 100644 lib/volatility/Sv.cs delete mode 100644 lib/volatility/Tr.cs delete mode 100644 lib/volatility/Ui.cs delete mode 100644 lib/volatility/Vc.cs delete mode 100644 lib/volatility/Vov.cs delete mode 100644 lib/volatility/Vr.cs delete mode 100644 lib/volatility/Vs.cs delete mode 100644 lib/volatility/Yzv.cs delete mode 100644 lib/volatility/_list.md delete mode 100644 lib/volume/Adl.cs delete mode 100644 lib/volume/Adosc.cs delete mode 100644 lib/volume/Aobv.cs delete mode 100644 lib/volume/Cmf.cs delete mode 100644 lib/volume/Eom.cs delete mode 100644 lib/volume/Kvo.cs delete mode 100644 lib/volume/Mfi.cs delete mode 100644 lib/volume/Nvi.cs delete mode 100644 lib/volume/Obv.cs delete mode 100644 lib/volume/Pvi.cs delete mode 100644 lib/volume/Pvo.cs delete mode 100644 lib/volume/Pvol.cs delete mode 100644 lib/volume/Pvr.cs delete mode 100644 lib/volume/Pvt.cs delete mode 100644 lib/volume/Tvi.cs delete mode 100644 lib/volume/Vf.cs delete mode 100644 lib/volume/Vp.cs delete mode 100644 lib/volume/Vwap.cs delete mode 100644 lib/volume/Vwma.cs delete mode 100644 lib/volume/_list.md delete mode 100644 notebooks/Htit.dib delete mode 100644 notebooks/Skender.dib delete mode 100644 notebooks/Tulip.dib delete mode 100644 notebooks/casting.dib delete mode 100644 notebooks/charting.dib delete mode 100644 notebooks/core.dib delete mode 100644 notebooks/ema.dib delete mode 100644 notebooks/jma.dib delete mode 100644 notebooks/means.dib delete mode 100644 notebooks/talib.dib delete mode 100644 notebooks/test.dib delete mode 100644 notebooks/trady.dib delete mode 100644 notebooks/validation.dib delete mode 100644 quantower/Averages/AfirmaIndicator.cs delete mode 100644 quantower/Averages/AlmaIndicator.cs delete mode 100644 quantower/Averages/DemaIndicator.cs delete mode 100644 quantower/Averages/DsmaIndicator.cs delete mode 100644 quantower/Averages/DwmaIndicator.cs delete mode 100644 quantower/Averages/EmaIndicator.cs delete mode 100644 quantower/Averages/EpmaIndicator.cs delete mode 100644 quantower/Averages/FramaIndicator.cs delete mode 100644 quantower/Averages/FwmaIndicator.cs delete mode 100644 quantower/Averages/GmaIndicator.cs delete mode 100644 quantower/Averages/HmaIndicator.cs delete mode 100644 quantower/Averages/HtitIndicator.cs delete mode 100644 quantower/Averages/HwmaIndicator.cs delete mode 100644 quantower/Averages/JmaIndicator.cs delete mode 100644 quantower/Averages/KamaIndicator.cs delete mode 100644 quantower/Averages/LtmaIndicator.cs delete mode 100644 quantower/Averages/MaafIndicator.cs delete mode 100644 quantower/Averages/MamaIndicator.cs delete mode 100644 quantower/Averages/MgdiIndicator.cs delete mode 100644 quantower/Averages/MmaIndicator.cs delete mode 100644 quantower/Averages/PwmaIndicator.cs delete mode 100644 quantower/Averages/RemaIndicator.cs delete mode 100644 quantower/Averages/RmaIndicator.cs delete mode 100644 quantower/Averages/SinemaIndicator.cs delete mode 100644 quantower/Averages/SmaIndicator.cs delete mode 100644 quantower/Averages/SmmaIndicator.cs delete mode 100644 quantower/Averages/T3Indicator.cs delete mode 100644 quantower/Averages/TemaIndicator.cs delete mode 100644 quantower/Averages/TrimaIndicator.cs delete mode 100644 quantower/Averages/VidyaIndicator.cs delete mode 100644 quantower/Averages/WmaIndicator.cs delete mode 100644 quantower/Averages/ZlemaIndicator.cs delete mode 100644 quantower/Averages/_Averages.csproj delete mode 100644 quantower/Experiments/ConvolutionIndicator.cs delete mode 100644 quantower/Experiments/FlowIndicator.cs delete mode 100644 quantower/Experiments/QemaIndicator.cs delete mode 100644 quantower/Experiments/TestIndicator.cs delete mode 100644 quantower/Experiments/_Experiments.csproj delete mode 100644 quantower/IndicatorExtensions.cs delete mode 100644 quantower/Momentum/AdxIndicator.cs delete mode 100644 quantower/Momentum/AdxrIndicator.cs delete mode 100644 quantower/Momentum/ApoIndicator.cs delete mode 100644 quantower/Momentum/DmiIndicator.cs delete mode 100644 quantower/Momentum/DmxIndicator.cs delete mode 100644 quantower/Momentum/DpoIndicator.cs delete mode 100644 quantower/Momentum/MacdIndicator.cs delete mode 100644 quantower/Momentum/MomIndicator.cs delete mode 100644 quantower/Momentum/PmoIndicator.cs delete mode 100644 quantower/Momentum/PoIndicator.cs delete mode 100644 quantower/Momentum/PpoIndicator.cs delete mode 100644 quantower/Momentum/RocIndicator.cs delete mode 100644 quantower/Momentum/TrixIndicator.cs delete mode 100644 quantower/Momentum/VelIndicator.cs delete mode 100644 quantower/Momentum/VortexIndicator.cs delete mode 100644 quantower/Momentum/_Momentum.csproj delete mode 100644 quantower/Oscillators/CtiIndicator.cs delete mode 100644 quantower/Oscillators/RsiIndicator.cs delete mode 100644 quantower/Oscillators/RsxIndicator.cs delete mode 100644 quantower/Oscillators/_Oscillators.csproj delete mode 100644 quantower/Statistics/CurvatureIndicator.cs delete mode 100644 quantower/Statistics/EntropyIndicator.cs delete mode 100644 quantower/Statistics/KurtosisIndicator.cs delete mode 100644 quantower/Statistics/MaxIndicator.cs delete mode 100644 quantower/Statistics/MedianIndicator.cs delete mode 100644 quantower/Statistics/MinIndicator.cs delete mode 100644 quantower/Statistics/ModeIndicator.cs delete mode 100644 quantower/Statistics/PercentileIndicator.cs delete mode 100644 quantower/Statistics/SkewIndicator.cs delete mode 100644 quantower/Statistics/SlopeIndicator.cs delete mode 100644 quantower/Statistics/StddevIndicator.cs delete mode 100644 quantower/Statistics/VarianceIndicator.cs delete mode 100644 quantower/Statistics/ZscoreIndicator.cs delete mode 100644 quantower/Statistics/_Statistics.csproj delete mode 100644 quantower/Volatility/AtrIndicator.cs delete mode 100644 quantower/Volatility/CmoIndicator.cs delete mode 100644 quantower/Volatility/CviIndicator.cs delete mode 100644 quantower/Volatility/HistoricalIndicator.cs delete mode 100644 quantower/Volatility/JbandsIndicator.cs delete mode 100644 quantower/Volatility/JvoltyIndicator.cs delete mode 100644 quantower/Volatility/RealizedIndicator.cs delete mode 100644 quantower/Volatility/RviIndicator.cs delete mode 100644 quantower/Volatility/_Volatility.csproj delete mode 100644 quantower/Volume/ObvIndicator.cs delete mode 100644 quantower/Volume/_Volume.csproj create mode 100644 tests/QuanTAlib.Tests/CsvFeedTests.cs create mode 100644 tests/QuanTAlib.Tests/GBMTests.cs create mode 100644 tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj create mode 100644 tests/QuanTAlib.Tests/SimdExtensionsTests.cs create mode 100644 tests/QuanTAlib.Tests/TBarSeriesTests.cs create mode 100644 tests/QuanTAlib.Tests/TBarTests.cs create mode 100644 tests/QuanTAlib.Tests/TSeriesTests.cs create mode 100644 tests/QuanTAlib.Tests/TValueTests.cs create mode 100644 tests/QuanTAlib.Tests/daily_IBM.csv diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e9345c0b..acf70bec 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,74 +1,91 @@ # QuanTAlib AI Coding Agent Instructions ## Project Overview -QuanTAlib is a high-performance C# library for quantitative technical analysis, targeting .NET 8.0 with real-time streaming data processing. The library provides 50+ technical indicators optimized for sub-millisecond calculations using circular buffers, SIMD operations, and event-driven architecture. +QuanTAlib is a high-performance C# library for quantitative technical analysis targeting .NET 8.0. Provides 50+ technical indicators optimized for sub-millisecond real-time streaming calculations using circular buffers, SIMD operations, and event-driven architecture. Used in production live trading environments. ## Critical Architecture Patterns ### Core Data Flow -All indicators inherit from `AbstractBase` (in `lib/core/abstractBase.cs`) which implements `ITValue`: +All indicators inherit from `AbstractBase` (`lib/core/abstractBase.cs`) implementing `ITValue`: ```csharp // Standard indicator lifecycle: -Input → Calc() → ManageState(isNew) → Calculation() → Process() → Pub event +TValue/TBar Input → Calc() → ManageState(isNew) → Calculation() → Process() → Pub event ``` -**Key insight**: The `isNew` parameter distinguishes between new bars and updates to the last bar. Indicators must support both modes - this is tested extensively in `Tests/test_updates_*.cs`. +**Critical concept**: The `isNew` parameter differentiates: +- `isNew=true`: New bar/candle arrives → increment `_index`, backup all state variables +- `isNew=false`: Update to current bar → restore backed-up state, recalculate with new value + +This dual-mode processing is **essential** for real-time trading where the current bar updates continuously before the next bar starts. Every indicator must handle both modes correctly - validated extensively in `Tests/test_updates_*.cs`. ### Circular Buffer Pattern -`CircularBuffer` (in `lib/core/circularbuffer.cs`) is the foundation for memory-efficient fixed-capacity storage: -- Never grows beyond initial capacity -- O(1) add/access operations -- SIMD-optimized aggregations (Sum, Min, Max, Average) -- **Critical**: Always use `Add(item, isNew)` - the `isNew` flag controls whether to append or update +`CircularBuffer` (`lib/core/circularbuffer.cs`) provides memory-efficient fixed-capacity storage: +- Never grows beyond initial capacity (fixed memory footprint regardless of data volume) +- O(1) add/access operations with wraparound +- SIMD-optimized aggregations (Sum, Min, Max, Average) using `System.Numerics.Vector` +- **Critical**: Always use `Add(item, isNew)` - the `isNew` flag controls append vs update behavior ### State Management in Indicators -Every indicator must implement: +Every indicator **must** implement this pattern to support bar updates: ```csharp protected override void ManageState(bool isNew) { if (isNew) { _index++; - _p_prevValue = _prevValue; // Backup state + _p_prevValue = _prevValue; // Backup state + _p_lastEma = _lastEma; // Backup all stateful variables } else { - _prevValue = _p_prevValue; // Restore state + _prevValue = _p_prevValue; // Restore state + _lastEma = _p_lastEma; // Restore all stateful variables } } ``` -This allows bar updates without corrupting historical calculations. +**Pattern**: Use `_p_` prefix for backup variables (e.g., `_p_lastEma`, `_p_isInit`, `_p_e`). When `isNew=false`, restore ALL stateful variables before recalculating. See `lib/averages/Ema.cs` for reference implementation. ## Development Workflow ### MCP-Orchestrated Process -**Research Gate**: Before implementing non-trivial indicators, use Context7 to retrieve authoritative formulas/references. Embed citation tags in PR descriptions. +**Research Gate**: Before implementing non-trivial indicators, use Context7 MCP to retrieve authoritative formulas/references. Embed citation tags in PR descriptions. -**Decomposition**: Use Sequential-Thinking for complex multi-stage work (SIMD refactors, multi-timeframe logic). +**Decomposition**: Use Sequential-Thinking MCP for complex multi-stage work (SIMD refactors, multi-timeframe logic, performance optimization epics). -**Task Tracking**: Taskmaster holds the canonical task graph. Feature branches follow pattern: `feature/{taskId}-{slug}`. +**Task Tracking**: Taskmaster MCP holds the canonical task graph. Feature branches follow pattern: `feature/{taskId}-{slug}`. Tasks include: feature, performance, documentation with status transitions (not-started → in-progress → done). **Quality Gates**: -1. Formula citation required for non-trivial indicators (Context7 tag) +1. Formula citation required for non-trivial indicators (Context7 tag in PR description) 2. Benchmark data required for performance-related changes -3. Taskmaster task IDs must be referenced in PRs -4. Update `memory-bank/progress.md` after merge when threshold met +3. Taskmaster task IDs must be referenced in PR body with closing keywords +4. Update `memory-bank/progress.md` after merge when threshold met (≥5 feature tasks or perf epic completes) ### Build & Test Commands ```powershell -# Build solution +# Build solution (or use VS Code Task: "build") dotnet build QuanTAlib.sln -# Run all tests -dotnet test --no-build +# Run all tests (or use VS Code Task: "test") +dotnet test --no-build --verbosity:normal # Run with coverage -dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=lcov +dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:CoverletOutput=./lcov.info --no-build -# Build using tasks.json -# Use Run Task: "build" or "test" +# Clean build artifacts +dotnet clean QuanTAlib.sln ``` +**VS Code Tasks**: Use Run Task menu for `build`, `test`, `test with coverage`, `clean` - configured in `.vscode/tasks.json`. + ### Adding a New Indicator -1. **Research**: Get formula/specification (Context7 if needed) -2. **Location**: Place in appropriate `lib/` subdirectory (averages, oscillators, momentum, volatility, volume, statistics) + +1. **Research**: Get formula/specification. For non-trivial indicators, use Context7 to retrieve authoritative references. + +2. **Location**: Place in appropriate `lib/` subdirectory: + - `averages/` - Moving averages (SMA, EMA, JMA, etc.) + - `oscillators/` - RSI, Stochastic, CCI, etc. + - `momentum/` - MACD, ADX, ROC, etc. + - `volatility/` - ATR, Bollinger Bands, volatility measures + - `volume/` - Volume-based indicators + - `statistics/` - Statistical measures, correlations + 3. **Template structure**: ```csharp using System.Runtime.CompilerServices; @@ -77,16 +94,27 @@ namespace QuanTAlib; [SkipLocalsInit] public sealed class MyIndicator : AbstractBase { + private readonly int _period; private CircularBuffer _buffer; - private double _prevValue, _p_prevValue; // State + backup + private double _prevValue, _p_prevValue; // State + backup with _p_ prefix [MethodImpl(MethodImplOptions.AggressiveInlining)] public MyIndicator(int period) { ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); + _period = period; _buffer = new(period); - WarmupPeriod = period; // Set when indicator stabilizes + WarmupPeriod = period; // Set when indicator stabilizes (95% accuracy) Name = $"MyIndicator({period})"; + Init(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override void Init() + { + base.Init(); + _prevValue = 0; + _buffer = new(_period); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -105,118 +133,226 @@ public sealed class MyIndicator : AbstractBase { ManageState(Input.IsNew); _buffer.Add(Input.Value, Input.IsNew); + // Implement calculation logic + double result = _buffer.Average(); // Example using SIMD-optimized operation + _prevValue = result; + + IsHot = _index >= WarmupPeriod; // Mark when indicator reaches accuracy threshold return result; } } ``` -4. **Testing**: Create update test in `Tests/test_updates_*.cs`: +4. **Testing**: Create update test in appropriate `Tests/test_updates_*.cs` file: ```csharp [Fact] public void MyIndicator_Update() { var indicator = new MyIndicator(period: 14); - TestTValueUpdate(indicator, indicator.Calc); + double initialValue = indicator.Calc(new TValue(DateTime.Now, 100.0, IsNew: true)); + + // Apply 100 random updates with isNew=false + for (int i = 0; i < 100; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + + // Final value with same input should equal initial value + double finalValue = indicator.Calc(new TValue(DateTime.Now, 100.0, IsNew: false)); + Assert.Equal(initialValue, finalValue, precision: 8); } ``` +5. **Validation**: Compare against reference implementations (TALib, Trady, Skender) in appropriate test file. + ### Quantower Integration For platform indicators in `quantower/`, create wrapper classes inheriting from Quantower's `Indicator`: +```csharp +public class MyIndicator : Indicator, IWatchlistIndicator +{ + [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] + public int Period { get; set; } = 14; + + private QuanTAlib.MyIndicator? ma; + protected LineSeries? Series; + + protected override void OnInit() + { + ma = new QuanTAlib.MyIndicator(period: Period); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TValue input = this.GetInputValue(args, Source); + TValue result = ma!.Calc(input); + Series!.SetValue(result.Value); + } +} +``` - Use private `lib/` indicator instances -- Map `OnUpdate()` to indicator's `Calc()` method -- Extract output fields (e.g., `ma`, `jmaUp`, `jmaLo`) from indicator state +- Map `OnUpdate()` to indicator's `Calc()` method +- Extract output from indicator state/properties +- Apply `IndicatorExtensions` for styling and painting ## Code Style Requirements ### Performance First -- Use `[MethodImpl(MethodImplOptions.AggressiveInlining)]` for hot paths -- Use `[MethodImpl(MethodImplOptions.AggressiveOptimization)]` for calculation methods -- Apply `[SkipLocalsInit]` to indicator classes -- Prefer SIMD operations in `CircularBuffer` for aggregations -- Minimize allocations in `Calculation()` methods +- Use `[MethodImpl(MethodImplOptions.AggressiveInlining)]` for all public methods and hot paths +- Use `[MethodImpl(MethodImplOptions.AggressiveOptimization)]` for `Calculation()` methods +- Apply `[SkipLocalsInit]` to indicator classes to skip zero-initialization +- Prefer SIMD operations in `CircularBuffer` for aggregations (Sum, Min, Max, Average) +- Minimize allocations in `Calculation()` methods - reuse buffers and avoid LINQ +- Use `sealed` classes when possible for devirtualization ### C# Conventions -- **No inline comments** within methods - code should be self-documenting -- Use XML doc comments for public APIs only -- PascalCase for public members, _camelCase for private fields +- **No inline comments** within methods - code should be self-documenting through clear naming +- Use XML doc comments for public classes/methods only - include purpose, formula description, and source citations +- PascalCase for public members, `_camelCase` for private fields +- `_p_` prefix for backup state variables used in `ManageState()` - Compact code - minimal whitespace between logical blocks -- Latest C# features: `ArgumentOutOfRangeException.ThrowIfLessThan`, pattern matching, etc. +- Latest C# features: `ArgumentOutOfRangeException.ThrowIfLessThan`, pattern matching, collection expressions, etc. +- No namespace imports in individual files - `Directory.Build.props` enables implicit usings -### Project Settings +### Project Settings (Directory.Build.props) - `LangVersion: preview` - use cutting-edge C# features - `AllowUnsafeBlocks: true` - SIMD and unsafe operations permitted -- `Nullable: enable` - strict nullability checking +- `Nullable: enable` - strict nullability checking enforced - Target: `net8.0` +- `DisableImplicitNamespaceImports: true` - explicit namespace control +- Release optimizations: AOT, ReadyToRun, TieredCompilation, trimming enabled ## Key Files & Directories ### Core Library Structure ``` lib/ -├── core/ # AbstractBase, CircularBuffer, TSeries, TBar, TValue -├── averages/ # Moving averages (SMA, EMA, DEMA, TEMA, JMA, etc.) -├── oscillators/ # RSI, Stochastic, Williams %R, CCI, Fisher -├── momentum/ # MACD, ADX, ROC, Vortex -├── volatility/ # ATR, Bollinger Bands, volatility measures -├── volume/ # Volume-based indicators -└── statistics/ # Statistical measures, correlations +├── core/ # AbstractBase, CircularBuffer, TSeries, TBar, TValue, ITValue +├── averages/ # Moving averages: SMA, EMA, DEMA, TEMA, JMA, KAMA, etc. (25+ indicators) +├── oscillators/ # RSI, Stochastic, Williams %R, CCI, Fisher, CTI, etc. +├── momentum/ # MACD, ADX, DMI, ROC, TRIX, Vortex, PMO, etc. +├── volatility/ # ATR, Bollinger Bands, Keltner Channels, volatility measures +├── volume/ # Volume-based indicators (OBV, MFI, etc.) +├── statistics/ # Statistical measures, correlations +└── errors/ # Error metrics: MAE, MSE, RMSE, MAPE, R-squared, etc. ``` ### Critical Reference Files -- `lib/core/abstractBase.cs` - Base class for all indicators -- `lib/core/circularbuffer.cs` - Memory-efficient storage with SIMD -- `Directory.Build.props` - Solution-wide MSBuild properties -- `memory-bank/systemPatterns.md` - Architecture patterns -- `memory-bank/activeContext.md` - Current work focus and MCP policies -- `memory-bank/progress.md` - Completed features and roadmap +- `lib/core/abstractBase.cs` - Base class for all indicators with lifecycle management +- `lib/core/circularbuffer.cs` - Memory-efficient storage with SIMD operations +- `lib/core/TValue.cs` - Immutable record struct for time-value pairs with IsNew/IsHot flags +- `lib/core/TBar.cs` - OHLCV bar data structure +- `Directory.Build.props` - Solution-wide MSBuild properties and optimizations +- `memory-bank/systemPatterns.md` - Architecture patterns and design decisions +- `memory-bank/activeContext.md` - Current work focus, MCP policies, and operational rules +- `memory-bank/progress.md` - Completed features, roadmap, and version history ### Testing Reference -- `Tests/test_updates_*.cs` - Update behavior validation (IsNew handling) +- `Tests/test_updates_*.cs` - Update behavior validation (IsNew handling) - **CRITICAL TESTS** - `Tests/test_quantower.cs` - Quantower integration validation -- `Tests/test_talib.cs`, `test_Trady.cs` - Cross-validation against reference libraries +- `Tests/test_talib.cs` - Cross-validation against TA-Lib reference library +- `Tests/test_Trady.cs` - Cross-validation against Trady reference library +- `Tests/test_skender.stock.cs` - Cross-validation against Skender.Stock.Indicators ## Common Patterns ### Multi-Stage Smoothing -Many indicators (DEMA, TEMA, MACD) use cascaded smoothing: +Many indicators (DEMA, TEMA, MACD) use cascaded smoothing with child indicator instances: ```csharp private readonly Ema _ema1; private readonly Ema _ema2; -_ema1.Calc(Input.Value, Input.IsNew); -_ema2.Calc(_ema1.Value, Input.IsNew); +public MyIndicator(int period) +{ + _ema1 = new Ema(period); + _ema2 = new Ema(period); +} + +protected override double Calculation() +{ + _ema1.Calc(Input.Value, Input.IsNew); + _ema2.Calc(_ema1.Value, Input.IsNew); // Feed output of first into second + return _ema2.Value; +} ``` -### Bar-Based vs Value-Based -- **Value-based**: Accept `TValue`, process single values (most indicators) +### Bar-Based vs Value-Based Indicators +- **Value-based**: Accept `TValue`, process single values (most indicators like SMA, EMA, RSI) - **Bar-based**: Accept `TBar` (OHLCV), process bar data (ATR, Stochastic, volume indicators) Override appropriate `Calc()` method: ```csharp -public override TValue Calc(TBar barInput) { /* ... */ } +// For bar-based indicators +public override TValue Calc(TBar barInput) +{ + BarInput = barInput; + return Process(barInput.Close, barInput.Time, barInput.IsNew); +} ``` ### WarmupPeriod Calculation -Set `WarmupPeriod` to indicate when the indicator reaches 95% accuracy: +Set `WarmupPeriod` to indicate when the indicator reaches 95% accuracy (used for IsHot flag): ```csharp -WarmupPeriod = (int)Math.Ceiling(Math.Log(0.05) / Math.Log(1 - alpha)); +// For exponential smoothing with constant alpha/k +WarmupPeriod = (int)Math.Ceiling(Math.Log(0.05) / Math.Log(1 - k)); + +// For simple period-based indicators +WarmupPeriod = period; + +// For multi-stage indicators +WarmupPeriod = stage1.WarmupPeriod + stage2.WarmupPeriod; +``` + +### Event-Driven Updates +Indicators support pub-sub pattern through `Pub` event: +```csharp +// Publishing side (automatic in AbstractBase.Process()) +Pub?.Invoke(this, new ValueEventArgs(value)); + +// Subscribing side +var ema = new Ema(20); +ema.Pub += (sender, args) => Console.WriteLine($"New EMA value: {args.Tick.Value}"); + +// Or subscribe one indicator to another +var sma = new Sma(10); +var ema = new Ema(sma, period: 20); // EMA automatically subscribes to SMA's Pub event ``` ## Validation Strategy -1. **Update tests**: Verify `isNew=false` behavior converges to `isNew=true` with same final value -2. **Reference comparison**: Validate against TALib, Trady, or Skender implementations -3. **Edge cases**: Test with insufficient data (< period), NaN/Infinity, extreme values -4. **Performance**: Benchmark calculation time - target < 0.5ms per update + +1. **Update tests** (CRITICAL): Verify `isNew=false` behavior converges to `isNew=true` with same final value after 100 random updates. This validates state management correctness. See `Tests/test_updates_*.cs`. + +2. **Reference comparison**: Validate against TALib, Trady, or Skender implementations. Expect high precision match (typically 8+ decimal places). + +3. **Edge cases**: Test with: + - Insufficient data (count < period) + - NaN and Infinity inputs (should propagate last valid value) + - Extreme values (very large/small numbers) + - Zero and negative values where applicable + +4. **Performance**: Benchmark calculation time - target < 0.5ms per update. Use `BenchmarkDotNet` for precise measurements. ## Documentation Requirements -- XML docs on public classes/methods describing purpose, formula, and sources -- Mathematical formulas in doc comments with source citations -- No internal comments - let code structure communicate intent -- Update `memory-bank/progress.md` after significant feature completion + +- XML doc comments on public classes/methods describing: + - Purpose and use case + - Formula/algorithm description + - Source citations (URLs to papers, documentation, books) + - Parameter constraints and validation +- Mathematical formulas in doc comments with proper notation +- No internal code comments - let code structure communicate intent through clear naming +- Update `memory-bank/progress.md` after significant feature completion (threshold: ≥5 feature tasks merged) ## GitVersion & Releases -- Semantic versioning via GitVersion.yml -- Version properties auto-injected: `$(GitVersion_MajorMinorPatch)` -- Commit messages influence version bumps (conventional commits) -- Build creates NuGet package with embedded version metadata + +- Semantic versioning via `GitVersion.yml` +- Version properties auto-injected: `$(GitVersion_MajorMinorPatch)`, `$(GitVersion_AssemblySemVer)` +- Commit messages influence version bumps using conventional commits: + - `+semver: major` or `+semver: breaking` → major bump + - `+semver: minor` or `+semver: feature` → minor bump + - `+semver: patch` or `+semver: fix` → patch bump + - `+semver: none` or `+semver: skip` → no bump +- `main` branch: ContinuousDeployment mode, patch increment +- `dev` branch: ContinuousDelivery mode, pre-release weight 30000 +- Build creates NuGet package with embedded version metadata and source link diff --git a/.github/copilot-instructions.md.backup b/.github/copilot-instructions.md.backup new file mode 100644 index 00000000..8b320b78 --- /dev/null +++ b/.github/copilot-instructions.md.backup @@ -0,0 +1,222 @@ +# QuanTAlib AI Coding Agent Instructions + +## Project Overview +QuanTAlib is a high-performance C# library for quantitative technical analysis, targeting .NET 8.0 with real-time streaming data processing. The library provides 50+ technical indicators optimized for sub-millisecond calculations using circular buffers, SIMD operations, and event-driven architecture. + +## Critical Architecture Patterns + +### Core Data Flow +All indicators inherit from `AbstractBase` (in `lib/core/abstractBase.cs`) which implements `ITValue`: +```csharp +// Standard indicator lifecycle: +Input → Calc() → ManageState(isNew) → Calculation() → Process() → Pub event +``` + +**Key insight**: The `isNew` parameter distinguishes between new bars and updates to the last bar. Indicators must support both modes - this is tested extensively in `Tests/test_updates_*.cs`. + +### Circular Buffer Pattern +`CircularBuffer` (in `lib/core/circularbuffer.cs`) is the foundation for memory-efficient fixed-capacity storage: +- Never grows beyond initial capacity +- O(1) add/access operations +- SIMD-optimized aggregations (Sum, Min, Max, Average) +- **Critical**: Always use `Add(item, isNew)` - the `isNew` flag controls whether to append or update + +### State Management in Indicators +Every indicator must implement: +```csharp +protected override void ManageState(bool isNew) +{ + if (isNew) { + _index++; + _p_prevValue = _prevValue; // Backup state + } else { + _prevValue = _p_prevValue; // Restore state + } +} +``` +This allows bar updates without corrupting historical calculations. + +## Development Workflow + +### MCP-Orchestrated Process +**Research Gate**: Before implementing non-trivial indicators, use Context7 to retrieve authoritative formulas/references. Embed citation tags in PR descriptions. + +**Decomposition**: Use Sequential-Thinking for complex multi-stage work (SIMD refactors, multi-timeframe logic). + +**Task Tracking**: Taskmaster holds the canonical task graph. Feature branches follow pattern: `feature/{taskId}-{slug}`. + +**Quality Gates**: +1. Formula citation required for non-trivial indicators (Context7 tag) +2. Benchmark data required for performance-related changes +3. Taskmaster task IDs must be referenced in PRs +4. Update `memory-bank/progress.md` after merge when threshold met + +### Build & Test Commands +```powershell +# Build solution +dotnet build QuanTAlib.sln + +# Run all tests +dotnet test --no-build + +# Run with coverage +dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=lcov + +# Build using tasks.json +# Use Run Task: "build" or "test" +``` + +### Adding a New Indicator +1. **Research**: Get formula/specification (Context7 if needed) +2. **Location**: Place in appropriate `lib/` subdirectory (averages, oscillators, momentum, volatility, volume, statistics) +3. **Template structure**: +```csharp +using System.Runtime.CompilerServices; +namespace QuanTAlib; + +[SkipLocalsInit] +public sealed class MyIndicator : AbstractBase +{ + private CircularBuffer _buffer; + private double _prevValue, _p_prevValue; // State + backup + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public MyIndicator(int period) + { + ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); + _buffer = new(period); + WarmupPeriod = period; // Set when indicator stabilizes + Name = $"MyIndicator({period})"; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void ManageState(bool isNew) + { + if (isNew) { + _index++; + _p_prevValue = _prevValue; + } else { + _prevValue = _p_prevValue; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + protected override double Calculation() + { + ManageState(Input.IsNew); + _buffer.Add(Input.Value, Input.IsNew); + // Implement calculation logic + return result; + } +} +``` + +4. **Testing**: Create update test in `Tests/test_updates_*.cs`: +```csharp +[Fact] +public void MyIndicator_Update() +{ + var indicator = new MyIndicator(period: 14); + TestTValueUpdate(indicator, indicator.Calc); +} +``` + +### Quantower Integration +For platform indicators in `quantower/`, create wrapper classes inheriting from Quantower's `Indicator`: +- Use private `lib/` indicator instances +- Map `OnUpdate()` to indicator's `Calc()` method +- Extract output fields (e.g., `ma`, `jmaUp`, `jmaLo`) from indicator state + +## Code Style Requirements + +### Performance First +- Use `[MethodImpl(MethodImplOptions.AggressiveInlining)]` for hot paths +- Use `[MethodImpl(MethodImplOptions.AggressiveOptimization)]` for calculation methods +- Apply `[SkipLocalsInit]` to indicator classes +- Prefer SIMD operations in `CircularBuffer` for aggregations +- Minimize allocations in `Calculation()` methods + +### C# Conventions +- **No inline comments** within methods - code should be self-documenting +- Use XML doc comments for public APIs only +- PascalCase for public members, _camelCase for private fields +- Compact code - minimal whitespace between logical blocks +- Latest C# features: `ArgumentOutOfRangeException.ThrowIfLessThan`, pattern matching, etc. + +### Project Settings +- `LangVersion: preview` - use cutting-edge C# features +- `AllowUnsafeBlocks: true` - SIMD and unsafe operations permitted +- `Nullable: enable` - strict nullability checking +- Target: `net8.0` + +## Key Files & Directories + +### Core Library Structure +``` +lib/ +├── core/ # AbstractBase, CircularBuffer, TSeries, TBar, TValue +├── averages/ # Moving averages (SMA, EMA, DEMA, TEMA, JMA, etc.) +├── oscillators/ # RSI, Stochastic, Williams %R, CCI, Fisher +├── momentum/ # MACD, ADX, ROC, Vortex +├── volatility/ # ATR, Bollinger Bands, volatility measures +├── volume/ # Volume-based indicators +└── statistics/ # Statistical measures, correlations +``` + +### Critical Reference Files +- `lib/core/abstractBase.cs` - Base class for all indicators +- `lib/core/circularbuffer.cs` - Memory-efficient storage with SIMD +- `Directory.Build.props` - Solution-wide MSBuild properties +- `memory-bank/systemPatterns.md` - Architecture patterns +- `memory-bank/activeContext.md` - Current work focus and MCP policies +- `memory-bank/progress.md` - Completed features and roadmap + +### Testing Reference +- `Tests/test_updates_*.cs` - Update behavior validation (IsNew handling) +- `Tests/test_quantower.cs` - Quantower integration validation +- `Tests/test_talib.cs`, `test_Trady.cs` - Cross-validation against reference libraries + +## Common Patterns + +### Multi-Stage Smoothing +Many indicators (DEMA, TEMA, MACD) use cascaded smoothing: +```csharp +private readonly Ema _ema1; +private readonly Ema _ema2; + +_ema1.Calc(Input.Value, Input.IsNew); +_ema2.Calc(_ema1.Value, Input.IsNew); +``` + +### Bar-Based vs Value-Based +- **Value-based**: Accept `TValue`, process single values (most indicators) +- **Bar-based**: Accept `TBar` (OHLCV), process bar data (ATR, Stochastic, volume indicators) + +Override appropriate `Calc()` method: +```csharp +public override TValue Calc(TBar barInput) { /* ... */ } +``` + +### WarmupPeriod Calculation +Set `WarmupPeriod` to indicate when the indicator reaches 95% accuracy: +```csharp +WarmupPeriod = (int)Math.Ceiling(Math.Log(0.05) / Math.Log(1 - alpha)); +``` + +## Validation Strategy +1. **Update tests**: Verify `isNew=false` behavior converges to `isNew=true` with same final value +2. **Reference comparison**: Validate against TALib, Trady, or Skender implementations +3. **Edge cases**: Test with insufficient data (< period), NaN/Infinity, extreme values +4. **Performance**: Benchmark calculation time - target < 0.5ms per update + +## Documentation Requirements +- XML docs on public classes/methods describing purpose, formula, and sources +- Mathematical formulas in doc comments with source citations +- No internal comments - let code structure communicate intent +- Update `memory-bank/progress.md` after significant feature completion + +## GitVersion & Releases +- Semantic versioning via GitVersion.yml +- Version properties auto-injected: `$(GitVersion_MajorMinorPatch)` +- Commit messages influence version bumps (conventional commits) +- Build creates NuGet package with embedded version metadata diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 9bf69387..d23a4a35 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,7 @@ { "recommendations": [ + "ms-dotnettools.csdevkit", + "ms-dotnettools.csharp", "bierner.markdown-mermaid" ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 970bdfa4..d656a7dc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,121 @@ { + // ??????????????????????????????????????????????????????????????????? + // GitHub Copilot Settings for QuanTAlib Workspace + // Optimized for high-performance financial library development + // ??????????????????????????????????????????????????????????????????? + + // ????????????????????????????????????????????????????????????????? + // Copilot Core Settings + // ????????????????????????????????????????????????????????????????? + + // Enable Copilot completions (suggestions appear automatically) + "github.copilot.editor.enableAutoCompletions": true, + + // Enable Copilot for all file types + "github.copilot.enable": { + "*": true, + "plaintext": false, + "markdown": true, + "scminput": false + }, + + // Show inline suggestions + "editor.inlineSuggest.enabled": true, + + // Always show the inline suggestion toolbar + "editor.inlineSuggest.showToolbar": "always", + + // ????????????????????????????????????????????????????????????????? + // Copilot Chat Settings (Manual Review Required) + // ????????????????????????????????????????????????????????????????? + + // DO NOT auto-apply chat edits - require manual review for quality control + "chat.editing.autoApply": "off", + + // Confirm before removing edit requests + "chat.editing.confirmEditRequestRemoval": true, + + // Show chat panel on the side + "chat.editor.wordWrap": "on", + + // ????????????????????????????????????????????????????????????????? + // Editor Settings for Productivity + // ????????????????????????????????????????????????????????????????? + + // Enable quick suggestions in all contexts + "editor.quickSuggestions": { + "other": true, + "comments": true, + "strings": true + }, + + // Show suggestions on trigger characters + "editor.suggestOnTriggerCharacters": true, + + // Accept suggestion on commit character (like dot, parenthesis) + "editor.acceptSuggestionOnCommitCharacter": true, + + // Faster suggestion appearance + "editor.quickSuggestionsDelay": 0, + + // Show snippet suggestions with other suggestions + "editor.snippetSuggestions": "inline", + + // Tab key behavior + "editor.tabCompletion": "on", + + // ????????????????????????????????????????????????????????????????? + // C# Specific Settings + // ????????????????????????????????????????????????????????????????? + + "[csharp]": { + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "editor.quickSuggestions": { + "other": true, + "comments": true, + "strings": true + } + }, + + // ????????????????????????????????????????????????????????????????? + // Performance & Quality Control + // ????????????????????????????????????????????????????????????????? + + // Save automatically (helps with Copilot context) + "files.autoSave": "afterDelay", + "files.autoSaveDelay": 1000, + + // Show whitespace (important for performance-critical code) + "editor.renderWhitespace": "boundary", + + // Show inline parameter hints + "editor.inlayHints.enabled": "on", + + // Highlight matching brackets + "editor.bracketPairColorization.enabled": true, + "editor.guides.bracketPairs": true, + + // ????????????????????????????????????????????????????????????????? + // Git Integration + // ????????????????????????????????????????????????????????????????? + + // Auto-fetch git changes + "git.autofetch": true, + + // Confirm before synchronizing + "git.confirmSync": false, + + // Show inline blame + "git.decorations.enabled": true, + + // ????????????????????????????????????????????????????????????????? + // Terminal Settings (Preserved from original) + // ????????????????????????????????????????????????????????????????? + "terminal.integrated.defaultProfile.windows": "PowerShell", "terminal.integrated.profiles.windows": { "PowerShell": { @@ -6,5 +123,68 @@ "icon": "terminal-powershell" } }, - "terminal.integrated.shellIntegration.enabled": true + "terminal.integrated.shellIntegration.enabled": true, + "terminal.integrated.suggest.enabled": true, + + // ????????????????????????????????????????????????????????????????? + // File Exclusions (Reduce Noise) + // ????????????????????????????????????????????????????????????????? + + "files.exclude": { + "**/bin": true, + "**/obj": true, + "**/.vs": true, + "**/node_modules": true, + "**/.git": false + }, + + "search.exclude": { + "**/bin": true, + "**/obj": true, + "**/node_modules": true, + "**/.vs": true, + "**/coverage": true + }, + + // ????????????????????????????????????????????????????????????????? + // .NET Specific Settings + // ????????????????????????????????????????????????????????????????? + + "omnisharp.enableEditorConfigSupport": true, + "omnisharp.enableRoslynAnalyzers": true, + "dotnet.backgroundAnalysis.enabled": true, + + // ????????????????????????????????????????????????????????????????? + // Testing Integration + // ????????????????????????????????????????????????????????????????? + + "dotnet.defaultSolution": "QuanTAlib.sln", + "dotnet.testController.enabled": true, + "dotnet.testExplorer.enabled": true, + "dotnet-test-explorer.autoExpandTree": true, + "dotnet-test-explorer.autoWatch": false, + "dotnet-test-explorer.runAfterBuild": false, + "dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true, + "dotnet.server.useOmnisharp": false, + + "testing.automaticallyOpenPeekView": "never", + "testing.openTesting": "neverOpen", + "testing.automaticallyOpenTestResults": "neverOpen" + + // ??????????????????????????????????????????????????????????????????? + // Keyboard Shortcuts Reference + // ??????????????????????????????????????????????????????????????????? + // Tab - Accept inline suggestion + // Ctrl+? - Accept next word + // Ctrl+Enter - Accept line + // Esc - Dismiss suggestion + // Alt+] - Next suggestion + // Alt+[ - Previous suggestion + // Ctrl+I - Open Copilot Chat + // + // Quality Control Reminders: + // ? Review all Copilot suggestions for optimization patterns + // ? Run tests after accepting: dotnet test + // ? Check performance impact with benchmarks + // ? Validate against reference implementations } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 33d40edd..aa1fd30c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,62 +1,54 @@ { - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/QuanTAlib.sln", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile", - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "test", - "command": "dotnet", - "type": "process", - "args": [ - "test", - "${workspaceFolder}/QuanTAlib.sln", - "--no-build", - "--verbosity:normal" - ], - "problemMatcher": "$msCompile", - "group": { - "kind": "test", - "isDefault": true - }, - "dependsOn": ["build"] - }, - { - "label": "test with coverage", - "command": "dotnet", - "type": "process", - "args": [ - "test", - "${workspaceFolder}/QuanTAlib.sln", - "/p:CollectCoverage=true", - "/p:CoverletOutputFormat=lcov", - "/p:CoverletOutput=./lcov.info", - "--no-build" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "clean", - "command": "dotnet", - "type": "process", - "args": [ - "clean", - "${workspaceFolder}/QuanTAlib.sln" - ], - "problemMatcher": "$msCompile" - } - ] -} \ No newline at end of file + "version": "2.0.0", + "tasks": [ + { + "label": "test-net10", + "command": "dotnet", + "type": "process", + "args": [ + "test", + "${workspaceFolder}/tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj", + "--framework", + "net10.0" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "test-all-frameworks", + "command": "dotnet", + "type": "process", + "args": [ + "test", + "${workspaceFolder}/tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj" + ], + "problemMatcher": "$msCompile", + "group": "test", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/QuanTAlib.sln" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/QuanTAlib.sln b/QuanTAlib.sln index 63971a37..4ae60645 100644 --- a/QuanTAlib.sln +++ b/QuanTAlib.sln @@ -1,85 +1,91 @@ + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.5.2.0 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{9CF47860-2CEA-F379-09D8-9AEF27965D12}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "quantalib", "lib\quantalib.csproj", "{F455234B-2A3C-140A-17C3-683D7820A733}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "quantower", "quantower", "{6CF592EE-4302-E72F-3CB4-AB1D314DD5A8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{B36A84DF-456D-A817-6EDD-3EC3E7F6E11F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Averages", "quantower\Averages\_Averages.csproj", "{F6651413-2F44-2F7B-EBE6-A300E8655AFD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreTypes", "examples\CoreTypes\CoreTypes.csproj", "{8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Experiments", "quantower\Experiments\_Experiments.csproj", "{87051F5D-8006-0241-4339-A1B2D29EA094}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{3A8DF596-E814-FECC-DD4B-D8EF8AAC1A0D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Momentum", "quantower\Momentum\_Momentum.csproj", "{2D6628C9-C059-15E9-F3A0-C50F1BCCADA0}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Oscillators", "quantower\Oscillators\_Oscillators.csproj", "{A95DA667-23DF-4067-A173-E9C7FC430D09}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuanTAlib.Tests", "tests\QuanTAlib.Tests\QuanTAlib.Tests.csproj", "{43CA2584-D4AD-4082-AFF4-68B3D1239221}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Statistics", "quantower\Statistics\_Statistics.csproj", "{556D8C92-E3DD-F64A-53B1-D741A96888F2}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "feeds", "feeds", "{2B942E44-74DA-CD21-D337-7A5E9D347C1B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Volatility", "quantower\Volatility\_Volatility.csproj", "{4FAD1FB1-4696-ABF4-50D9-162F81114A20}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_Volume", "quantower\Volume\_Volume.csproj", "{03C2D1D7-AB94-445B-2127-285A367DC6A6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GbmExample", "examples\feeds\GbmExample.csproj", "{B27145AF-B255-4D6E-827B-3512952FB29C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {908D03EE-717E-7E8C-7EAA-0DF14BA8C45E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {908D03EE-717E-7E8C-7EAA-0DF14BA8C45E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {908D03EE-717E-7E8C-7EAA-0DF14BA8C45E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {908D03EE-717E-7E8C-7EAA-0DF14BA8C45E}.Release|Any CPU.Build.0 = Release|Any CPU - {9CF47860-2CEA-F379-09D8-9AEF27965D12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9CF47860-2CEA-F379-09D8-9AEF27965D12}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9CF47860-2CEA-F379-09D8-9AEF27965D12}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9CF47860-2CEA-F379-09D8-9AEF27965D12}.Release|Any CPU.Build.0 = Release|Any CPU {F455234B-2A3C-140A-17C3-683D7820A733}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F455234B-2A3C-140A-17C3-683D7820A733}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Debug|x64.ActiveCfg = Debug|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Debug|x64.Build.0 = Debug|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Debug|x86.ActiveCfg = Debug|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Debug|x86.Build.0 = Debug|Any CPU {F455234B-2A3C-140A-17C3-683D7820A733}.Release|Any CPU.ActiveCfg = Release|Any CPU {F455234B-2A3C-140A-17C3-683D7820A733}.Release|Any CPU.Build.0 = Release|Any CPU - {F6651413-2F44-2F7B-EBE6-A300E8655AFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F6651413-2F44-2F7B-EBE6-A300E8655AFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F6651413-2F44-2F7B-EBE6-A300E8655AFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F6651413-2F44-2F7B-EBE6-A300E8655AFD}.Release|Any CPU.Build.0 = Release|Any CPU - {87051F5D-8006-0241-4339-A1B2D29EA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {87051F5D-8006-0241-4339-A1B2D29EA094}.Debug|Any CPU.Build.0 = Debug|Any CPU - {87051F5D-8006-0241-4339-A1B2D29EA094}.Release|Any CPU.ActiveCfg = Release|Any CPU - {87051F5D-8006-0241-4339-A1B2D29EA094}.Release|Any CPU.Build.0 = Release|Any CPU - {2D6628C9-C059-15E9-F3A0-C50F1BCCADA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2D6628C9-C059-15E9-F3A0-C50F1BCCADA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2D6628C9-C059-15E9-F3A0-C50F1BCCADA0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2D6628C9-C059-15E9-F3A0-C50F1BCCADA0}.Release|Any CPU.Build.0 = Release|Any CPU - {A95DA667-23DF-4067-A173-E9C7FC430D09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A95DA667-23DF-4067-A173-E9C7FC430D09}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A95DA667-23DF-4067-A173-E9C7FC430D09}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A95DA667-23DF-4067-A173-E9C7FC430D09}.Release|Any CPU.Build.0 = Release|Any CPU - {556D8C92-E3DD-F64A-53B1-D741A96888F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {556D8C92-E3DD-F64A-53B1-D741A96888F2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {556D8C92-E3DD-F64A-53B1-D741A96888F2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {556D8C92-E3DD-F64A-53B1-D741A96888F2}.Release|Any CPU.Build.0 = Release|Any CPU - {4FAD1FB1-4696-ABF4-50D9-162F81114A20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FAD1FB1-4696-ABF4-50D9-162F81114A20}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FAD1FB1-4696-ABF4-50D9-162F81114A20}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FAD1FB1-4696-ABF4-50D9-162F81114A20}.Release|Any CPU.Build.0 = Release|Any CPU - {03C2D1D7-AB94-445B-2127-285A367DC6A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03C2D1D7-AB94-445B-2127-285A367DC6A6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03C2D1D7-AB94-445B-2127-285A367DC6A6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03C2D1D7-AB94-445B-2127-285A367DC6A6}.Release|Any CPU.Build.0 = Release|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Release|x64.ActiveCfg = Release|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Release|x64.Build.0 = Release|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Release|x86.ActiveCfg = Release|Any CPU + {F455234B-2A3C-140A-17C3-683D7820A733}.Release|x86.Build.0 = Release|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Debug|x64.ActiveCfg = Debug|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Debug|x64.Build.0 = Debug|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Debug|x86.ActiveCfg = Debug|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Debug|x86.Build.0 = Debug|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Release|Any CPU.Build.0 = Release|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Release|x64.ActiveCfg = Release|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Release|x64.Build.0 = Release|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Release|x86.ActiveCfg = Release|Any CPU + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782}.Release|x86.Build.0 = Release|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Debug|x64.ActiveCfg = Debug|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Debug|x64.Build.0 = Debug|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Debug|x86.ActiveCfg = Debug|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Debug|x86.Build.0 = Debug|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Release|Any CPU.Build.0 = Release|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Release|x64.ActiveCfg = Release|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Release|x64.Build.0 = Release|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Release|x86.ActiveCfg = Release|Any CPU + {43CA2584-D4AD-4082-AFF4-68B3D1239221}.Release|x86.Build.0 = Release|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Debug|x64.ActiveCfg = Debug|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Debug|x64.Build.0 = Debug|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Debug|x86.ActiveCfg = Debug|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Debug|x86.Build.0 = Debug|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Release|Any CPU.Build.0 = Release|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Release|x64.ActiveCfg = Release|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Release|x64.Build.0 = Release|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Release|x86.ActiveCfg = Release|Any CPU + {B27145AF-B255-4D6E-827B-3512952FB29C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {F6651413-2F44-2F7B-EBE6-A300E8655AFD} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} - {87051F5D-8006-0241-4339-A1B2D29EA094} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} - {2D6628C9-C059-15E9-F3A0-C50F1BCCADA0} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} - {A95DA667-23DF-4067-A173-E9C7FC430D09} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} - {556D8C92-E3DD-F64A-53B1-D741A96888F2} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} - {4FAD1FB1-4696-ABF4-50D9-162F81114A20} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} - {03C2D1D7-AB94-445B-2127-285A367DC6A6} = {6CF592EE-4302-E72F-3CB4-AB1D314DD5A8} + {8AB1BE0C-06AE-4EE2-B45A-4F8CE6381782} = {B36A84DF-456D-A817-6EDD-3EC3E7F6E11F} + {43CA2584-D4AD-4082-AFF4-68B3D1239221} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {2B942E44-74DA-CD21-D337-7A5E9D347C1B} = {B36A84DF-456D-A817-6EDD-3EC3E7F6E11F} + {B27145AF-B255-4D6E-827B-3512952FB29C} = {2B942E44-74DA-CD21-D337-7A5E9D347C1B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E6DB434C-508E-4231-B8A6-5EDD7FF87E22} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj deleted file mode 100644 index 9b508306..00000000 --- a/Tests/Tests.csproj +++ /dev/null @@ -1,56 +0,0 @@ - - - QuanTAlib.Tests - QuanTAlib.Tests - false - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - - - - - - - - - ..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - - - - - - - - diff --git a/Tests/UpdateTestBase.cs b/Tests/UpdateTestBase.cs deleted file mode 100644 index 7a245277..00000000 --- a/Tests/UpdateTestBase.cs +++ /dev/null @@ -1,91 +0,0 @@ -using Xunit; -using System.Security.Cryptography; - -namespace QuanTAlib.Tests; - -public abstract class UpdateTestBase -{ - protected readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); - protected const int RandomUpdates = 100; - protected const double ReferenceValue = 100.0; - protected const int precision = 8; - - protected double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 - } - - protected TBar GetRandomBar(bool IsNew) - { - double open = GetRandomDouble(); - double high = open + Math.Abs(GetRandomDouble()); - double low = open - Math.Abs(GetRandomDouble()); - double close = low + ((high - low) * GetRandomDouble()); - return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew); - } - - protected void TestTValueUpdate(T indicator, Func calc) where T : class - { - var initialValue = calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - var finalValue = calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue.Value, finalValue.Value, precision); - } - - protected void TestTBarUpdate(T indicator, Func calc) where T : class - { - TBar r = GetRandomBar(true); - var initialValue = calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - calc(GetRandomBar(IsNew: false)); - } - var finalValue = calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue.Value, finalValue.Value, precision); - } - - protected void TestDualTValueUpdate(T indicator, Func calc) where T : class - { - var initialValue = calc( - new TValue(DateTime.Now, ReferenceValue, IsNew: true), - new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - calc( - new TValue(DateTime.Now, GetRandomDouble(), IsNew: false), - new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - var finalValue = calc( - new TValue(DateTime.Now, ReferenceValue, IsNew: false), - new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue.Value, finalValue.Value, precision); - } - - protected void TestDualTBarUpdate(T indicator, Func calc) where T : class - { - TBar bar1 = GetRandomBar(true); - TBar bar2 = GetRandomBar(true); - var initialValue = calc(bar1, bar2); - - for (int i = 0; i < RandomUpdates; i++) - { - calc(GetRandomBar(false), GetRandomBar(false)); - } - var finalValue = calc( - new TBar(bar1.Time, bar1.Open, bar1.High, bar1.Low, bar1.Close, bar1.Volume, false), - new TBar(bar2.Time, bar2.Open, bar2.High, bar2.Low, bar2.Close, bar2.Volume, false)); - - Assert.Equal(initialValue.Value, finalValue.Value, precision); - } -} diff --git a/Tests/test_Trady.cs b/Tests/test_Trady.cs deleted file mode 100644 index 10de3783..00000000 --- a/Tests/test_Trady.cs +++ /dev/null @@ -1,108 +0,0 @@ -using Xunit; -using Trady.Analysis.Indicator; -using Trady.Core; -using Trady.Core.Infrastructure; -using System.Diagnostics.CodeAnalysis; -using System.Security.Cryptography; - -#pragma warning disable S1944, S2053, S2222, S2259, S2583, S2589, S3329, S3655, S3900, S3949, S3966, S4158, S4347, S5773, S6781 - -namespace QuanTAlib; - -public class TradyTests -{ - private readonly TBarSeries bars; - private readonly GbmFeed feed; - private readonly RandomNumberGenerator rng; - private readonly double range; - private readonly int iterations; - private readonly int skip; - private readonly IEnumerable Candles; - - public TradyTests() - { - rng = RandomNumberGenerator.Create(); - feed = new(sigma: 0.5, mu: 0.0); - bars = new(feed); - range = 1e-9; - feed.Add(10000); - iterations = 3; - skip = 500; - Candles = bars.Select(bar => new Candle( - bar.Time, - (decimal)bar.Open, - (decimal)bar.High, - (decimal)bar.Low, - (decimal)bar.Close, - (decimal)bar.Volume - )).ToList(); - } - - private int GetRandomNumber(int minValue, int maxValue) - { - byte[] randomBytes = new byte[4]; - rng.GetBytes(randomBytes); - int randomInt = BitConverter.ToInt32(randomBytes, 0); - return Math.Abs(randomInt % (maxValue - minValue)) + minValue; - } - - [Fact] - public void SMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Sma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - - var Trady = new SimpleMovingAverage(Candles, period) - .Compute() - .Select(result => new - { - Date = result.DateTime, - Value = result.Tick.HasValue ? (double)result.Tick.Value : double.NaN - }) - .ToList(); - - Assert.Equal(QL.Length, Trady.Count); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].Value; - double Tr_item = Trady[i].Value; - Assert.InRange(Tr_item - QL_item, -range, range); - } - } - } - - [Fact] - public void EMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Ema ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - - var Trady = new ExponentialMovingAverage(Candles, period) - .Compute() - .Select(result => new - { - Date = result.DateTime, - Value = result.Tick.HasValue ? (double)result.Tick.Value : double.NaN - }) - .ToList(); - - Assert.Equal(QL.Length, Trady.Count); - for (int i = QL.Length - 1; i > skip * 2; i--) - { - double QL_item = QL[i].Value; - double Tr_item = Trady[i].Value; - Assert.InRange(Tr_item - QL_item, -range, range); - } - } - } -} \ No newline at end of file diff --git a/Tests/test_Tulip.cs b/Tests/test_Tulip.cs deleted file mode 100644 index 8b495acc..00000000 --- a/Tests/test_Tulip.cs +++ /dev/null @@ -1,88 +0,0 @@ -using Xunit; -using Tulip; -using System.Diagnostics.CodeAnalysis; -using System.Security.Cryptography; - -#pragma warning disable S1944, S2053, S2222, S2259, S2583, S2589, S3329, S3655, S3900, S3949, S3966, S4158, S4347, S5773, S6781 - -namespace QuanTAlib; - -public class TulipTests -{ - private readonly GbmFeed feed; - private readonly RandomNumberGenerator rng; - private readonly double range; - private readonly int iterations; - private readonly double[] data; - private readonly double[] outdata; - private readonly int skip; - - public TulipTests() - { - rng = RandomNumberGenerator.Create(); - feed = new(sigma: 0.5, mu: 0.0); - range = 1e-9; - feed.Add(10000); - iterations = 3; - skip = 500; - data = feed.Close.v.ToArray(); - outdata = new double[data.Count()]; - } - - private int GetRandomNumber(int minValue, int maxValue) - { - byte[] randomBytes = new byte[4]; - rng.GetBytes(randomBytes); - int randomInt = BitConverter.ToInt32(randomBytes, 0); - return Math.Abs(randomInt % (maxValue - minValue)) + minValue; - } - - [Fact] - public void SMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Sma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - - double[][] arrin = [data]; - double[][] arrout = [outdata]; - Tulip.Indicators.sma.Run(inputs: arrin, options: [period], outputs: arrout); - Assert.Equal(QL.Length, arrout[0].Length); - for (int i = QL.Length - 1; i > skip; i--) - { - double QL_item = QL[i].Value; - double TU = i < period - 1 ? double.NaN : arrout[0][i - period + 1]; - Assert.InRange(TU - QL_item, -range, range); - } - } - } - - [Fact] - public void EMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 35); - Ema ma = new(period, useSma: false); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - - double[][] arrin = [data]; - double[][] arrout = [outdata]; - Tulip.Indicators.ema.Run(inputs: arrin, options: [period], outputs: arrout); - - Assert.Equal(QL.Length, arrout[0].Length); - for (int i = QL.Length - 1; i > skip * 2; i--) //Initial Tulip Ema value is (wrongly) set to the first input value - therefore large skip - { - double QL_item = QL[i].Value; - double TU = arrout[0][i]; - Assert.True(Math.Abs(TU - QL_item) <= range, $"Assertion failed at index {i} for period {period}: TU = {TU}, QL_item = {QL_item}, delta = {TU - QL_item}"); - } - } - } -} \ No newline at end of file diff --git a/Tests/test_core.cs b/Tests/test_core.cs deleted file mode 100644 index 49d67d4b..00000000 --- a/Tests/test_core.cs +++ /dev/null @@ -1,251 +0,0 @@ -using Xunit; - -namespace QuanTAlib.Tests; - -public class CoreTests -{ - #region CircularBuffer Tests - - [Fact] - public void CircularBuffer_BasicOperations() - { - var buffer = new CircularBuffer(5); - - // Test initial state - Assert.Equal(5, buffer.Capacity); - Assert.Equal(0, buffer.Count); - - // Test adding items - buffer.Add(1.0); - buffer.Add(2.0); - Assert.Equal(2, buffer.Count); - Assert.Equal(1.0, buffer[0]); - Assert.Equal(2.0, buffer[^1]); - - // Test overflow behavior - buffer.Add(3.0); - buffer.Add(4.0); - buffer.Add(5.0); - buffer.Add(6.0); // Should remove oldest item (1.0) - Assert.Equal(5, buffer.Count); - Assert.Equal(2.0, buffer[0]); - Assert.Equal(6.0, buffer[^1]); - } - - [Fact] - public void CircularBuffer_UpdateBehavior() - { - var buffer = new CircularBuffer(3); - - // Add new values - buffer.Add(1.0, isNew: true); - buffer.Add(2.0, isNew: true); - Assert.Equal(2, buffer.Count); - - // Update last value - buffer.Add(2.5, isNew: false); - Assert.Equal(2, buffer.Count); - Assert.Equal(2.5, buffer[^1]); - } - - [Fact] - public void CircularBuffer_MinMaxSumAverage() - { - var buffer = new CircularBuffer(5); - - buffer.Add(1.0); - buffer.Add(2.0); - buffer.Add(3.0); - buffer.Add(4.0); - buffer.Add(5.0); - - Assert.Equal(1.0, buffer.Min()); - Assert.Equal(5.0, buffer.Max()); - Assert.Equal(15.0, buffer.Sum()); - Assert.Equal(3.0, buffer.Average()); - } - - [Fact] - public void CircularBuffer_Enumeration() - { - var buffer = new CircularBuffer(3); - - buffer.Add(1.0); - buffer.Add(2.0); - buffer.Add(3.0); - - var list = buffer.ToList(); - Assert.Equal(3, list.Count); - Assert.Equal(1.0, list[0]); - Assert.Equal(3.0, list[2]); - } - - #endregion - - #region TBar Tests - - [Fact] - public void TBar_Construction() - { - // Default constructor - var bar1 = new TBar(); - Assert.Equal(0, bar1.Open); - Assert.True(bar1.IsNew); - - // Value constructor - var bar2 = new TBar(10.0); - Assert.Equal(10.0, bar2.Open); - Assert.Equal(10.0, bar2.High); - Assert.Equal(10.0, bar2.Low); - Assert.Equal(10.0, bar2.Close); - - // Full constructor - var time = DateTime.Now; - var bar3 = new TBar(time, 10.0, 12.0, 9.0, 11.0, 1000.0, false); - Assert.Equal(time, bar3.Time); - Assert.Equal(10.0, bar3.Open); - Assert.Equal(12.0, bar3.High); - Assert.Equal(9.0, bar3.Low); - Assert.Equal(11.0, bar3.Close); - Assert.Equal(1000.0, bar3.Volume); - Assert.False(bar3.IsNew); - } - - [Fact] - public void TBar_DerivedValues() - { - var bar = new TBar(DateTime.Now, 10.0, 20.0, 5.0, 15.0, 1000.0); - - Assert.Equal(12.5, bar.HL2); // (20 + 5) / 2 - Assert.Equal(12.5, bar.OC2); // (10 + 15) / 2 - Assert.Equal(11.67, bar.OHL3, 2); // (10 + 20 + 5) / 3 - Assert.Equal(13.33, bar.HLC3, 2); // (20 + 5 + 15) / 3 - Assert.Equal(12.5, bar.OHLC4); // (10 + 20 + 5 + 15) / 4 - Assert.Equal(13.75, bar.HLCC4); // (20 + 5 + 15 + 15) / 4 - } - - [Fact] - public void TBarSeries_Operations() - { - var series = new TBarSeries(); - var time = DateTime.Now; - var bar1 = new TBar(time, 10.0, 12.0, 9.0, 11.0, 1000.0); - var bar2 = new TBar(time.AddMinutes(1), 11.0, 13.0, 10.0, 12.0, 1100.0); - - // Test adding bars - series.Add(bar1); - series.Add(bar2); - Assert.Equal(2, series.Count); - - // Test updating last bar - var bar2Update = new TBar(bar2.Time, 11.0, 13.5, 9.5, 12.5, 1200.0, false); - series.Add(bar2Update); - Assert.Equal(2, series.Count); - Assert.Equal(12.5, series.Last.Close); - - // Test derived series - Assert.Equal(11.0, series.Open.Last.Value); - Assert.Equal(13.5, series.High.Last.Value); - Assert.Equal(9.5, series.Low.Last.Value); - Assert.Equal(12.5, series.Close.Last.Value); - Assert.Equal(1200.0, series.Volume.Last.Value); - } - - #endregion - - #region TValue Tests - - [Fact] - public void TValue_Construction() - { - // Default constructor - var value1 = new TValue(); - Assert.Equal(0, value1.Value); - Assert.True(value1.IsNew); - Assert.True(value1.IsHot); - - // Value constructor - var value2 = new TValue(10.0); - Assert.Equal(10.0, value2.Value); - - // Full constructor - var time = DateTime.Now; - var value3 = new TValue(time, 10.0, false, false); - Assert.Equal(time, value3.Time); - Assert.Equal(10.0, value3.Value); - Assert.False(value3.IsNew); - Assert.False(value3.IsHot); - } - - [Fact] - public void TValue_Conversions() - { - var value = new TValue(10.0); - - // Test implicit conversions - double d = value; - Assert.Equal(10.0, d); - - DateTime time = value; - Assert.Equal(value.Time, time); - - // Test implicit conversion from double - TValue newValue = 20.0; - Assert.Equal(20.0, newValue.Value); - } - - [Fact] - public void TSeries_Operations() - { - var series = new TSeries(); - var time = DateTime.Now; - - // Test adding values - series.Add(time, 10.0); - series.Add(time.AddMinutes(1), 20.0); - Assert.Equal(2, series.Count); - - // Test updating last value - series.Add(new TValue(time.AddMinutes(1), 25.0, false)); - Assert.Equal(2, series.Count); - Assert.Equal(25.0, series.Last.Value); - - // Test adding range of values - var values = new[] { 30.0, 40.0, 50.0 }; - foreach (var value in values) - { - series.Add(time.AddMinutes(series.Count + 1), value); - } - Assert.Equal(5, series.Count); - - // Test conversions - var doubleList = (List)series; - Assert.Equal(5, doubleList.Count); - Assert.Equal(50.0, doubleList[^1]); - - var doubleArray = (double[])series; - Assert.Equal(5, doubleArray.Length); - Assert.Equal(50.0, doubleArray[^1]); - } - - [Fact] - public void TSeries_EventHandling() - { - var series = new TSeries(); - var receivedValues = new List(); - var time = DateTime.Now; - - series.Pub += (object sender, in ValueEventArgs args) => receivedValues.Add(args.Tick.Value); - - series.Add(time, 10.0); - series.Add(time.AddMinutes(1), 20.0); - series.Add(time.AddMinutes(2), 30.0); - - Assert.Equal(3, receivedValues.Count); - Assert.Equal(10.0, receivedValues[0]); - Assert.Equal(20.0, receivedValues[1]); - Assert.Equal(30.0, receivedValues[2]); - } - - #endregion -} diff --git a/Tests/test_eventing.cs b/Tests/test_eventing.cs deleted file mode 100644 index 1d9c6b7c..00000000 --- a/Tests/test_eventing.cs +++ /dev/null @@ -1,160 +0,0 @@ -using Xunit; -using System.Security.Cryptography; -using System.Reflection; - -namespace QuanTAlib.Tests; - -public class EventingTests -{ - private const int TestDataPoints = 200; - private const int DefaultPeriod = 10; - private const double Tolerance = 1e-9; - - private static readonly (string Name, object[] DirectParams, object[] EventParams)[] ValueIndicators = - { - ("Afirma", new object[] { DefaultPeriod, DefaultPeriod, Afirma.WindowType.BlackmanHarris }, new object[] { new TSeries(), DefaultPeriod, DefaultPeriod, Afirma.WindowType.BlackmanHarris }), - ("Alma", new object[] { DefaultPeriod, 0.85, 6.0 }, new object[] { new TSeries(), DefaultPeriod, 0.85, 6.0 }), - ("Beta", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Convolution", new object[] { new double[] {1,2,3,2,1} }, new object[] { new TSeries(), new double[] {1,2,3,2,1} }), - ("Corr", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Covar", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Curvature", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Dema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Dsma", new object[] { DefaultPeriod, 0.9 }, new object[] { new TSeries(), DefaultPeriod, 0.9 }), - ("Dwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Ema", new object[] { DefaultPeriod, true }, new object[] { new TSeries(), DefaultPeriod, true }), - ("Entropy", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Epma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Fisher", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Frama", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Fwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Gma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Granger", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Hma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Htit", Array.Empty(), new object[] { new TSeries() }), - ("Hwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Jma", new object[] { DefaultPeriod, 0, 0.45, 10 }, new object[] { new TSeries(), DefaultPeriod, 0, 0.45, 10 }), - ("Kama", new object[] { DefaultPeriod, 2, 30 }, new object[] { new TSeries(), DefaultPeriod, 2, 30 }), - ("Kendall", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Kurtosis", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Ltma", new object[] { 0.2 }, new object[] { new TSeries(), 0.2 }), - ("Maaf", new object[] { 39, 0.002 }, new object[] { new TSeries(), 39, 0.002 }), - ("Mama", new object[] { 0.5, 0.05 }, new object[] { new TSeries(), 0.5, 0.05 }), - ("Max", new object[] { DefaultPeriod, 0.0 }, new object[] { new TSeries(), DefaultPeriod, 0.0 }), - ("Median", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Mgdi", new object[] { DefaultPeriod, 0.6 }, new object[] { new TSeries(), DefaultPeriod, 0.6 }), - ("Min", new object[] { DefaultPeriod, 0.0 }, new object[] { new TSeries(), DefaultPeriod, 0.0 }), - ("Mma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Mode", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Percentile", new object[] { DefaultPeriod, 0.5 }, new object[] { new TSeries(), DefaultPeriod, 0.5 }), - ("Pwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Qema", new object[] { 0.2, 0.2, 0.2, 0.2 }, new object[] { new TSeries(), 0.2, 0.2, 0.2, 0.2 }), - ("Rema", new object[] { DefaultPeriod, 0.5 }, new object[] { new TSeries(), DefaultPeriod, 0.5 }), - ("Rma", new object[] { DefaultPeriod, true }, new object[] { new TSeries(), DefaultPeriod, true }), - ("Skew", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Slope", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Sma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Smma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Spearman", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Stddev", new object[] { DefaultPeriod, false }, new object[] { new TSeries(), DefaultPeriod, false }), - ("T3", new object[] { DefaultPeriod, 0.7, true }, new object[] { new TSeries(), DefaultPeriod, 0.7, true }), - ("Tema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Trima", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Variance", new object[] { DefaultPeriod, false }, new object[] { new TSeries(), DefaultPeriod, false }), - ("Vidya", new object[] { DefaultPeriod, 0, 0.2 }, new object[] { new TSeries(), DefaultPeriod, 0, 0.2 }), - ("Wma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Zlema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }), - ("Zscore", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }) - }; - - private static readonly (string Name, object[] DirectParams, object[] EventParams)[] BarIndicators = - { - ("Adl", Array.Empty(), new object[] { new TBarSeries() }), - ("Adosc", new object[] { 3, 10 }, new object[] { new TBarSeries(), 3, 10 }), - ("Aobv", Array.Empty(), new object[] { new TBarSeries() }), - ("Cmf", new object[] { 20 }, new object[] { new TBarSeries(), 20 }), - ("Eom", new object[] { 14 }, new object[] { new TBarSeries(), 14 }), - ("Kvo", new object[] { 34, 55 }, new object[] { new TBarSeries(), 34, 55 }), - ("Atr", new object[] { 14 }, new object[] { new TBarSeries(), 14 }), - ("Chop", new object[] { 14 }, new object[] { new TBarSeries(), 14 }), - ("Dosc", Array.Empty(), new object[] { new TBarSeries() }) - }; - - public static IEnumerable GetValueIndicatorData() - => ValueIndicators.Select(x => new object[] { x.Name, x.DirectParams, x.EventParams }); - - public static IEnumerable GetBarIndicatorData() - => BarIndicators.Select(x => new object[] { x.Name, x.DirectParams, x.EventParams }); - - private static double GetRandomDouble(RandomNumberGenerator rng) - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue; - } - - private static TBar GenerateRandomBar(RandomNumberGenerator rng, double baseValue) - { - return new TBar( - DateTime.Now, - baseValue, - baseValue + Math.Abs(GetRandomDouble(rng) * 10), - baseValue - Math.Abs(GetRandomDouble(rng) * 10), - baseValue + (GetRandomDouble(rng) * 5), - Math.Abs(GetRandomDouble(rng) * 1000), - true - ); - } - - [Theory] - [MemberData(nameof(GetValueIndicatorData))] - public void ValueIndicatorEventTest(string indicatorName, object[] directParams, object[] eventParams) - { - using var rng = RandomNumberGenerator.Create(); - var input = (TSeries)eventParams[0]; - - // Create indicator instances using reflection - var indicatorType = Type.GetType($"QuanTAlib.{indicatorName}, QuanTAlib")!; - var directIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, directParams)!; - var eventIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, eventParams)!; - - // Generate test data and calculate - for (int i = 0; i < TestDataPoints; i++) - { - double randomValue = GetRandomDouble(rng) * 100; - input.Add(randomValue); - directIndicator.Calc(randomValue); - } - - bool areEqual = (double.IsNaN(directIndicator.Value) && double.IsNaN(eventIndicator.Value)) || - Math.Abs(directIndicator.Value - eventIndicator.Value) < Tolerance; - - Assert.True(areEqual, $"Value indicator {indicatorName} failed: Expected {directIndicator.Value}, Actual {eventIndicator.Value}"); - } - - [Theory] - [MemberData(nameof(GetBarIndicatorData))] - public void BarIndicatorEventTest(string indicatorName, object[] directParams, object[] eventParams) - { - using var rng = RandomNumberGenerator.Create(); - var barInput = (TBarSeries)eventParams[0]; - - // Create indicator instances using reflection - var indicatorType = Type.GetType($"QuanTAlib.{indicatorName}, QuanTAlib")!; - var directIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, directParams)!; - var eventIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, eventParams)!; - - // Generate test data and calculate - for (int i = 0; i < TestDataPoints; i++) - { - var bar = GenerateRandomBar(rng, GetRandomDouble(rng) * 100); - barInput.Add(bar); - directIndicator.Calc(bar); - } - - bool areEqual = (double.IsNaN(directIndicator.Value) && double.IsNaN(eventIndicator.Value)) || - Math.Abs(directIndicator.Value - eventIndicator.Value) < Tolerance; - - Assert.True(areEqual, $"Bar indicator {indicatorName} failed: Expected {directIndicator.Value}, Actual {eventIndicator.Value}"); - } -} diff --git a/Tests/test_iTBar.cs b/Tests/test_iTBar.cs deleted file mode 100644 index 25ce67b3..00000000 --- a/Tests/test_iTBar.cs +++ /dev/null @@ -1,172 +0,0 @@ -using Xunit; -using System.Reflection; -using System.Diagnostics.CodeAnalysis; -using System.Security.Cryptography; - -namespace QuanTAlib; - -/// -/// Contains unit tests for bar-based indicators in QuanTAlib. -/// -public class BarIndicatorTests -{ - private readonly RandomNumberGenerator rng; - private const int SeriesLen = 1000; - private const int Corrections = 100; - - /// - /// Initializes a new instance of the BarIndicatorTests class. - /// - public BarIndicatorTests() - { - rng = RandomNumberGenerator.Create(); - } - - private static readonly ITValue[] indicators = new ITValue[] - { - new Atr(period: 14), - - // Add other TBar-based indicators here - }; - - /// - /// Tests if the indicator produces consistent results when processing new and updated bars. - /// - /// The indicator to test. - [Theory] - [MemberData(nameof(GetIndicators))] - public void IndicatorIsNew(ITValue indicator) - { - var indicator1 = indicator; - var indicator2 = indicator; - - MethodInfo calcMethod = FindCalcMethod(indicator.GetType()); - if (calcMethod == null) - { - throw new InvalidOperationException($"Calc method not found for indicator type: {indicator.GetType().Name}"); - } - - for (int i = 0; i < SeriesLen; i++) - { - TBar item1 = GenerateRandomBar(isNew: true); - InvokeCalc(indicator1, calcMethod, item1); - - for (int j = 0; j < Corrections; j++) - { - item1 = GenerateRandomBar(isNew: false); - InvokeCalc(indicator1, calcMethod, item1); - } - - var item2 = new TBar(item1.Time, item1.Open, item1.High, item1.Low, item1.Close, item1.Volume, IsNew: true); - InvokeCalc(indicator2, calcMethod, item2); - - Assert.Equal(indicator1.Value, indicator2.Value); - } - } - - /// - /// Finds the appropriate Calc method for the given indicator type. - /// - /// The type of the indicator. - /// The MethodInfo for the Calc method. - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations.", - Justification = "BaseType will have the same dynamic access requirements as the derived type in this reflection scenario.")] - private static MethodInfo FindCalcMethod([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type) - { - while (type != null && type != typeof(object)) - { - var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Where(m => m.Name == "Calc") - .ToList(); - - if (methods.Count > 0) - { - // Prefer the method with TBar parameter - var method = methods.Find(m => - { - var parameters = m.GetParameters(); - return parameters.Length == 1 && parameters[0].ParameterType == typeof(TBar); - }); - - // If not found, return the first method - return method ?? methods[0]; - } - - type = type.BaseType!; - } - return null!; - } - - /// - /// Invokes the Calc method on the given indicator with the provided input. - /// - /// The indicator instance. - /// The Calc method to invoke. - /// The input TBar. - private static void InvokeCalc(ITValue indicator, MethodInfo calcMethod, TBar input) - { - var parameters = calcMethod.GetParameters(); - if (parameters.Length == 1) - { - calcMethod.Invoke(indicator, new object[] { input }); - } - else if (parameters.Length == 2) - { - calcMethod.Invoke(indicator, new object[] { input, double.NaN }); - } - else - { - throw new InvalidOperationException($"Invalid number of parameters for Calc method in indicator type: {indicator.GetType().Name}"); - } - } - - /// - /// Generates a random TBar for testing purposes. - /// - /// Indicates whether the generated bar should be marked as new. - /// A randomly generated TBar. - private TBar GenerateRandomBar(bool isNew) - { - double open = (GetRandomDouble() * 200) - 100; - double close = (GetRandomDouble() * 200) - 100; - double high = Math.Max(open, close) + (GetRandomDouble() * 10); - double low = Math.Min(open, close) - (GetRandomDouble() * 10); - long volume = GetRandomNumber(0, 10000); - - return new TBar(Time: DateTime.Now, Open: open, High: high, Low: low, Close: close, Volume: volume, IsNew: isNew); - } - - /// - /// Generates a random double between 0 and 1. - /// - /// A random double between 0 and 1. - private double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue; - } - - /// - /// Generates a random integer between minValue (inclusive) and maxValue (exclusive). - /// - /// The minimum value (inclusive). - /// The maximum value (exclusive). - /// A random integer between minValue and maxValue. - private int GetRandomNumber(int minValue, int maxValue) - { - byte[] randomBytes = new byte[4]; - rng.GetBytes(randomBytes); - int randomInt = BitConverter.ToInt32(randomBytes, 0); - return Math.Abs(randomInt % (maxValue - minValue)) + minValue; - } - - /// - /// Provides the list of indicators for parameterized tests. - /// - /// An enumerable of object arrays, each containing an indicator instance. - public static IEnumerable GetIndicators() - { - return indicators.Select(indicator => new object[] { indicator }); - } -} diff --git a/Tests/test_quantower.cs b/Tests/test_quantower.cs deleted file mode 100644 index bf782978..00000000 --- a/Tests/test_quantower.cs +++ /dev/null @@ -1,168 +0,0 @@ -extern alias volatility; -extern alias averages; -extern alias statistics; -extern alias momentum; -extern alias oscillators; -extern alias volume; -extern alias experiments; - -using Xunit; -using System.Reflection; -using System.Diagnostics.CodeAnalysis; -using TradingPlatform.BusinessLayer; -using statistics::QuanTAlib; -using averages::QuanTAlib; -using volatility::QuanTAlib; -using momentum::QuanTAlib; -using oscillators::QuanTAlib; -using volume::QuanTAlib; -using experiments::QuanTAlib; - -namespace QuanTAlib -{ - public class QuantowerTests - { - private static void TestIndicator<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.NonPublicFields)] T>(string fieldName = "ma") where T : Indicator, new() - { - var indicator = new T(); - try - { - var onInitMethod = typeof(T).GetMethod("OnInit", BindingFlags.NonPublic | BindingFlags.Instance); - Assert.NotNull(onInitMethod); - onInitMethod.Invoke(indicator, null); - var onUpdateMethod = typeof(T).GetMethod("OnUpdate", BindingFlags.NonPublic | BindingFlags.Instance); - Assert.NotNull(onUpdateMethod); - - var field = typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); - Assert.NotNull(field); - var fieldValue = field.GetValue(indicator); - Assert.NotNull(fieldValue); - - Assert.NotNull(indicator.ShortName); - Assert.NotEmpty(indicator.ShortName); - Assert.NotNull(indicator.Name); - Assert.NotEmpty(indicator.Name); - Assert.NotNull(indicator.Description); - Assert.NotEmpty(indicator.Description); - Assert.IsAssignableFrom(indicator); - } - catch (Exception ex) - { - throw new Xunit.Sdk.XunitException($"Test failed for {typeof(T).Name}: {ex.Message}"); - } - } - - private static void TestIndicatorMultipleFields<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.NonPublicFields)] T>(string[] fieldNames) where T : Indicator, new() - { - var indicator = new T(); - try - { - var onInitMethod = typeof(T).GetMethod("OnInit", BindingFlags.NonPublic | BindingFlags.Instance); - Assert.NotNull(onInitMethod); - onInitMethod.Invoke(indicator, null); - var onUpdateMethod = typeof(T).GetMethod("OnUpdate", BindingFlags.NonPublic | BindingFlags.Instance); - Assert.NotNull(onUpdateMethod); - - foreach (var fieldName in fieldNames) - { - var field = typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); - Assert.NotNull(field); - var fieldValue = field.GetValue(indicator); - Assert.NotNull(fieldValue); - } - - Assert.NotNull(indicator.ShortName); - Assert.NotEmpty(indicator.ShortName); - Assert.NotNull(indicator.Name); - Assert.NotEmpty(indicator.Name); - Assert.NotNull(indicator.Description); - Assert.NotEmpty(indicator.Description); - Assert.IsAssignableFrom(indicator); - } - catch (Exception ex) - { - throw new Xunit.Sdk.XunitException($"Test failed for {typeof(T).Name}: {ex.Message}"); - } - } - - // Averages Indicators - [Fact] public void Afirma() => TestIndicator(); - [Fact] public void Alma() => TestIndicator(); - [Fact] public void Dema() => TestIndicator(); - [Fact] public void Dsma() => TestIndicator(); - [Fact] public void Dwma() => TestIndicator(); - [Fact] public void Ema() => TestIndicator(); - [Fact] public void Epma() => TestIndicator(); - [Fact] public void Frama() => TestIndicator(); - [Fact] public void Fwma() => TestIndicator(); - [Fact] public void Gma() => TestIndicator(); - [Fact] public void Hma() => TestIndicator(); - [Fact] public void Htit() => TestIndicator(); - [Fact] public void Hwma() => TestIndicator(); - [Fact] public void Jma() => TestIndicator(); - [Fact] public void Kama() => TestIndicator(); - [Fact] public void Ltma() => TestIndicator(); - [Fact] public void Maaf() => TestIndicator(); - [Fact] public void Mama() => TestIndicator(); - [Fact] public void Mgdi() => TestIndicator(); - [Fact] public void Mma() => TestIndicator(); - [Fact] public void Pwma() => TestIndicator(); - [Fact] public void Qema() => TestIndicator(); - [Fact] public void Rema() => TestIndicator(); - [Fact] public void Rma() => TestIndicator(); - [Fact] public void Sinema() => TestIndicator(); - [Fact] public void Sma() => TestIndicator(); - [Fact] public void Smma() => TestIndicator(); - [Fact] public void T3() => TestIndicator(); - [Fact] public void Tema() => TestIndicator(); - [Fact] public void Trima() => TestIndicator(); - [Fact] public void Vidya() => TestIndicator(); - [Fact] public void Wma() => TestIndicator(); - [Fact] public void Zlema() => TestIndicator(); - - // Statistics Indicators - [Fact] public void Curvature() => TestIndicator("curvature"); - [Fact] public void Entropy() => TestIndicator("entropy"); - [Fact] public void Kurtosis() => TestIndicator("kurtosis"); - [Fact] public void Max() => TestIndicator("ma"); - [Fact] public void Median() => TestIndicator("med"); - [Fact] public void Min() => TestIndicator("mi"); - [Fact] public void Mode() => TestIndicator("mode"); - [Fact] public void Percentile() => TestIndicator("percentile"); - [Fact] public void Skew() => TestIndicator("skew"); - [Fact] public void Slope() => TestIndicator("slope"); - [Fact] public void Stddev() => TestIndicator("stddev"); - [Fact] public void Variance() => TestIndicator("variance"); - [Fact] public void Zscore() => TestIndicator("zScore"); - - // Volatility Indicators - [Fact] public void Atr() => TestIndicator("atr"); - [Fact] public void Cmo() => TestIndicator("cmo"); - [Fact] public void Cvi() => TestIndicator("cvi"); - [Fact] public void Historical() => TestIndicator("historical"); - [Fact] public void Jbands() => TestIndicatorMultipleFields(new[] { "jmaUp", "jmaLo" }); - [Fact] public void Jvolty() => TestIndicator("jma"); - [Fact] public void Realized() => TestIndicator("realized"); - [Fact] public void Rvi() => TestIndicator("rvi"); - - // Momentum Indicators - [Fact] public void Adx() => TestIndicator("adx"); - [Fact] public void Adxr() => TestIndicator("adxr"); - [Fact] public void Apo() => TestIndicator("apo"); - [Fact] public void Dmi() => TestIndicator("dmi"); - [Fact] public void Dmx() => TestIndicator("dmx"); - [Fact] public void Dpo() => TestIndicator("dpo"); - [Fact] public void Macd() => TestIndicator("macd"); - [Fact] public void Mom() => TestIndicator("Series"); - [Fact] public void Pmo() => TestIndicator("Series"); - [Fact] public void Po() => TestIndicator("Series"); - [Fact] public void Ppo() => TestIndicator("Series"); - [Fact] public void Roc() => TestIndicator("Series"); - [Fact] public void Trix() => TestIndicator("Series"); - [Fact] public void Vel() => TestIndicator("Series"); - [Fact] public void Vortex() => TestIndicatorMultipleFields(new[] { "PlusLine", "MinusLine" }); - - // Oscillators Indicators - [Fact] public void Cti() => TestIndicator("Series"); - } -} diff --git a/Tests/test_skender.stock.cs b/Tests/test_skender.stock.cs deleted file mode 100644 index ef9e74ca..00000000 --- a/Tests/test_skender.stock.cs +++ /dev/null @@ -1,354 +0,0 @@ -using Xunit; -using Skender.Stock.Indicators; -using System.Diagnostics.CodeAnalysis; -using System.Security.Cryptography; - -#pragma warning disable S1944, S2053, S2222, S2259, S2583, S2589, S3329, S3655, S3900, S3949, S3966, S4158, S4347, S5773, S6781 - -namespace QuanTAlib.Tests; - -public class SkenderTests -{ - private readonly TBarSeries bars; - private readonly GbmFeed feed; - private readonly RandomNumberGenerator rng; - private readonly double range; - private int period; - private readonly int iterations = 3; // Initialized directly at declaration - private readonly IEnumerable quotes; - - public SkenderTests() - { - rng = RandomNumberGenerator.Create(); - feed = new(sigma: 0.5, mu: 0.0); - bars = new(feed); - range = 1e-9; - feed.Add(10000); - quotes = bars.Select(q => new Quote - { - Date = q.Time, - Open = (decimal)q.Open, - High = (decimal)q.High, - Low = (decimal)q.Low, - Close = (decimal)q.Close, - Volume = (decimal)q.Volume - }); - } - - private int GetRandomNumber(int minValue, int maxValue) - { - byte[] randomBytes = new byte[4]; - rng.GetBytes(randomBytes); - int randomInt = BitConverter.ToInt32(randomBytes, 0); - return Math.Abs(randomInt % (maxValue - minValue)) + minValue; - } - - [Fact] - public void SMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Sma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetSma(lookbackPeriods: period).Select(i => i.Sma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void SMAEMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Ema ma = new(period, useSma: true); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void EMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Ema ma = new(period, useSma: false); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > QL.Length - 500; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void DEMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Dema ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetDema(lookbackPeriods: period).Select(i => i.Dema.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > QL.Length - 500; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void TEMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Tema ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetTema(lookbackPeriods: period).Select(i => i.Tema.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > QL.Length - 500; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void SMAConvolution() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - double[] kernel = Enumerable.Repeat(1.0, period).ToArray(); - Convolution ma = new(kernel); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetSma(lookbackPeriods: period).Select(i => i.Sma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void WMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Wma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetWma(lookbackPeriods: period).Select(i => i.Wma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period + 2; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void HMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Hma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetHma(lookbackPeriods: period).Select(i => i.Hma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period + 5; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void EPMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Epma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetEpma(lookbackPeriods: period).Select(i => i.Epma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period + 5; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void ALMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Alma ma = new(period, offset: 0.85, sigma: 6); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetAlma(lookbackPeriods: period).Select(i => i.Alma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void T3() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - T3 ma = new(period, vfactor: 0.7, useSma: false); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void SMMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Smma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetSmma(lookbackPeriods: period).Select(i => i.Smma.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void KAMA() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Kama ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.GetKama(erPeriods: period).Select(i => i.Kama.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void MAMA() - { - for (int run = 0; run < iterations; run++) - { - Mama ma = new(fastLimit: 0.5, slowLimit: 0.05); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.Select(q => (q.Date, (double)q.Close)) - .GetMama(fastLimit: 0.5, slowLimit: 0.05) - .Select(i => i.Mama.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > 500; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void MGDI() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Mgdi ma = new(period: period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - var SK = quotes.Select(q => (q.Date, (double)q.Close)) - .GetDynamic(lookbackPeriods: period) - .Select(i => i.Dynamic.Null2NaN()!); - Assert.Equal(QL.Length, SK.Count()); - for (int i = QL.Length - 1; i > period + 5; i--) - { - Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void ATR() - { - for (int run = 0; run < iterations; run++) - { - period = GetRandomNumber(5, 55); - Atr ma = new(period: period); - TSeries QL = new(); - foreach (TBar item in bars) { QL.Add(ma.Calc(item)); } - - var atrValues = quotes.GetAtr(lookbackPeriods: period).Select(i => i.Atr.Null2NaN()!); - const int AdditionalPeriods = 500; - - for (int i = QL.Length - 1; i > 1000 + AdditionalPeriods; i--) - { - Assert.InRange(atrValues.ElementAt(i) - QL[i].Value, -range, range); - } - } - } -} diff --git a/Tests/test_talib.cs b/Tests/test_talib.cs deleted file mode 100644 index 78d21597..00000000 --- a/Tests/test_talib.cs +++ /dev/null @@ -1,130 +0,0 @@ -using Xunit; -using TALib; -using System.Diagnostics.CodeAnalysis; -using System.Security.Cryptography; - -namespace QuanTAlib; - -public class TAlibTests -{ - private readonly GbmFeed feed; - private readonly RandomNumberGenerator rng; - private readonly double range; - private readonly int iterations; - private readonly double[] data; - private readonly double[] TALIB; - - public TAlibTests() - { - rng = RandomNumberGenerator.Create(); - feed = new(sigma: 0.5, mu: 0.0); - range = 1e-9; - feed.Add(10000); - iterations = 3; - data = feed.Close.v.ToArray(); - TALIB = new double[data.Count()]; - } - - private int GetRandomNumber(int minValue, int maxValue) - { - byte[] randomBytes = new byte[4]; - rng.GetBytes(randomBytes); - int randomInt = BitConverter.ToInt32(randomBytes, 0); - return Math.Abs(randomInt % (maxValue - minValue)) + minValue; - } - - [Fact] - public void SMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Sma ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - Core.Sma(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(QL.Length, TALIB.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void EMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Ema ma = new(period, useSma: true); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - Core.Ema(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(QL.Length, TALIB.Count()); - for (int i = QL.Length - 1; i > period; i--) - { - Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void DEMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Dema ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - Core.Dema(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(QL.Length, TALIB.Length); - for (int i = QL.Length - 1; i > period * 20; i--) - { - Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void TEMA() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - Tema ma = new(period); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - Core.Tema(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period); - Assert.Equal(QL.Length, TALIB.Length); - for (int i = QL.Length - 1; i > period * 20; i--) - { - Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range); - } - } - } - - [Fact] - public void T3() - { - for (int run = 0; run < iterations; run++) - { - int period = GetRandomNumber(5, 55); - T3 ma = new(period, vfactor: 0.7, useSma: false); - TSeries QL = new(); - foreach (TBar item in feed) - { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } - Core.T3(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period, optInVFactor: 0.7); - Assert.Equal(QL.Length, TALIB.Length); - for (int i = QL.Length - 1; i > period * 20; i--) - { - Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range); - } - } - } -} \ No newline at end of file diff --git a/Tests/test_updates_averages.cs b/Tests/test_updates_averages.cs deleted file mode 100644 index 36b154d0..00000000 --- a/Tests/test_updates_averages.cs +++ /dev/null @@ -1,529 +0,0 @@ -using Xunit; -using System.Security.Cryptography; - -namespace QuanTAlib.Tests; - -public class AveragesUpdateTests -{ - private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); - private const int RandomUpdates = 100; - private const double ReferenceValue = 100.0; - private const int precision = 8; - - private double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 - } - - [Fact] - public void Afirma_Update() - { - var indicator = new Afirma(periods: 14, taps: 4, window: Afirma.WindowType.Blackman); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Alma_Update() - { - var indicator = new Alma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Convolution_Update() - { - var indicator = new Convolution(new double[] { 1, 2, 3, 2, 1 }); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Dema_Update() - { - var indicator = new Dema(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Dsma_Update() - { - var indicator = new Dsma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Dwma_Update() - { - var indicator = new Dwma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Ema_Update() - { - var indicator = new Ema(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Epma_Update() - { - var indicator = new Epma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Frama_Update() - { - var indicator = new Frama(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Fwma_Update() - { - var indicator = new Fwma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Gma_Update() - { - var indicator = new Gma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Hma_Update() - { - var indicator = new Hma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Htit_Update() - { - var indicator = new Htit(); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Hwma_Update() - { - var indicator = new Hwma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Jma_Update() - { - var indicator = new Jma(period: 14, phase: 0); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Kama_Update() - { - var indicator = new Kama(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Ltma_Update() - { - var indicator = new Ltma(gamma: 0.2); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Maaf_Update() - { - var indicator = new Maaf(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mama_Update() - { - var indicator = new Mama(fastLimit: 0.5, slowLimit: 0.05); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mgdi_Update() - { - var indicator = new Mgdi(period: 14, kFactor: 0.6); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mma_Update() - { - var indicator = new Mma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pwma_Update() - { - var indicator = new Pwma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Qema_Update() - { - var indicator = new Qema(k1: 0.2, k2: 0.2, k3: 0.2, k4: 0.2); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rema_Update() - { - var indicator = new Rema(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rma_Update() - { - var indicator = new Rma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Sinema_Update() - { - var indicator = new Sinema(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Sma_Update() - { - var indicator = new Sma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Smma_Update() - { - var indicator = new Smma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void T3_Update() - { - var indicator = new T3(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Tema_Update() - { - var indicator = new Tema(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Trima_Update() - { - var indicator = new Trima(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vidya_Update() - { - var indicator = new Vidya(shortPeriod: 14, longPeriod: 30, alpha: 0.2); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Wma_Update() - { - var indicator = new Wma(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Zlema_Update() - { - var indicator = new Zlema(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } -} diff --git a/Tests/test_updates_errors.cs b/Tests/test_updates_errors.cs deleted file mode 100644 index 8af37f5e..00000000 --- a/Tests/test_updates_errors.cs +++ /dev/null @@ -1,259 +0,0 @@ -using Xunit; -using System.Security.Cryptography; - -namespace QuanTAlib.Tests; - -public class UpdateTests -{ - private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); - private const int RandomUpdates = 100; - private const double ReferenceValue = 100.0; - private const int precision = 8; - - private double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 - } - - [Fact] - public void Huberloss_Update() - { - var indicator = new Huber(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mae_Update() - { - var indicator = new Mae(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mapd_Update() - { - var indicator = new Mapd(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mape_Update() - { - var indicator = new Mape(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mase_Update() - { - var indicator = new Mase(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mda_Update() - { - var indicator = new Mda(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Me_Update() - { - var indicator = new Me(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mpe_Update() - { - var indicator = new Mpe(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mse_Update() - { - var indicator = new Mse(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Msle_Update() - { - var indicator = new Msle(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rae_Update() - { - var indicator = new Rae(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rmse_Update() - { - var indicator = new Rmse(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rmsle_Update() - { - var indicator = new Rmsle(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rse_Update() - { - var indicator = new Rse(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Smape_Update() - { - var indicator = new Smape(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rsquared_Update() - { - var indicator = new Rsquared(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } -} diff --git a/Tests/test_updates_momentum.cs b/Tests/test_updates_momentum.cs deleted file mode 100644 index 96b2930d..00000000 --- a/Tests/test_updates_momentum.cs +++ /dev/null @@ -1,292 +0,0 @@ -using Xunit; -using System.Security.Cryptography; - -namespace QuanTAlib.Tests; - -public class MomentumUpdateTests -{ - private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); - private const int RandomUpdates = 100; - private const double ReferenceValue = 100.0; - private const int precision = 8; - - private double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 - } - - private TBar GetRandomBar(bool IsNew) - { - double open = GetRandomDouble(); - double high = open + Math.Abs(GetRandomDouble()); - double low = open - Math.Abs(GetRandomDouble()); - double close = low + ((high - low) * GetRandomDouble()); - return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew); - } - - [Fact] - public void Adx_Update() - { - var indicator = new Adx(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Adxr_Update() - { - var indicator = new Adxr(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Apo_Update() - { - var indicator = new Apo(fastPeriod: 12, slowPeriod: 26); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Dmi_Update() - { - var indicator = new Dmi(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Dmx_Update() - { - var indicator = new Dmx(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Dpo_Update() - { - var indicator = new Dpo(period: 20); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Macd_Update() - { - var indicator = new Macd(fastPeriod: 12, slowPeriod: 26, signalPeriod: 9); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pmo_Update() - { - var indicator = new Pmo(period1: 35, period2: 20); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Po_Update() - { - var indicator = new Po(fastPeriod: 10, slowPeriod: 21); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Ppo_Update() - { - var indicator = new Ppo(fastPeriod: 12, slowPeriod: 26); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Prs_Update() - { - var indicator = new Prs(); - indicator.SetBenchmark(ReferenceValue); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.SetBenchmark(GetRandomDouble() + 100); // Ensure positive benchmark - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - - indicator.SetBenchmark(ReferenceValue); - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Roc_Update() - { - var indicator = new Roc(period: 12); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mom_Update() - { - var indicator = new Mom(period: 10); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Trix_Update() - { - var indicator = new Trix(period: 18); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Tsi_Update() - { - var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vel_Update() - { - var indicator = new Vel(period: 10); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vortex_Update() - { - var indicator = new Vortex(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } -} diff --git a/Tests/test_updates_oscillators.cs b/Tests/test_updates_oscillators.cs deleted file mode 100644 index 636ede3a..00000000 --- a/Tests/test_updates_oscillators.cs +++ /dev/null @@ -1,182 +0,0 @@ -using Xunit; - -namespace QuanTAlib.Tests; - -public class OscillatorsUpdateTests : UpdateTestBase -{ - [Fact] - public void Rsi_Update() - { - var indicator = new Rsi(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Rsx_Update() - { - var indicator = new Rsx(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Cmo_Update() - { - var indicator = new Cmo(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ao_Update() - { - var indicator = new Ao(); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ac_Update() - { - var indicator = new Ac(); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Aroon_Update() - { - var indicator = new Aroon(period: 25); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Bop_Update() - { - var indicator = new Bop(); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Cci_Update() - { - var indicator = new Cci(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Cfo_Update() - { - var indicator = new Cfo(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Chop_Update() - { - var indicator = new Chop(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Cog_Update() - { - var indicator = new Cog(period: 10); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Coppock_Update() - { - var indicator = new Coppock(roc1Period: 14, roc2Period: 11, wmaPeriod: 10); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Crsi_Update() - { - var indicator = new Crsi(period1: 10, period2: 14, period3: 30); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Smi_Update() - { - var indicator = new Smi(period: 10, smooth1: 3, smooth2: 3); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Srsi_Update() - { - var indicator = new Srsi(rsiPeriod: 14, stochPeriod: 14, smoothK: 3, smoothD: 3); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Stc_Update() - { - var indicator = new Stc(cyclePeriod: 10, fastPeriod: 23, slowPeriod: 50); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Stoch_Update() - { - var indicator = new Stoch(period: 14, smoothK: 3, smoothD: 3); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Tsi_Update() - { - var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Uo_Update() - { - var indicator = new Uo(period1: 7, period2: 14, period3: 28); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Willr_Update() - { - var indicator = new Willr(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Dosc_Update() - { - var indicator = new Dosc(); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Efi_Update() - { - var indicator = new Efi(period: 13); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Fisher_Update() - { - var indicator = new Fisher(period: 10); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Cti_Update() - { - var indicator = new Cti(period: 20); - TestTValueUpdate(indicator, indicator.Calc); - } -} diff --git a/Tests/test_updates_statistics.cs b/Tests/test_updates_statistics.cs deleted file mode 100644 index 5558f5ae..00000000 --- a/Tests/test_updates_statistics.cs +++ /dev/null @@ -1,160 +0,0 @@ -using Xunit; - -namespace QuanTAlib.Tests; - -public class StatisticsUpdateTests : UpdateTestBase -{ - [Fact] - public void Beta_Update() - { - var indicator = new Beta(period: 14); - TestDualTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Corr_Update() - { - var indicator = new Corr(period: 14); - TestDualTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Covar_Update() - { - var indicator = new Covar(period: 14); - TestDualTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Curvature_Update() - { - var indicator = new Curvature(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Entropy_Update() - { - var indicator = new Entropy(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Granger_Update() - { - var indicator = new Granger(lags: 5); - TestDualTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Hurst_Update() - { - var indicator = new Hurst(period: 100, minLength: 10); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Kendall_Update() - { - var indicator = new Kendall(period: 14); - TestDualTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Kurtosis_Update() - { - var indicator = new Kurtosis(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Max_Update() - { - var indicator = new Max(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Median_Update() - { - var indicator = new Median(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Min_Update() - { - var indicator = new Min(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Mode_Update() - { - var indicator = new Mode(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Percentile_Update() - { - var indicator = new Percentile(period: 14, percent: 50); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Skew_Update() - { - var indicator = new Skew(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Slope_Update() - { - var indicator = new Slope(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Spearman_Update() - { - var indicator = new Spearman(period: 14); - TestDualTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Stddev_Update() - { - var indicator = new Stddev(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Theil_Update() - { - var indicator = new Theil(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Tsf_Update() - { - var indicator = new Tsf(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Variance_Update() - { - var indicator = new Variance(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Zscore_Update() - { - var indicator = new Zscore(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } -} diff --git a/Tests/test_updates_volatility.cs b/Tests/test_updates_volatility.cs deleted file mode 100644 index 7a9c1314..00000000 --- a/Tests/test_updates_volatility.cs +++ /dev/null @@ -1,223 +0,0 @@ -using Xunit; - -namespace QuanTAlib.Tests; - -public class VolatilityUpdateTests : UpdateTestBase -{ - [Fact] - public void Adr_Update() - { - var indicator = new Adr(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Atr_Update() - { - var indicator = new Atr(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Atrs_Update() - { - var indicator = new Atrs(period: 14, factor: 2.0); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ap_Update() - { - var indicator = new Ap(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Atrp_Update() - { - var indicator = new Atrp(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Bband_Update() - { - var indicator = new Bband(period: 20, multiplier: 2.0); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ccv_Update() - { - var indicator = new Ccv(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ce_Update() - { - var indicator = new Ce(period: 22, multiplier: 3.0); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Cv_Update() - { - var indicator = new Cv(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Cvi_Update() - { - var indicator = new Cvi(period: 10, smoothPeriod: 10); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Dchn_Update() - { - var indicator = new Dchn(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ewma_Update() - { - var indicator = new Ewma(period: 20, lambda: 0.94); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Fcb_Update() - { - var indicator = new Fcb(period: 20, smoothing: 0.5); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Gkv_Update() - { - var indicator = new Gkv(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Historical_Update() - { - var indicator = new Hv(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Hlv_Update() - { - var indicator = new Hlv(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Jvolty_Update() - { - var indicator = new Jvolty(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Natr_Update() - { - var indicator = new Natr(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Pch_Update() - { - var indicator = new Pch(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Pv_Update() - { - var indicator = new Pv(period: 10); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Realized_Update() - { - var indicator = new Rv(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Rsv_Update() - { - var indicator = new Rsv(period: 10); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Rvi_Update() - { - var indicator = new Rvi(period: 14); - TestTValueUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Sv_Update() - { - var indicator = new Sv(period: 20, lambda: 0.94); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Tr_Update() - { - var indicator = new Tr(); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Ui_Update() - { - var indicator = new Ui(period: 14); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Vc_Update() - { - var indicator = new Vc(period: 20, deviations: 2.0); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Vov_Update() - { - var indicator = new Vov(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Vr_Update() - { - var indicator = new Vr(shortPeriod: 10, longPeriod: 20); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Vs_Update() - { - var indicator = new Vs(period: 14, multiplier: 2.0); - TestTBarUpdate(indicator, indicator.Calc); - } - - [Fact] - public void Yzv_Update() - { - var indicator = new Yzv(period: 20); - TestTBarUpdate(indicator, indicator.Calc); - } -} diff --git a/Tests/test_updates_volume.cs b/Tests/test_updates_volume.cs deleted file mode 100644 index c85a619b..00000000 --- a/Tests/test_updates_volume.cs +++ /dev/null @@ -1,386 +0,0 @@ -using Xunit; -using System.Security.Cryptography; - -namespace QuanTAlib.Tests; - -public class VolumeUpdateTests -{ - private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); - private const int RandomUpdates = 100; - private const int precision = 8; - - private double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 - } - - private TBar GetRandomBar(bool IsNew) - { - double open = GetRandomDouble(); - double high = open + Math.Abs(GetRandomDouble()); - double low = open - Math.Abs(GetRandomDouble()); - double close = low + ((high - low) * GetRandomDouble()); - double volume = Math.Abs(GetRandomDouble()) * 1000; // Random positive volume - return new TBar(DateTime.Now, open, high, low, close, volume, IsNew); - } - - [Fact] - public void Adl_Update() - { - var indicator = new Adl(); - TBar r = GetRandomBar(true); - - // First calculation with IsNew: true - double value1 = indicator.Calc(r); - - // Multiple recalculations with IsNew: false should not change the value - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - } - - // Final calculation with IsNew: false should match initial value - double value2 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - Assert.Equal(value1, value2, precision); - - // New calculation with IsNew: true should update the value - double value3 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: true)); - Assert.NotEqual(value1, value3, precision); - } - - [Fact] - public void Adosc_Update() - { - var indicator = new Adosc(shortPeriod: 3, longPeriod: 10); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Aobv_Update() - { - var indicator = new Aobv(); - TBar r = GetRandomBar(true); - - // First calculation with IsNew: true - double value1 = indicator.Calc(r); - - // Multiple recalculations with IsNew: false should not change the value - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - } - - // Final calculation with IsNew: false should match initial value - double value2 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - Assert.Equal(value1, value2, precision); - - // New calculation with IsNew: true should update the value - double value3 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: true)); - Assert.NotEqual(value1, value3, precision); - } - - [Fact] - public void Cmf_Update() - { - var indicator = new Cmf(period: 20); - TBar r = GetRandomBar(true); - - // Generate a sequence of bars for warmup - var warmupBars = new List(); - for (int i = 0; i < indicator.WarmupPeriod; i++) - { - var bar = GetRandomBar(IsNew: true); - warmupBars.Add(bar); - indicator.Calc(bar); - } - - // Calculate initial value after warmup - double initialValue = indicator.Calc(r); - - // Apply random updates - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - - // Reset and replay the same sequence - indicator.Init(); - foreach (var bar in warmupBars) - { - indicator.Calc(bar); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Eom_Update() - { - var indicator = new Eom(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Kvo_Update() - { - var indicator = new Kvo(shortPeriod: 34, longPeriod: 55); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Mfi_Update() - { - var indicator = new Mfi(period: 14); - TBar r = GetRandomBar(true); - - // Generate a sequence of bars for warmup - var warmupBars = new List(); - for (int i = 0; i < indicator.WarmupPeriod; i++) - { - var bar = GetRandomBar(IsNew: true); - warmupBars.Add(bar); - indicator.Calc(bar); - } - - // Calculate initial value after warmup - double initialValue = indicator.Calc(r); - - // Apply random updates - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - - // Reset and replay the same sequence - indicator.Init(); - foreach (var bar in warmupBars) - { - indicator.Calc(bar); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Nvi_Update() - { - var indicator = new Nvi(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Obv_Update() - { - var indicator = new Obv(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pvi_Update() - { - var indicator = new Pvi(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pvol_Update() - { - var indicator = new Pvol(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pvo_Update() - { - var indicator = new Pvo(shortPeriod: 12, longPeriod: 26); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pvr_Update() - { - var indicator = new Pvr(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Pvt_Update() - { - var indicator = new Pvt(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Tvi_Update() - { - var indicator = new Tvi(minTick: 0.5); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vf_Update() - { - var indicator = new Vf(period: 13); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vp_Update() - { - var indicator = new Vp(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vwap_Update() - { - var indicator = new Vwap(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Vwma_Update() - { - var indicator = new Vwma(period: 20); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } -} diff --git a/build.sh b/build.sh deleted file mode 100644 index 835802bf..00000000 --- a/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -dotnet gitversion . /output buildserver -dotnet build diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index 8b137891..00000000 --- a/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docs/.playground/mermaidtest.md b/docs/.playground/mermaidtest.md deleted file mode 100644 index c289878e..00000000 --- a/docs/.playground/mermaidtest.md +++ /dev/null @@ -1,21 +0,0 @@ -```mermaid -flowchart LR - subgraph m[Mermaid.js] - direction TB - S[ ]-.- - C[build
diagrams
with markdown] --> - D[on-line
live editor] - end - A[Why are diagrams
useful?] --> m - m --> N[3 x methods
for creating
diagrams] - N --> T[Examples] - T --> X[Styling
and
captions] - X --> V[Tips] - - - classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; - classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 - class A,C,D,N,X,m,T,V box - class S spacewhite -``` - diff --git a/docs/Progress.md b/docs/Progress.md deleted file mode 100644 index eaf705a9..00000000 --- a/docs/Progress.md +++ /dev/null @@ -1,313 +0,0 @@ -| AD | Chaikin A/D Line | -| AROON | Aroon Indicator | -| ADX | Average Directional Movement Index | -| ADXR | Average Directional Movement Index Rating | -| DX | Directional Movement Index | -| SAR | Parabolic SAR | -| SAREXT | Parabolic SAR - Extended | -| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline | -| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode | -| ZZ | ZigZag Indicator | -| DMI | Directional Movement Index | -| Alligator | Alligator Indicator | -| Regression | Regression Line Indicator | -| SI | Swing Index | -| ATS | ATR Trailing Stop | -| ERI | Elder-ray Index | -| GO | Gator Oscillator | -| HE | Hurst Exponent | -| IC | Ichimoku Cloud | -| ST | SuperTrend | -| VI | Vortex Indicator | -| WA | Williams Alligator | -| RSI | Relative Strength Index | -| CCI | Commodity Channel Index | -| MOM | Momentum | -| ROC | Rate of Change | -| PPO | Percentage Price Oscillator | -| AO | Awesome Oscillator | -| CMO | Chande Momentum Oscillator | -| TRIX | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA | -| ULTOSC | Ultimate Oscillator | -| AROONOSC | Aroon Oscillator | -| ADOSC | Chaikin A/D Oscillator | -| APO | Absolute Price Oscillator | -| STOCH | Stochastic | -| STOCHF | Stochastic Fast | -| STOCHRSI | Stochastic Relative Strength Index | -| Qstick | Qstick Indicator | -| RLW | %R Larry Williams | -| AC | Acceleration Oscillator | -| TSI | True Strength Index | -| CRSI | ConnorsRSI | -| DPO | Detrended Price Oscillator | -| KDJ | KDJ Index | -| STC | Schaff Trend Cycle | -| SMI | Stochastic Momentum Index | -| BB | Bollinger Bands | -| Keltner | Keltner Channel | -| BBF | Bollinger Bands Flat | -| Channel | Price Channel | -| MAE | Moving Average Envelope | -| PAZ | Price Action Zones | -| DC | Donchian Channels | -| FCB | Fractal Chaos Bands | -| PP | Pivot Points | -| RPP | Rolling Pivot Points | -| STARC | STARC Bands | -| SDC | Standard Deviation Channels | -| OBV | On Balance Volume | -| PVI | Positive Volume Index | -| Volume | Volume Indicator | -| MFI | Money Flow Index | -| ADL | Accumulation / Distribution Line | -| CMF | Chaikin Money Flow | -| FI | Force Index | -| KVO | Klinger Volume Oscillator | -| PVO | Percentage Volume Oscillator | -| ATS | ATR Trailing Stop | -| CE | Chandelier Exit | -| SAR | Parabolic SAR | -| ST | SuperTrend | -| VS | Volatility Stop | -| Pivots | Pivots | -| WF | Williams Fractal | -| EMA | Exponential Moving Average | -| SMA | Simple Moving Average | -| LWMA | Linearly Weighted Moving Average | -| SMMA | Smoothed Moving Average | -| MMA | Modified Moving Average | -| KAMA | Kaufman Adaptive Moving Average | -| DEMA | Double Exponential Moving Average | -| TEMA | Triple Exponential Moving Average | -| MAMA | MESA Adaptive Moving Average | -| TRIMA | Triangular Moving Average | -| T3 | Triple Exponential Moving Average (T3) | -| PPMA | Pivot Point Moving Average | -| WMA | Weighted Moving Average | -| ALMA | Arnaud Legoux Moving Average | -| EPMA | Endpoint Moving Average | -| HMA | Hull Moving Average | -| LSMA | Least Squares Moving Average | -| MD | McGinley Dynamic | -| RMA | Running Moving Average | -| VWAP | Volume Weighted Average Price | -| VWMA | Volume Weighted Moving Average | -| ATR | Average True Range | -| NATR | Normalized Average True Range | -| TRANGE | True Range | -| STDDEV | Standard Deviation | -| HV | Historical Volatility | -| BOP | Balance of Power | -| BBP | Bull and Bear Power | -| CI | Choppiness Index | -| DCP | Dominant Cycle Periods | -| PMO | Price Momentum Oscillator | -| PRS | Price Relative Strength | -| ROCB | ROC with Bands | -| RRA | Rescaled Range Analysis | -| UI | Ulcer Index | -| CORREL | Pearson's Correlation Coefficient | -| BETA | Beta | -| VAR | Variance | -| AVGPRICE | Average Price | -| MEDPRICE | Median Price | -| TYPPRICE | Typical Price | -| WCLPRICE | Weighted Close Price | -| SUM | Summation | -| MAX | Highest value over a specified period | -| MIN | Lowest value over a specified period | -| MAXINDEX | Index of highest value over a specified period | -| MININDEX | Index of lowest value over a specified period | -| MINMAX | Lowest and highest values over a specified period | -| MINMAXINDEX | Indexes of lowest and highest values over a period | -| BC | Beta Coefficient | -| MAD | Mean absolute deviation | -| MAPE | Mean absolute percentage error | -| MSE | Mean square error | -| R2 | R-Squared (Coefficient of Determination) | -| SLR | Slope and Linear Regression | -| ZS | Z-Score | -| AD | Chaikin A/D Line | -| AROON | Aroon Indicator | -| ADX | Average Directional Movement Index | -| ADXR | Average Directional Movement Index Rating | -| DX | Directional Movement Index | -| SAR | Parabolic SAR | -| SAREXT | Parabolic SAR - Extended | -| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline | -| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode | -| ZZ | ZigZag Indicator | -| DMI | Directional Movement Index | -| Alligator | Alligator Indicator | -| Regression | Regression Line Indicator | -| SI | Swing Index | -| ATS | ATR Trailing Stop | -| ERI | Elder-ray Index | -| GO | Gator Oscillator | -| HE | Hurst Exponent | -| IC | Ichimoku Cloud | -| ST | SuperTrend | -| VI | Vortex Indicator | -| WA | Williams Alligator | -| RSI | Relative Strength Index | -| CCI | Commodity Channel Index | -| MOM | Momentum | -| ROC | Rate of Change | -| PPO | Percentage Price Oscillator | -| AO | Awesome Oscillator | -| CMO | Chande Momentum Oscillator | -| TRIX | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA | -| ULTOSC | Ultimate Oscillator | -| AROONOSC | Aroon Oscillator | -| ADOSC | Chaikin A/D Oscillator | -| APO | Absolute Price Oscillator | -| STOCH | Stochastic | -| STOCHF | Stochastic Fast | -| STOCHRSI | Stochastic Relative Strength Index | -| Qstick | Qstick Indicator | -| RLW | %R Larry Williams | -| AC | Acceleration Oscillator | -| TSI | True Strength Index | -| CRSI | ConnorsRSI | -| DPO | Detrended Price Oscillator | -| KDJ | KDJ Index | -| STC | Schaff Trend Cycle | -| SMI | Stochastic Momentum Index | -| BB | Bollinger Bands | -| Keltner | Keltner Channel | -| BBF | Bollinger Bands Flat | -| Channel | Price Channel | -| MAE | Moving Average Envelope | -| PAZ | Price Action Zones | -| DC | Donchian Channels | -| FCB | Fractal Chaos Bands | -| PP | Pivot Points | -| RPP | Rolling Pivot Points | -| STARC | STARC Bands | -| SDC | Standard Deviation Channels | -| OBV | On Balance Volume | -| PVI | Positive Volume Index | -| Volume | Volume Indicator | -| MFI | Money Flow Index | -| ADL | Accumulation / Distribution Line | -| CMF | Chaikin Money Flow | -| FI | Force Index | -| KVO | Klinger Volume Oscillator | -| PVO | Percentage Volume Oscillator | -| ATS | ATR Trailing Stop | -| CE | Chandelier Exit | -| SAR | Parabolic SAR | -| ST | SuperTrend | -| VS | Volatility Stop | -| Pivots | Pivots | -| WF | Williams Fractal | -| ALMA | Arnaud Legoux Moving Average | -| EPMA | Endpoint Moving Average | -| HMA | Hull Moving Average | -| LSMA | Least Squares Moving Average | -| MD | McGinley Dynamic | -| RMA | Running Moving Average | -| T3 | Tillson T3 Moving Average | -| VWAP | Volume Weighted Average Price | -| VWMA | Volume Weighted Moving Average | -| BOP | Balance of Power | -| BBP | Bull and Bear Power | -| CI | Choppiness Index | -| DCP | Dominant Cycle Periods | -| PMO | Price Momentum Oscillator | -| PRS | Price Relative Strength | -| ROCB | ROC with Bands | -| RRA | Rescaled Range Analysis | -| UI | Ulcer Index | -| BC | Beta Coefficient | -| MAD | Mean absolute deviation | -| MAPE | Mean absolute percentage error | -| MSE | Mean square error | -| R2 | R-Squared (Coefficient of Determination) | -| SLR | Slope and Linear Regression | -| ZS | Z-Score | -| EMA | Exponential Moving Average | -| SMA | Simple Moving Average | -| LWMA | Linearly Weighted Moving Average | -| SMMA | Smoothed Moving Average | -| MMA | Modified Moving Average | -| KAMA | Kaufman Adaptive Moving Average | -| DEMA | Double Exponential Moving Average | -| TEMA | Triple Exponential Moving Average | -| MAMA | MESA Adaptive Moving Average | -| TRIMA | Triangular Moving Average | -| T3 | Triple Exponential Moving Average (T3) | -| PPMA | Pivot Point Moving Average | -| MAE | Moving Average Envelope | -| MACD | Moving Average Convergence Divergence | -| MACDEXT | MACD with controllable MA type | -| MACDFIX | Moving Average Convergence Divergence Fix 12/26 | -| OsMA | Moving Average of Oscillator | -| Regression | Regression Indicator | -| LINEARREG | Linear Regression | -| LINEARREG_ANGLE | Linear Regression Angle | -| LINEARREG_INTERCEPT | Linear Regression Intercept | -| LINEARREG_SLOPE | Linear Regression Slope | -| RSI | Relative Strength Index | -| CCI | Commodity Channel Index | -| MOM | Momentum | -| ROC | Rate of Change | -| PPO | Percentage Price Oscillator | -| AO | Awesome Oscillator | -| CMO | Chande Momentum Oscillator | -| TRIX | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA | -| ULTOSC | Ultimate Oscillator | -| AROONOSC | Aroon Oscillator | -| ADOSC | Chaikin A/D Oscillator | -| APO | Absolute Price Oscillator | -| STOCH | Stochastic | -| STOCHF | Stochastic Fast | -| STOCHRSI | Stochastic Relative Strength Index | -| Qstick | Qstick Indicator | -| RLW | %R Larry Williams | -| AC | Acceleration Oscillator | -| TSI | True Strength Index | -| AD | Chaikin A/D Line | -| AROON | Aroon Indicator | -| ADX | Average Directional Movement Index | -| ADXR | Average Directional Movement Index Rating | -| DX | Directional Movement Index | -| SAR | Parabolic SAR | -| SAREXT | Parabolic SAR - Extended | -| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline | -| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode | -| ZZ | ZigZag Indicator | -| DMI | Directional Movement Index | -| Alligator | Alligator Indicator | -| Regression | Regression Line Indicator | -| SI | Swing Index | -| ATR | Average True Range | -| NATR | Normalized Average True Range | -| TRANGE | True Range | -| STDDEV | Standard Deviation | -| HV | Historical Volatility | -| BB | Bollinger Bands | -| Keltner | Keltner Channel | -| BBF | Bollinger Bands Flat | -| Channel | Price Channel | -| MAE | Moving Average Envelope | -| PAZ | Price Action Zones | -| OBV | On Balance Volume | -| PVI | Positive Volume Index | -| Volume | Volume Indicator | -| MFI | Money Flow Index | -| CORREL | Pearson's Correlation Coefficient | -| BETA | Beta | -| VAR | Variance | -| AVGPRICE | Average Price | -| MEDPRICE | Median Price | -| TYPPRICE | Typical Price | -| WCLPRICE | Weighted Close Price | -| SUM | Summation | -| MAX | Highest value over a specified period | -| MIN | Lowest value over a specified period | -| MAXINDEX | Index of highest value over a specified period | -| MININDEX | Index of lowest value over a specified period | -| MINMAX | Lowest and highest values over a specified period | -| MINMAXINDEX | Indexes of lowest and highest values over a period | diff --git a/docs/_sidebar.md b/docs/_sidebar.md deleted file mode 100644 index 40084778..00000000 --- a/docs/_sidebar.md +++ /dev/null @@ -1,113 +0,0 @@ -* [Home](/) - -* [List of Indicators](indicators/indicators.md) - -* 🚧 Introduction - * [Overview]() - * [Features]() - * [Historical vs Real-time analysis](essays/realtime.md) - -* 🚧 Core Concepts - * [Time Series Data Handling]() - * [Calculation classes]() - * [Presentation Classes]() - -* 🚧 QuanTAlib C# Library - * [Installation]() - * [Quick Start Guide]() - * [Usage Examples]() - * [Tests and Validation]() - -* 🚧 Quantower Charts - * [Installation]() - * [Quick Start Guide]() - * [Using VS Code for QuanTower coding](setup/vscode.md) - * [Using DotPeek](setup/dotpeek.md) - * [Creating Custom Indicators]() - * [Inspecting Quantower Internals]() - -* [🚧 Available Indicators](indicators/indicators.md) - * Momentum - * [ADX - Average Directional Index](indicators/momentum/adx/description.md) - * [ADXR - Average Directional Index Rating](indicators/momentum/adxr/description.md) - * [APO - Absolute Price Oscillator](indicators/momentum/apo/description.md) - * [DMI - Directional Movement Index](indicators/momentum/dmi/description.md) - * [DMX - Directional Movement Extended](indicators/momentum/dmx/description.md) - * [DPO - Detrended Price Oscillator](indicators/momentum/dpo/description.md) - * [MOM - Momentum](indicators/momentum/mom/description.md) - * [PMO - Price Momentum Oscillator](indicators/momentum/pmo/description.md) - * [PO - Price Oscillator](indicators/momentum/po/description.md) - * [PPO - Percentage Price Oscillator](indicators/momentum/ppo/description.md) - * [PRS - Price Relative Strength](indicators/momentum/prs/description.md) - * [ROC - Rate of Change](indicators/momentum/roc/description.md) - * [TRIX - Triple Exponential](indicators/momentum/trix/description.md) - * [TSI - True Strength Index](indicators/momentum/tsi/description.md) - * [VEL - Velocity](indicators/momentum/vel/description.md) - * [VORTEX - Vortex Indicator](indicators/momentum/vortex/description.md) - * Basic Transforms - * Numerical Analysis - * Errors - * Moving Averages - * [AFIRMA - Adaptive Filtering Integrated Recursive Moving Average](indicators/averages/afirma/afirma.md) - * [Calculation](indicators/averages/afirma/calc.md) - * [Analysis](indicators/averages/afirma/analysis.md) - * [Charts](indicators/averages/afirma/charts.md) - * [ALMA - Arnaud Legoux Moving Average](indicators/averages/alma/alma.md) - * [Calculation](indicators/averages/alma/calc.md) - * [Analysis](indicators/averages/alma/analysis.md) - * [Charts](indicators/averages/alma/charts.md) - * [AMA - Adaptive Moving Average](indicators/averages/ama/ama.md) - * [Calculation](indicators/averages/ama/calc.md) - * [Analysis](indicators/averages/ama/analysis.md) - * [Charts](indicators/averages/ama/charts.md) - * [DEMA - Double Exponential Moving Average](indicators/averages/dema/dema.md) - * [Calculation](indicators/averages/dema/calc.md) - * [Analysis](indicators/averages/dema/analysis.md) - * [Charts](indicators/averages/dema/charts.md) - * [DSMA - Deviation Scaled Moving Average](indicators/averages/dsma/dsma.md) - * [Calculation](indicators/averages/dsma/calculation.md) - * [Quality](indicators/averages/dsma/quality.md) - * [Charts](indicators/averages/dsma/charts.md) - * [DWMA - Double Weighted Moving Average](indicators/averages/dwma/calculation.md) - * [Calculation](indicators/averages/dwma/calculation.md) - * [Quality](indicators/averages/dwma/quality.md) - * [Charts](indicators/averages/dwma/charts.md) - * [EMA - Exponential Moving Average](indicators/averages/ema/ema.md) - * [Calculation](indicators/averages/ema/calculation.md) - * [Quality](indicators/averages/ema/quality.md) - * [Charts](indicators/averages/ema/charts.md) - * EPMA - Endpoint Moving Average - * FRAMA - Fractal Adaptive Moving Average - * FWMA - Fibonacci-Weighted Moving Average - * GMA - Gaussian-Weighted Moving Average - * HMA - Hull Moving Average - * HTIT - Hilbert Transform Instantaneous Trendline - * HWMA - Holt-Winter Moving Average - * JMA - Jurik Moving Average - * KAMA - Kaufman's Adaptive Moving Average - * LTMA - Laguerre Transform Moving Average - * MAAF - Median-Average Adaptive Filter - * MAMA - MESA Adaptive Moving Average - * MGDI - McGinley Dynamic Index - * MMA - Modified Moving Average - * QEMA - Quad Exponential Moving Average - * REMA - Regularized Exponential Moving Average - * RMA - wildeR Moving Average - * SINEMA - Sine-Weighted Moving Average - * [SMA - Simple Moving Average](indicators/averages/sma/sma.md) - * [Charts](indicators/averages/sma/charts.md) - * SMMA - Smoothed Moving Average - * T3 - Tillson T3 Moving Average - * [TEMA - Triple Exponential Moving Average](indicators/averages/tema/tema.md) - * [Calculation](indicators/averages/tema/calc.md) - * [Analysis](indicators/averages/tema/analysis.md) - * [Charts](indicators/averages/tema/charts.md) - * TRIMA - Triangular Moving Average - * VIDYA - Variable Index Dynamic Average - * WMA - Weighted Moving Average - * ZLEMA - Weighted Moving Average - * Trends - * Momentum - * Oscillators - * Volatility - * Volume diff --git a/docs/essays/realtime.md b/docs/essays/realtime.md deleted file mode 100644 index 13a3f46f..00000000 --- a/docs/essays/realtime.md +++ /dev/null @@ -1,43 +0,0 @@ -# Historical vs. Real-time Indicators: A Tale of Two Approaches - -**Indicators for historical analysis** are like long automation trains. They zoom through a complete set of provided historical data, crunching numbers faster in the series than you can say "bullish pattern." These indicators have the luxury of seeing the big picture all at once, from the oldest to the most current data point. That is allowing them to make end-to-end calculations with a bird's-eye view of market trends. - -On the flip side, **real-time indicators** are more like surfers riding the wave of not-yet-known incoming data. They process information as it arrives, often dealing with updates and corrections to the most recent data point. - -"*Currently the Close value of the bar is at \$3.10. Actually, it is at \$3.20. No, scrape that, it is at \$3.25, which also makes a new High of the current bar.*" - -It's a bit like trying to predict the ocean's next move while you're already on the wave – exciting, but challenging! Unknown upcoming data trends alongside with the constant possiblity of corrections of the last provided value - that makes historical analysis indicators practically useless; they are fine-tuned to calculate an output on a well-known array of all known and valid historical inputs. - - -### The High-Frequency Data Dilemma - -Imagine you attach your system to an active forex or crypto ticker, and you're receiving up to 200 updates per second to form a single one-second bar. 200 updates per second is not uncommon during an active trading rally of the day, sometimes exceeding 500 updates/second. That's a lot of data to process in real-time, right? Let's break it down: - -- In one second: Up to 200 updates -- In one minute: 12,000 updates -- In one hour: 720,000 updates -- In 24 hours: 17,280,000 updates - -Now, if we're talking about gathering 24 hours of one-second bars, we're looking at `86,400` data points (60 seconds * 60 minutes * 24 hours). And every single time we receive a new update (or a signal that a new bar started so the last bar is now sealed), we need to crunch through nearly 100,000 datapoints. And do that 200 times per second. That's the calculation demand that will make even the most hard-core historical analysis indicator choke and give up. - -### The Great Calculation Showdown - -Let's compare how our historical and real-time approaches would handle this data tsunami: - -**Historical Analysis Approach:** - -- Imagine recalculating the entire history with each new or updated data point. It's like rewriting the entire encyclopedia every time you learn a new fact. With 17,280,000 updates in a day , you'd be needing: -- `17,280,000 * 86,400 = 1,492,992,000,000` calculations. -- That's nearly 1.5 trillion calculations! Your poor computer might just decide to pack its bags and go on vacation. - -**Real-time Analysis Approach:** - -- Our real-time indicator doesn't need to recalculate the entire history. It just processes each new (or updated) data point as it arrives, and spits out the result. So, we're looking at a mere 17,280,000 calculations per day, one single calculation per each update. - -### Why This Matters - -This enormous difference in calculation requirements isn't just about saving your computer from a meltdown. It's about providing traders with insights when they use tens of indicators with many parameter variations across hundreds of tracked symbols. Real-time indicators allow for quicker decision-making, more responsive trading strategies, and the ability to catch market movements as they happen. - -So, the next time someone tells you that fine-tuned historical indicators are basically faster than performance of real-time indicators, you can wow them with your newfound knowledge. Just remember, in the world of technical analysis, being real-time isn't just a feature – it's a superpower! - -**Real-time analysis is like having a super-efficient personal assistant who only tells you what's new, while historical analysis is like that friend who insists on retelling you their entire life story every time you meet up for coffee.** \ No newline at end of file diff --git a/docs/img/dotpeek.png b/docs/img/dotpeek.png deleted file mode 100644 index 5d2bb67fa3738a31d40f26a349e0fa645a20156d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177156 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 z 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

SQS=*CaVQt);>bD~&hX%?aC5&?&50 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 z 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%0AkDtLh z?=hGot30RFrQL=d5F`SsT3nE=y&KLfkU+9XXIJ+IaZM3(h_>Av-}y>&^YPg;o_f;~ z=yFLgp-UD`5QflAxuW5Dc51|ss`yz^-b69@rw&>=Du2;b%N0TbKAyd7Woza$e~8u@ z@A{Rh$&2?-XDhnAmrr<+>LWN6 zZfIC9b5)t;gY2nOr?Aj6^zZ%+6#ACh^)YO6T?4g_U1DsD*xxx@kb;2Y$zyrRJaJw3 Fe*<@Nwd4Q* diff --git a/docs/img/emaweights.svg b/docs/img/emaweights.svg deleted file mode 100644 index 384ce713..00000000 --- a/docs/img/emaweights.svg +++ /dev/null @@ -1,434 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EMA(10) Weights Chart - - - - - - - - - - - - -1 - - - - 0 - - - - 1 - - - - 2 - - - - 3 - - - - 4 - - - - 5 - - - - 6 - - - - 7 - - - - 8 - - - - 9 - - - - 10 - - - - 11 - - - - 12 - - - - 13 - - - - 14 - - - - 15 - - - - 16 - - - - 17 - - - - 18 - - - - 19 - - - - 20 - - - - 21 - - - - 22 - - - - 23 - - - - 24 - - - - 25 - - - - 26 - - - - 27 - - - - 28 - - - - 29 - - - - 30 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.02 - - - - 0.04 - - - - 0.06 - - - - 0.08 - - - - 0.1 - - - - 0.12 - - - - 0.14 - - - - 0.16 - - - - 0.18 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/img/quotes.gif b/docs/img/quotes.gif deleted file mode 100644 index f7ffdd1ba88a769df34f18ccf1e694749d8bf100..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 780780 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%0D3FEayRRP! zpth^ZqvSbtmV0yicWueGHaL__A44x1SEhEj`KNLf3P9d_b-C$;-o$Z$y$gNkx^DyRGL zymykQ?{spdeDE+K4?Ug3DW3{to;1%%PO}k-U-)2s34r*&6S)fd_CI7uH`{hnKt7G5wz$d*$eDHU5M4*l62)qKkaS;?$UL0jLn*j7edhGKfA^14I z-QlqSjCx63;@8Jk#Ibtw!({b@$BN?hu_5PUyH>To}@8h5I zZpTJZ0#cKx=!+&ubhek3Djo<>5vleeIu@0Od+y^TBANF)1ZdC_9b61F5CEGT4viK) zikmehq8KMyvsp>n=HYNCPKfOOjZ->m207D-KyZDoM660%JCx#vcrXAAYG{KR_SuGh zx`Chl45&cc@CGn|1~2P$q$OssK}nzzlAJ(RwtS;P0GLZ~mHH1i2opID6%C#ALDX6t zWjM}}LP;_z)Ks7}QA0S&N58U2LI>o&1$G8i@~jyf+zC(bICs- zu-?u+E$!M|$f?$_3}gNA_6g(Qz#;tDaiRQLw>{53vGhe*q+vD z6k(%tzrR7=UJI^OV<`NVN`WNQehR_9DZ z8ZrTE#D!)1h5!TC}`Usf=%=)$$HKEq0k!<1UJH08@N z2YT=9<+|G8<4&Bf!2z%e*{&BDLuSG_)_~1Qt^$Co&=G(;S>A0lk%^(*>4_zd5O~Y^ zwTzayvu9pLWQVso`iz>(D%rF^BzKC{`4zW=wTv6+P)`Qr4UrKo!~wL5VEDANj~p@{ zPoP1gOH?|0DITkW2yH3XLe5e?VhNomrL-mU<`5VPu~au4jBGE>h6u`rGbfehQ1`9V zoSSx>6)_0=nJsi!{yyz6=C&m+|4JDzRkj^vp&x86+h{K?#bOJo!tfLEQT^2QYxS zUfz&hA7Crh$b^N-yo?_X2hh+2xB&_gfvlJ-Si94xWB7fvO=z>?g6nwJ)*VtE!nq_M zxho7MvN+G0)`D0o^`+dBv~!cy8wg15H}E?}otDlqTk)MjK4BhwKLXz?*$Y%-l7M2< zFBCmmEs@-V?hod%Ps&;`dmCdl%~FRXmu9##np0=FsTfjbX32KN-rnpkQAl1zC)qwF z#aM5KzvshhCk!C-I%#jlmA`f~91U-{1P>SORybq#_y_jPhD5+dWnvX-p~YHZV`b(Qc?Lu%r2s{-(F*e= zaS<3*Ovh^DgbZzV5v!9*_$4~~@Ez_Tg4@wxppbfkaR4N61x@e-W+Zb121{82R~cbQ z`OE(V%wOHw&BMew>zK$M=8(5l&y%gzYDN>}4co z!70fUb!!!EXZ9u0)L?*h4}zr+I+hM=FfT@iV76xfM}P%ZU<4OHX-4E~isb%Xzz{ci z5)KPx8s@Ik03?6~Sa1XwaBl?= zcU*y8UL{Fmu?gdlFA!#gK5C9KvJ7I9>wC=!n2lC2dO!5DgM zsbQAmIV*{Zmg9TeC>^>)Cp1|qHbWHkaTIe#kOfw71ao+AhxvNOQ$5vEc6}2aS1|)sm3r^fP03jZAdr!q zsgd~EIDCheKO%rTVMJauHK}Nl{W*MtlVmM)LV@uLK~$i^fS_Fzpi@(Ci_tPTW_k@& zMe_C~A+m!8Z~;t^1y>*fLwACdCQT;fIS^VHjX49+m4g*iG7;kfG+LuJdZRdMqcXZP zJnAqf)1yEdq#d)PLh3OqQ=}jBqd+R731FdRSSl+L4*_!k0+RtFkOf)L1Q^f&M@pm* zLoivSxJPt zNrRM0kBUeO0H}@HM{D$`w<$iLaveIhmrKE4f-z(VZ~<><1zd0ed-F%OCm^l*nE;As zz5@V%n086Il(VjfjZb8eg)fA2j|JA-d3sG-!@WD3VjNfwWU@{HbPPre#d1 zmJO$LYhaiM6!U&#dx5pV%q0FdG-v$`Tnj}S^~RwQC%RSbI?;sdegWuHu&nVc!7 zX%;n|hJXthir@By>?DEMmuc}D3+~8H2IOMTrg1I%JX9ilUGz?(f*ldG9nnK+APSJZ z8a(g`D#!|#n^l*g@LQO-`riyF! zZDu7Ah+CG_XElxccO2E4i?Dt0Vv`DhsvO{xRxpqgMv%rpFN{(zpv5`FHVHoifOisN z1TeU|tCgC$j3P&yc*t=Mh$ZT_eE#s07D8K_QN^yWC2Gt&ui6AC(8>};f>m3lwLMo? z5Q>C(Mux*ASfqn`o#34SDTfMCE?@?(3#JjpRxUh9VaK?c&RCzk>!yv^4WPx2GD)&q zmw)?v4F`x;DN7;ihJgn7Cp>|cAUmO|d1GgTQ{S7Nr@~(#f&e?I1OO`nbBMIgDH!9B zU@99|C}ArI0c?@^aTzhOocRIrOR*byxgBg*5aKt{hO(RnaaJ2W;Zh)==6Dvgfggox zU?;Nd_FW-cwUHqy?{tr96IlE86ko!6D=4BDP@x zmAfvil`4$JgQvwoELxZs{uAmZ!26@axA2L{wxG?cw`QSjRNE46QeADSk|Wo~ErC^% zaSpV~4k4&x8)}QX3Wr=Ubi2kC!(kD-){+F=ieOd{2k{4fV5bGCXvDw*^ox<4nZ}w~ zxFc32GrY3OXSV$NzpJ)&g+O`0d4)X33lyk zH(hjtPTt^bW`?#XOdMqAaL#F`-HSz5@40K)DgojKs3Xe77=20GFC~Ob8EKJ5V{l7F)3!d6k}7EK3NA{5w7{)^B{Z&<%(w z;5Anysl30NZltLrrWmm(+sDkpinKXpv9yhg)NV5?D#hd~6RZFO8<EewcP`Ql`WCu4bn+bx`#%M6``TT=}j zh403a9NjRwadhM8#?c|-=vF{l&@sA4hlry?)X`wz==76NLQrWzL9qZ8@#BBE_dfTW z^PcllM;TbkQdAPug{_yxa{KxEK7O1`|JvLUpSeB!M*6Lo=Bt+>cdy1tU5CvSUMvUE z_&=K}7#gIf`=#FytyR>G_V|-Dd6F^tC4pH$PSX0XdkbRN{X6GIH}62`@;$_B@4t?M za+w2D;?ya*(wjH;V$S#o>vxRK=DI8k-ySn2EI;Zid)%MWKeqPvaUl*LwspgEd^|kn zN(u0UZbLA4*1O6>Cw^`$S_^ zuO(Yyb+XZA&A+{>Mo~>qXqp*8gsJ3_oeA3UOusI+FRB~tG2i_ESSRdp?QeJU?Z-PF^u)eF)e@*&P*byfC z+bz#*0^<=w-3%(3_O^hhO%KI?C+u53k1|;Qsx!k5FLo<2L=m- zro=1(i>1!lEa}BKr#JPQj<@TRusEzsfEneSww-VxFC#y4(`q6~Qol7^%OCSpOiG*g zk$EhF{$yBWXlWsXEbiQwq1XI#*`I zrM^w|0N8#6bS~DM^w7DUrU@cuN*K3sG|q6Ooc#8OibjuZc(j`{y=lK3m?5MDb8?kz z_FieX$~q1J17D4eZps|reG7gH`JfWNcU{7&W2gA%O}YUw=%Vkn8+P;J|H+!j*FA~5 z<}Rw2&$xIcx>#^+_;HDJ*P=B`BF(AwMG?GY&*#-FmPqF|*9ET_!mrT>qLBydxXE|o zq+qGOjrIFi!-%<+aiK%4l=%&nXF%8H)Ljq#%2J0t@B6JDpTx&<_^z!k;U8YOddADI z<JdQg%;@FV3PYuI;Z$`n@j7qdiK)apF?Fsm z;Ruk!1ID_9~dLQL2+(Z)SH_y4`0=8#PN+cgkO>9z@n9el7O~Wy9XoT;BfsjkeG} zcB9J2*7qofFEU*S%3%U&ni9Pu5a?W4US&$H2>EZ6Q7h$dadqmG^$dx#P)nZOjEFGM zRKUF~9ZpH|-5;^lb;XeKy@uuL3Ax5L+Ktv8k^>m%_G^f~FAX|;{9mEc?0|8}*Eoav zTQ}16MmU7IFfCeR1#03k3%ZR#x&=)gj2@*Azl~G+Ln8g)waa42+`@-Tv>mg^`OUET zi9P3DuENY3xk-VfgON-JiwW&N*=p_8zJp?v$vg(Bzzg+Jc3)J#ziG_jRnto}V&y~w zS0Hsz(l==zFgK=tGt&vHtFZqu_mR)Q9Of?LVk|=RU#{m@>22bqLZhEfq~wFqY*Wt5 zc@069%Zni&RFz)L>Zr)EziVmj>;`6nZhZEkv3~iZUBQIQ4i7prAbiS5Qn9&#VvO2E4&@a*~_a(*nzEsdeJvX3a^*vsh@4Z~>wZZQT+m;PkMfr>u zn#2&-8xrxBlMhr<13lxgPFa$*&aySKC;Y+1`yU{(n_Eq2xu=reDJ^gh;h_eqN~ zfNH1<`1Y`*W_*m^8^L=8Wo<{3=olAA)21ayOgp1iqZ_nKO4^VV_O1Q5gT&ow(3^Hc z!+n1TRn)sfzaFTY^iEZEs&msm)7T2_^L zSKEt*rxAcEO|LV=7%?Q~!bcsR%7doQo)|$|jqR8GJrg>aSuucAtH;?+TiB`Z^wdoV&p1H*38lQKF~itrvyFf)g+J(7$_RGk8=eDOJ?G{L_5lF(>;2I*-Pe;O-HZ zY)^6E-OYCisnO}O4};UL2$6qICz;ik4;L<=l;ZIOL^@d8}~&VSOS z!-uh!uG_$kqi!nSS3{`2)oRDnu`}y#KILTN-XL-4!ef4i5A8i}(zA^>mX*z)+}J=1 zVdK`ynpHpIQu`K)d7nbB+PT7ac;vY2p&cfl%)?$G`5&`bI7pY=_VRZgj;&E;dH8Lk zX&p5+I1e0Q@UK>=;(_$0v_m_MqoP6UvdkTiPZXO?`_y|E{2Xuu{VQDqD{4j>tNHEH z%6Hz9XAqoi-)7#YlC>-sJf`!9*L@A`j-0-5Fe~i3S9j9C`@FpTr!i;%V_{&?bMW6E zN9@zDYTv#qsdlcr+n|!pxDTgRp4AL3ZG(!ku4f1&52?1^+Jg=&B!qB`=WB2TDz$`I z$xIvyTN1O>lDR`Oaf~jNx)il0Bo1zJ`31JFJu}-E?lu^@j>s?N4qoCg&ztxaQ?YPZ{ zzBcmee6Pi&zke#@6VO&X3#7^TW|qFmT|zwai(LSHNO?$p`CLxoQp=t|h`yqjVQDvw z{VipuRQ0>KXi1;cg$>1(YvpgA&_?k^KP>LA3`G;h4Jrf-3<%&_+Gscw;kU9wa>^w!RLf~}X$lmZTJ z81YRkp{d(ObTHhfTT$B9O?e{>yja|zk^#YH=BHL_-Ol+G&6C2n? zWb{pYK4`ZIGwC#5OaX^K#E16-4htrFWCy~*nr$W7I-^$bvLf_i>Qx}ki8WlmAMmJB z<4HX`Nyv#(i4{c{Ix2i>)9RZAd;4cL_8JI%qx(DK`BF`;43heAT%f|AqXBkpY+bPp zktmR2nIn`H!OCFU=3hO=m>cGK;>a2~BiO3!|BghgYbSn8@+%#rmG>f~vN%6WyR_Es zKZi%4XN2Z_5bk=pE5m%WtcedyqgF=~JzvYo9%Z^p(7r`r^F6N#mqf=O6PyiY*0ycR zg|9xMq+f6nJ5_+%qWvY(i7`fzDymm~Mg#wP>t2H4P3oOK8N?I;z`A7a<8^j{HITo* ziMF47oN|PMY5{_ze}EB?MCwpGkje`(BER(0chh2_x|CssY`wy`db&?6GRbNBXBy>& z5__(k;UX?H7D{GCmaz%)+(mUlg|mx{vM%f|M~kj`7uz&DeJ0DwEf=Z;6n-XH&%uaY zD#SsU_s@3NPe`%#a`A=a0taro=Nm`^_+^KI48^q!B$dq`9*Z63_2DwTQth+CoX@s| zJTnz|d_uS6>9S#qUX|c+VorMA8(Y>KTow@APQ2b9b)nY>76~wF9BW%Cu#YEa9rTvf ziP#^ZXyRj;5LjNLD0`OIMZL56f73$rq}-kXTHQ7Qz8i(@22$FwT8!!Gt?MCVh|W!e zfM=fG3wn|dk1o>M-ra9gyt|AKcNQK|5p7Wk88yq9!Sk;fNama6Oa`0@eDb_xIu!Jl zaP@Elb_0OgpzOS9L!q74`A zYhsePOqFx!(A;DCUa?Z*6r8hrX3?`@&g#T4Ir~ZnDA#^@*?cLMY7pln$_-Pw^`Ph8 z4IIo91^w7_Zv_?la)@)x(|_StbNE16O`rr<=0H!}NyDUC{cOD- zS?#B3sIf=?pI@A(qwUO~n}$@#cxurhJm)hyzL+AvJRw1ICqaR7N;VAzT5$}w`M9gnMDk^y=r}8dsLMwQ}fbQ ztIcj&xhRo-4|oaN*DB}3=tDhw(Hf66`TR%2T@V28{X$vurfp-5V7h{+nwU9zw@+oDA3#l0hb+_s(>MU%x=Ay)y(e7z zNa0E zzfEyvDdh3Z=U2bi9nF^?#e}K;@%^e!L6*2kXI1oKP^d$IX$`pibi~CH#CQm>kw?5L zNARZripsX}u{#;f;js=5S?yl?%`QI!a##>4?+GyZ)N|E5aFEi^`6q#Q(dLFlXOSN4 zL8G95L~E^-vPxT*yx|kz?E8&cN%ms7E$ej@0K z9HOl#P^VC+ITgwk3gVn$)tF@brP;~PQm{E`5A=c?T|4)k2L}$FDvk-7?X}V?I*1N8 zSH5ZXkXcT-Y5cVK>Da6+b}VU+ED$P$FY8== zjC1_wXm9(rpXbbV(r(bFh<(~hv6M%%uPZ_Cjd8JIP#!g>pTLQ-rO{P?F?Fe~gYs6RSlvVp}kLi6#IWi#gp z%~DA8lPo5qspBQZRW0s1QRR`$%ki$4m6=10e`>qmG-4}Fv#7@3!U}N`K%!)bC6>|j z#Tn%IbO>QlC-TJk+6!l|w#r9k&qN<*}$zp}!90BpC99{+jF zqdykqsfq4O<@FD;&-4gwS!y&+7umdZpl5!ILmzkO6@t~tUA>&4*NI<@W#LM5S;{!V zN*;cCYfL?VxR#x$kgC%mmYPTI19xUdo{L;@A1A!A+f?k#+3Lk+w$$$?%bLlmoMgI5;@iJSdl7nwVkB#E9AutL$`CsUp#+-Gjr zJMFim%eOfBR{{>$JwOj(4-E#1`EBa9^R0P|2QvwGrNAOoIxs`9ANR5Fk|!Qsk}u|6 zb>oE)TF70r?t`b;P=-1m(lUwB)C+j8^X@VQYBKYx(~vzGH8VV1r}`hS45fyTPHpQ~ ze1`t@=|RcqpsLydCOXODp-+rHRx5>7v!2tO^xIn%0^2p|+f?$Hw5rQ#y4ryHYV(f7 z5l1Vuys^)y!n;a(DzpE!ELYojgSFiQ*!TMiz5s%vr@H@W8QgPdL)=I?uy2E0w^CmM5)B=lSf01bYvX+O9#R4?<>?H^|W5j_*EI}Gq zXSKh4*SIvzNLDU+GkW{;G@*(YJ@Ir!Bm1c^{$+W`n!+2lZ$HFZvs@f}u}^5vNo)KJ z>`x+VUT=x&8|%|OHWs72PxKgiVH#eULI?`<0Y?v8duu|17GHTKx;DfRhM@V}O}{-$ zU)(H1(qB;y75rFu!6m=^`@86Jjna9`4iF$D@cI*OApGN<;v~TB`LDZ=fT}#@%ICjo z@|2M{5DVdV^P}JQ@BL=Qt~6Z&B^OE*1z!A-B;k3&E>v%#6cF>_@JPNKS$(tRK@z`Q z9}?eOWVm-HrKakUtDNUY*U~jM!ypE4%uO%K7gdJZ*%z=7sgS|YvltV|kVAm?iha)5 zdj&^k=OiCyYz&AS4K@#jZV{H<02+}Q6h|IPhJaEbC&>c{IyxjVB{eNQBQq;IEjc$O z8J?4rla~(T;pP#e=ebu|MZU{ZLw}c^mYIe1!NW(Cwg>FY%2n-5{VZ=*S0duyQH}= z4(p^0+MO&S$RO%;Nw2%rrOh|?5TWHgPCy8lUUQrEfEr)n|JFY9q(_tvtnUZruq52U zLU>h+OrL_FnX@~vBzW{Y%Nr{`x6{}$1f?-Xwi~`5>+DQE z{1+S}%M6M+s zep09#@BOgJ=v~1=_*41H?4Q8L`QK{*w87wI@a=y%>H>SH8)$z*wBq7#p)zs;>`fy9 z98*_4ntZLPEtMz4d)GK6uy-~!h2I)6dgi2kg5SuHY>4q>(xjXWp*R34*idn7GM@tgC{$yvbN=Zk38ZqVaCE{O&llSqb>x*~-%|e~e?SHS; zUfqCbtMTiD&{TjctW3{{?Zb38FK;--PD1PYiTJz)v3;fAc@NY4r9Um?{ewbtBN|=$6NVbWsTkPFrcN5`A%&X938$WdT$be>HHP(IM zBR-EMh5HK20`F zJY*0a8DJj>m#@74uvsdh@2t=t@+*nkH@z5t9VxMN=g~9C{hME&XIV*LY-=WdfA%AC z@7vu+DDT^XTGnlhHEf0*_cgDL=PQg}#{kYx^*CBXtx}_4T;SuaAwJ#bP&`{ASS$rM z1d=7a0&(I)lN+7AJw}+TiEG4Iu4VN(V*$1kNqrcGeV*_w$FgwzJW>C73B-~9bI?*q znor-P8D^aJX*DXiEmC!g09=H49CW|&)e2dC`wrj3r0t9$T#<_i&A$>?{fRR#Isiho zg~*?74jG6!UywKs4}Aoa1cLiu3~I0Mx7sf%JC|n2RE54)IpFaHS`vhe*>LHJx$XX& zB~evA{cJoDwl~hiQM=--)JqV>!_9f~quvV1N%{BM`cW%BVMeUR*@pvgA)i;XZv2th zhRsGHyxV8mXx;m`KkK?nQx~o`&r}T0X*6m^cMi4Q4eZDXSq*!6_jcF(yEU3@VC|0k zv_nh8gZuXU>y;0_v67~gWfgvXJ}y{nVx%n zTr~XGIuw4b8}mPFbNHn%q3OO%QhzG)_EmgZ9stSnQQR!nkK3psQNU2`+SoAApsz)uOXl573iAbUT!xW%-getyv*PTIbqh0beZ?$H&w! zuFf|cci_c9fUO+&t1(850Ec9lA1dq}vnl%7UIJD`6of?Vq>y2%KBeS7Bq308bY#6w z^Jz-~mPe8gK(|R9p4#1Oou|C+d}$r^)VT^mHqke~e>nl--}CV2O96U4AXMR!8OLKB zjiPcWa%(N`ag+=sfCXRqv=pL-xm%VW?vb=yKVZJ2k;2d%aPXT8)=dLtZ}(E2eseaH zs;qiZl`2G|_@hcPk$Y~od^S~U+u;TWbod@X_K@tz)&KFGMX_2&eqLnYzwQqHOk4*v zN88Mu$G;;cgH34t>4Z~|qT|)7S@R(oQrU^}z54ojAgr~S|C7B*WUt4)8R5E%%_DNp zu1%5Cw2MtGH#pODl`rt;*Ny9c>@1Hcl46ROdoJ4eDC=Di4WMxMf{wpAzTifYDm~Sl zku2prI*~FJDAe(}NP@Wi!Sct~<_`;fg?y=PH(nsm-whU^TeUvup^+6xGzA#WHP3Lv zfekChl0~S1_UqM;2+k9hm9M$k+lKYH$H{`7XCHj(W|4Xk`h@GG>JrM7#97EfqEiTi zz3am75AGjE<n0|P z%Rs4p#1+GqdJ?7zXhQ3ZwMJvg*cLuwox@FSF+w z+A%Kw=V1HDmt0zkVE4Nc8rADr{qHkpjm=*Z|N3@4zqy{yYbJtUM;r^5ceX+<@Qli) zy&Ux2_xZ5pQvW$B%ryR7L-dlMH>QPLeB3$sgW{ZEF)szag@q-b`Am6k0kBb>coLXn zgUz?o^)1+X^NZWO6!O=2Dt;sZnLqC7`Eiv#O z1<_HBgktlSEF1vtH~7VCQ(qEBJ+D{XM#=RJ5r4{LP4L!4FrYI#*e zL>rA7>9XE$t7~Xeknxf=+kb?#R_eNR)j#ds+Ku81Unjni9agzGeYaoHy|yttpt0{I z7Pk`mzdL-T1#NhO9~agAcWZ*qv}8O*1h~_(iqxD<%bEMaz?EY^<*++ie)y615@ytK z9F#3uJ{IxsPm#uGVDAI>>?^?xSAXdVzFl=nth#vsS{=_ORx{sMm}n@aU&k#Co|{9T^MV4m|(jQS3y`H0Pk1eOzXmlE9l5k3^C`FLR!3O z6huE71hi?<*^57~7DN)+O4J0I$@aNFjf7a)XxEk5#CZCBL`%B3uJ(d9;IOSm_h?(s z{bCT!Ax)Hs+Gislz6 z;H$k{z6Iw?yWlr=F~Ng{~c8(3o+S+k2N{1CTc&m)>doMgUv z9i=5-r_g)uso(%(uZ((q`HvgmGjq0NE5qcMUdiXi!>~VaWyiaGULtLmDL_BiAY4*% zMSuT$Jd-D!LATi$Jq$DyK=NdBt)yL0L`{Ee9Kk z;KvHI0b(e_VN5ATyz^w3=?iIg)-c#!DbQbOq?Vo;lr%wj>)1Vso@x<)`B9UV^m}MeT z??D(t4kLYI6gt%bBW#IJERA1ANeGvmCQ0q<2j;ptupm%=Ge##Vl7(m8hhP>g!6ho* zd!1jZ>{!37^hVj8*96uQ7S%p^?g35=&f5tK9_A`23$W%aDOj5iW^9Tx+=l<2AwG&x zP$<5{f0hJ9tl#|k%aq%LQ*_-&Z3x9h1!2f;{l>}jhDF^I$^R%i&t4}N7sxbv7>Y<~ z?w*%h>x(_gB9FaQgR!@6eAB(LA^UghQkW?Y%x*gGY08Y14~ga!vk7uFir!TaNMl9E zImz4{#40KT?@wIF8Mkq1a>+E&Mfw#JJ?`a-MhgxY_BTMd$VF@^1;8ZX3XlE0O}o1; ztg_3J2^6vjEbI3c?{PpyZmc{<9E+s!1sDm$by#6em7@APa1oM6OtZ_Y?Y?^ikN!|_ z{cbFn?0<#{#!J?67Don9Ln3{gc-!5*M|p#8pAJ93Wx^dd`)c;VZ=u9l@mrK*4Zh71r5+x%_te4L&ys% zXeHen=B%1xt}7kfp4SQXQ`W#30{ zV1Y66di6)2uhH%DbQV)hs{njFNcvr2oaRB58pLzj52W$n8)5CbU+H$GT#{*GLm^5TL3q?Frn&ni8?cqBmMy}IfFa80JD zH)IVKfrE$4^m?PC3}$F9;`%NE5FJwA#TgoGsPOHg5(2yY4VP*jp;9R=Ki?JSUkWIR zGRhNsFWrIWk&1dckH9+Bd;c|-I}}zlWMsXLgI4-O1j#7vsR%^{M=h0b4o8eIT&A&v zX_ppO-rc3Rr;ufT@5oI4W?S>>A0xu7GR(p?`cVr^131k4304{_pztUSmr72Nkg^|^>Uk5&EhY%NjAaZ(KY?}_z$P1btF2dYRG zL0qTvAwL?Uw5dF3b@?Hht#O1`A4-*^m3De1Q+Q>HlkH^K^f70Gmy-WamU#t4JW&u% zMTJa3bb9#Tu0OIu)jV)168zp@PQx`Iy}Uei<0@B(NATu9guG<@kc$n zD|(LU!T)6mPPQrT1*W>C`9g5Fo!A~Vx^U*bl2=sacdbb%oN-pL%Qo#D;l_Z?u--=9 zZo0=xqUZ?Nj6-(-n;I)CI>nlyljYhgHsbwaF7FFwbHxX>3J*MBo&fX_$l^SWp%_AG zAIvzTp{uj}r~?R!f7W6RVi7v)z6NEKg><37+k>3Up zgonqvL2W2A@E4kpzsojgDC2>4)dr+0{7qFm^wO|YYshT+K2!w-er0bpCvrWZP^50K zq*0#}q5$;E0aQ7F23YO?yD}iRI&!e02%G;LaN&;|xb%lge}l3!Id5<7)?vsxVCk1E&q81J*tN4Woi!xD;j=z&gn`h>LehfY2nIqglV;tioch3%%Z6=voRLD2BJ|W(LJ7_drSdnun;XOjh}U& zpDsth08RcW&9#1-5Cs5v_#U_gmVLMJ=k5DbD}tOgJrTu3Lhb&*F(u0HrsLoLcw3$D zmtSK8oK4vMj@c^`*rPkt+Wnn*HG|h*@){&GYdOR%{3}yI@yo23R*(c>K$Q!TY{wqb zoYC(?uY}GzQJ@?lP8)a|nE>ABLs55j~ocRw~mxWstzVC@W;FA8Rhg4z)_{hibK!n znUkLY7I;~6?c?aJ#f_FlZV?7R1G=c<)HB;3@sjC(d~?mZ)HvA%!M*T(krvD0(&P?qI!)p6{vz_pM0n+*@l^=jKJ;e7 z8|w>3A~Q|7t~o}tcZ6x?&qhHPW`3Fyj$K1%ws5drj7gNTT`U*~{s&xpd9d{E=ndm% zCW4YE6&iV|--!%mp4G-dev%czkvm{GCG~p4waD+Pi4YuNMoIJxpxA_`r^nb5!+Xoh z(n(lsC>G;FYVMnuFzbu`Ro-`w-*N-L&1TkT*MGkm9Awe52=|HfQU3N=AHao@2)H+W z)L$#*^evTU)2(K~`=|6D{TKlJ+vCxN1Gx_eJEP(fjPL$7;3$Lr-+nW`{Pt1riwBW_ zFKep)I*vewCMANj!nb-ohEfMoG+2bEXKTmugbmUWd+l519J0>c-hJW8S?P2zdOph5 zzNoo5t*SpzwmWQ5{?|}c!xNgtCW|8{b1V5-^J>1!jM8#?WyJ$!=EKF%ss!3M+Dd81 z0Bh7VW;x>+evjew0&&ZS!2|7Wo9yBy*(5?(B6;vE75V91?<~n(b zMXb4M$;DF~2qqCRbS8WOVNjwF%I0jC$r{W&d`lJm19cm|?n6S~-t*$ZN{|mtOEW?V zgT4)tA1tM6nwF=PeOWjGT{1g1Q@YGW(NY}MxnZu=9zR1w%28*AO&(KNz;ptYQW?_y zHX@m!17d2l;UsGoEaZjGhcQ(dVW@Owa9u|(TxL9JC1(9uJCDwe5L(>w-*~2Jy!KW~ z(5=XW$gBE9dei`v6HkR&8`X^DvxIODq?ih)6A~$0-snN(1)O^IMYh0`K@#6VGL+Rg zlnUYw$`%Qp8()ycT4uAQL~LSj!1Wy<)5I`yjj-k4SMHr8I1r?GSk9l0;fCIcQh8b zK9uZ?6+WwtRTdlf_Y|*ylII$(6_y)kia~=N%^+DIJA!OmJazEDABTvfoUK6>gO$b8 zqWL?`VftK!v4!=7O=W+K2#=q+aUGY@xdVd_S}|Qz%k^Yzt2O{N>gBXNO&W9pGC3js z8M?YrWjTo%j$(*%;MSp9>Un9O5wz-dQiu{f@d2tO&CHU;z-`KU;iM;E4rNc#TyKz@ zO%b@4ssa_M{(OV&4FRkSz?o9LvLAgKwWY;ttxlLqI}O0{=60UEKW~Y2EKNG$@yQah z9(j|O-w8Zhg9H`nrj*J$(CAwW66>1u6schEti^C-92*r-Z>r|~q+epeazX+D*9 z3$pjEESn4^f$zMf+ywPvy^R0t`;-u?*$^x2RCUzOqtzKpMd|rr`7?k>{eUJfn?ht!al_CsFnMpKMZ|0xwhV8bHG}X!h5OIa^k!&H~sIV26zt z#CZU4%)l`px0)fo!!fL48r1HI9K(-_hSWe}83=hV41vVDYSt+P9w=@5BC1~urL#mg zMFF8{`&2VY$FG@phd0v6F$kIB;cKK+#k$wcEQ%slG3+EFC&XpE zN+$e+^`VDoBNi&94#IvtgsHT8FkFu@;F+VqRO<95?LI3OKdOYO2akfhTJEgs zP^G)&sLTEH{9h0~m;T;N3Eb6N6+DzM$71Et_x{*yXB5R=In-yUf;I#`BSToj4Nt5| z0t{#@sK^lulje7^xcmkv&)u(QT6Bi;F~7RE6X8{>B0FAS=uCP+b?W^V_$YKB!*wQQ z+1Wo+fb|1QL+{7LC(=?6|GPeLSDlfPA9Xg(E&08bB9rO*lLFTM?SGDUA!+}4| z4>~+9sb^qyTP7%WYU^El$p9Gu=<#o9P=qIMUt9xGZoWGxQB$=xVCrr=@NM!OfZK{$ zxNu-W-Z4W(1C^#d(kWW7(9O_CO$U1L@D*W33e4etJTD@uYVBg170!Rk{Bo$vvL zho}{BoDdF5zpR%y)2QCPRlat1B&E(;fR2JB#)^Bndch`lc(@%R79vD}p(2wOIusR9 zY^pX|OuVA8ieqf+LcBHMJ@O=SH3kC_*|O&bWD&7gTsAH)h76ZdZUnXw#UEIe`Z|6DA+$I=syV<)S2LcgX(w~ zooh$f5-Wo`)D8t@HifdALhF;D9R8PbhnVfqy#8%a%nbM^Rr*~UudMCVghVVI-c!*&?2isJtJ;X0klwp{ISFBvOa3Vc<; z=YQqS1mA41O;NKGpp0D>I0TSnAYjJQ*c8XI1H+@^tGg6PcyIxPwZND@cYwFTkb!PS z;w$+g^@jAE_f-L`G90+2G2;XWS^xI9bt(K7yAVVLixKeDv`@bDej`1vkd?y}%EARL zRZnDY%D7{i$R(M`a6%yOvO3@ifHR?v3wExoa5xU=JmldL#9L3pk^;R1NOqUgCK)qF}OAn52LSV z!qCZC>Sv5e=Osrr8JOZ6cYJ~ZkI#vH<8S4S% zgvPfED-Ke15j$MQDpqUx(rqNAFSwf^46x3bu4%{_r6-7}wtXcA7RAYyr9cG{!gheL zLs4Q-Bed8#Q70?|hlW-opvb1odP$fALDL^k@Ff>&H5W$VVCQa(F0x1uS>#6rabdw` zzc|d0G?wK>BB6dyM(Ey-xKq`WlG7aAppIir$mdkzV1D*F`K&-@z|Y)#A*t`B6wBn2 z^L@otg~&{+`Y2PmjwZ9N7Ly z#>>wtjE{v?qAw2QlWOyU&m`6G(KIy?tGCCOACLf6WctypQ)HVOXSt5v7AKMdN(}>( zJA{nME@2W-OR9^}qKmNv>{JbQas3Wf0j|f*7KDRG&cJS<;C^J#HVZrw3!jOtoYU|z z@DLu8@|kskhoJ+p8+WmT>{q^uTx2O*Sp+F5Asd}?pBZN-eW;>JX5S69^qx@J+tAZm z3N~*lmrC}~D7^j+8}MK#XTB{d(oBD7SMj46u%ARP0;euAul%%|3&2aWkI?;7@;i&4qg}P}qeBC#@N`-a8cm8! z{e%H+80Q}$!{oy}g?zbtLvnX%G~0fOl^DY!al#QZuw&Eu2lc}4L$DAMoL2-FjD^qX z@f!}rt^*CL89+-lk39aS3;+@zz8KFX5WAaTTB~ct@^vpdkC;78lKPJ1hrJfQ z;o=cot{)$+uk;wy#fEF@vaA`iTuwv|tzqLbm}Jw$V~IQs-x%-f-Q@Tk*J^tnBA4+z zwhTnY(*xxJOQxhwtMpK&0|#1J8mahY`ra`xF97~yT-IK9@c<8&!JsaN(nNLCGU!=r zqSH6M#WXN=AWCX(rvjU&+>$MqRX2il@C*ba17Ub!apLrKCJ$dDJ-!rWs@K+`0*W&G4rQ)Dm|kZH;Al z8}SEkakBz{exB)V+vVTJWdbXVC@c`6bn8Z&!Pcz+ zdFa4)ejw28aZcO(O-DLL3metXnkJ(DyxJR#zkkvmC)JE`*&lExxvEHE#_@w~Dz{Jo zQMqY5$~Q!Gs&P@Ls)T_SF*FFlA>JPi#)R#U`)Yg%G4zNx3gLc zbwGXQL*C35KW8uv@_vV62MML9(EHm5PUe0Ty2Ds&)*8*ZEL`~q6uVcAjwuf~qk+DkrK_egov17^sK8TwK6 z{=Qk*ZqR^D4?yU-YmvHZ%Xpzi>CqF)U1Hm7sZalsJf+|GHiB7YN}PApSMITRqx zAl^VaZgj=+J{Ar{!Oy0(aFSV11?n8>>GJ<>N`e_elOAZN2q1?EDLx%r8J#Fi%+U830q_@o11O5=3 zz5?2483B7P&>b!Q|DFgV=^qD=3%D0>seG#P+E4OlrSjwZ=Izt?DFACg1)EnV@wHPz z3JOcH&4$NPkgJOJgh3G)pl0|;_My#6Hdl=0c*gBZe8(9G03*z`tf z=ynOLuIKEzde?KgTE4CP(PTQNz7)UjL80~>@Mms5AF}`3JB7spVF>&cK~^qa6j#Ha zirqF)kYqsla50nN@b8aFTv5}9GvHx%9cGUi=57fYjP@ao76w9t0(jIs+2uT? zu>qy6gOhY{xhyyy=VR~a)1UpHsLq_@&QuJAyS~!npHyvYB{y(BLc9@;SD6pk7(#Z6 z@5i=5yXl80QYt5K9*if~2M;y|PgQYbsltFye0W(=5Z{gmE9Ya&)G%Xy&xte(L=>{x z2AC-cQ7nzd{|#@z1u#1W6s0csJy`I&>wcYK@lGPZu%@V3=-ymv)>%=UEuj3&>%wSAJc&U0e?V%znrVW zsG8QH4Nz3g43aS#C?QIX5gFu2KPy;{*g)K>yKBez zGLIn%CQ6RgEyk09H7|2Mm7%A$Y6{|ULKT%Zn<-qr02LMB6csRAPjMq@{ zYXEsj;aXM;%1Xfi3=jv;+l`;A0KC{qYAeR+WB|qxCyQYm0dSDH^cWaE;=D1&w$0xD zH2rs!B8=VZo)i>}isuKn)f^@OChdXaIbLz0o8#?a91HN{2>|3kF62XAl zU;@R5<2G)5DuCloUU4`6B}0zoS+3<+e&k2~<6EBP2QcJxa^w*J=2`CLST5#7&gDU_ z% z8{Ngg7jZzo=3wsSMQ-L|UgSxR=2;#Anf~dQPUodw=cbP8sea~;u_>D32Y;}1lnk>n zi-w1=8Kyy}dMa{vO#lo0NXQp5eFru1+114@8JC$(LLOe!?Oo|~KkZdP#$EmZ@kI=F zeHrb&KEfb!CXTZ>2JOGF5~-^uV{8DvI@s5n=k$%ae0Ts6ux3(mBNXu86cFz*LIDtv z0F5f?)KRf;+>K``2NYgP_p|JiVI0#=04y^Mp`M=Hd(C=X~d z6U6G*;Oc)6nT}uxhM^CX1Pqm#3Y*YNiRUsdQ6Xwr0@2!rH8c#uj;9xY^X2Fnh}VmR z=M3p%Y=Wl=&kphDvx4mNCh55*7#>z!y^!w^3obgi?~w2{Qt$L40Tod1WG2~gfLeWf zrLiLp>9DzSoU%soxp|F0qcKy)@SvDLV8K)gpMmnJTQ!z4zApZ2@%}xB!nV(!F;;a; zE6>OE&fZSU~Ein-81!5KCSW-1o1y#CoIPp zJ^bRHu&{1r-~4G&B?|y+Ht$st`%*z>5P*4Juflp8%Km=#nCuOdUK(9FO1|Lsj-nhR z-U)Fp_qYwPhgYkopC+L2l?WF2)&T3Wf&v*g!s>CUxujrtf)D709wW-Y+@x#2#A`K; zRg_>HF^!cffhV89^tS2@$Uv*;HNlXv^OmCBrqK9y4+sTnhvD_3}9_+tE{cAY;rZEy?^g4YGt&;`lb;@#xq*5>Gg$=vCK0DkZ>?|y#`8YTGo zB`5j!B^>%TICIvnSONsf5E$6tPoF*%4kKn|OJ9vI#%mAEk zLkWiXAUbS#_-wXfajp49U^w3ifB^BSh!`<1-@0`E(_#D^j@@I51p)|S7U1I{jx^sA zq*imTHfR6IrMWdY^T0EK*)KP*=NSSIf>Og5I2T!BA(#3UFEv?nN%25M`LCm|| z7921O;5D(B1;vWH8z8ss(BO5izc_B4`o6>f$B+T9Ug3wFrJzq*v$aJ)NE}gCnPr?c zc$jB;x#d?or40fN0j<52Kzna>bIdTXna2@F1h6I9Asc~{&PciS6&X$k_*RJrJVgS+ zBRc`-2qsJ|h18D}JP@5!+4bTEE3_zpU6H%E(H%@LnX|xSt!+f$Xc2xUpIlmIdDcxC ztplbw`tb)(W%uxtSVSkNd02v|X#?JC!yx|9pqq+0SVCTNY8hW-VQAief zR3bTs91}rWm|()uUhZHhCzgD{_1HEE7{JpC9;~o}PaOb793?Cu5I~QgI0qys(4j&k zlWZKh3RX(4LLIGar~yYUshK5CStpH`7ouKvDd#lrjfp^u%7!MPlz{fB9}R#p=Vp3NbSZuFrBmTEsi{^@1kWY_Es1EAV~l4sITL{(Qw}0*hHs&l zQBBT#I_juA4Oe51E4ZMlCeE?CiK{(kJS45URFzATOX4yeRc??G%s~)FdO!rmasv~g ze||P$zMu^YU$o;I$n3$^Bv59y4gR9*AXwAtoRR_?Ea(tKc{=#4O3AXTVwW7g1g&0> zE=x$W%1CP$pqUD6$YWFXNsPs>qU{taYV6A79e2=?hIeY{%B!xwcn6b_My>VN zTMxda>Z6IN>~XLDSaGaiw0$>qSRs&xRkhm6In&PTeH)A`SJMi`+7oKG7wjdTAvg$|HztB1Hnq8N~oIX~iRf?3-33o_A#P z5`z3okf|)A7wh5;fJv*C?f3>pw>HMO93lV_0L*dvvjNFz-~b8*(`!BdNu(MOd|w1 zurYHl>e(q@Axezexk?lu9pJ23vB|i8^D0@P&L(N)hT=6Uc|bf+5I5Vwwp0*c@!2U( z+c(xa0tOR6^B#aoFxk%FlQ&mo2Mm?=JsNfvtXfT7XpOl{Li{$Kh$~$oS9cAKItG%@ zF)IZs0D*0`0f7m0;3}lzhBPRE0U`UO0dcWfSmZ$i3YgUU^3u1WebukzjZ9bL^1%#V z)g75@9tQyly#)LL9srofABy^qrSWl=f5qBM_?T3DfS9|D{OVv;yqj1`6T5r;?9S#? zjs5_7f?}1dz$Qk@R$bXw18LBe8{jM7Zvw*rCCXat^n%mZ)zhZE#ZN|q2xH{JBLEuq z)(kr**vmo>hLhum3}qO)EMCo>2qp_t<)>A7LfLT9LvvMa>ev%ibCN*9F%uQ=1+}(8 z4Q+6P8UzjKLbu`2e@+9T!H@w3zyZ*12(%g|4d_1$`p<_RbfDkxD}`7MArv&m1#yUt zDA$a)<1_Wn7ME%g7Jx88v#v$H>&}B9W*>RP2R}-@Cu25QYj@#om0cv3flla|EIx2} z%SIpdeu7o)rW6N20081-00T52@{yO^Tj$rYfG`>OopFc`FETsCATP*TtSnckTqOGm~L z0gvLDRSp1Rzg$zVoH!L`r7Xas;xrSCjFJHVN{ulF|Mx-ATGjgVTi2tE*>{F;&K1$m z?t%p~q(3RV^*T4kQ8q51?btRxw&=7Y^8S&Vxz~6^Nl#USo0>I`v$b2woNi zbkYYoOJ_OK^>jFKabTtoYJx&C*kPPeL!*~0LufDcvn*UhN2`bqKX-nBbx7t=e0@?B zNTFl=7Yb>nHCFh z67+acWATrTbS0*zFZPjjPM1Hb5{`+rWuEh4;$d}S^cX0Ed9YXl5Fuu|)|9>GC6|as zr75!&bljcnV@puCFV2jrnnE6>{KNmGo zX(9RvppEwcySbZFSPHr6e-6MLBJ}{h`9G)hpRj|7`iX%0741@ z5U`s?x}XFaq(Zu+LmC0w$9*bdqcuwYfpB&|{3v=n+7?AOm^WFaU{zdRmLC|#Mko{! zBKk(2QD-VPDc@Ijc_())_kG`&c2_rS(gdZ{@h`*>0Zy7>h6(_M zil~R0VTCHFf@u&@dRc)uaadD&iD+P6(pMJrfH4YMGCB^p6jbzpnExaQj_QpVQ76jq zeJ_DzX@@fBaSTvGr*)b`7p0sTVOgg~Emes%0eT|b;G_|79LJGi#fk~WdZ^9Na9I<0 zbs=_McTCk-irdAd@v*0Zhj3klCDsFVo+YM!kYW7+RX}MuCbE9T;1L_K5eN|$10jU1 z8Jx-XJi_>9%HnPa7l6Q3qKW<_Ef2P#>532`0RZDsN~Lsk1gI({k)70F2>sbZ_I4AR zb*WVqlhDH~Pxh^x3XBnV4x!o~{@^Wks1Ja%i32ey!D*Ex!VC?_68}1-(Nc<|wyX2! zt%8Ii8=J1dB{&oKjV!4Q1k$b>avV=Hd~s57C3=nVlXy6TuAg;A8LJzALS@Vnf%G>J zh&8JFAhJ{^itsi%+)73&VK0h8c@�sYA6lx{#uQDbK`xf@8Ix=&9?GA(KK72oaol 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

#E>Gn4MY!-hQzk7t_8ey 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%0A`yx_g$Q7xvAPzG2P6{9SeG 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 z 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 z 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 z

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] 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
- - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/indicators/averages/afirma/afirma.md b/docs/indicators/averages/afirma/afirma.md deleted file mode 100644 index db119ae2..00000000 --- a/docs/indicators/averages/afirma/afirma.md +++ /dev/null @@ -1,27 +0,0 @@ -# AFIRMA: Autoregressive Finite Impulse Response Moving Average - -## Concept - -AFIRMA indicator is a hybrid moving average that combines the benefits of digital filtering and cubic spline fitting to provide a smooth and accurate representation of price movement without significant time lag. - -## Origin - -The AFIRMA indicator is based on the principles of digital signal processing and curve fitting. It was developed to address the limitations of traditional moving averages, which often suffer from time lag or fail to accurately track price movements. - -## Key Features - -- **Digital Filter**: The AFIRMA indicator uses a digital filter to smooth out price movements. -- **Cubic Spline Fitting**: The latest candlesticks are smoothed using cubic spline fitting with the least square method to ensure a seamless transition. -- **Combined Moving Average**: The indicator combines the digital filter and cubic spline fitting to create a smooth moving average that accurately tracks prices without time lag. -- **Customizable Parameters**: The AFIRMA indicator allows users to adjust the Periods, Taps, and Window parameters to fine-tune the indicator's performance. - -## Advantages - -- **Accurate Price Tracking**: The AFIRMA indicator provides a smooth and accurate representation of price movement without time lag. -- **Hybrid Approach**: The combination of digital filtering and cubic spline fitting provides a unique and effective approach to moving average calculation. - -## Considerations - -**Complexity**: The AFIRMA indicator is a complex filter that requires some understanding of digital signal processing and curve fitting to use it right. -- **Parameter Optimization**: Finding the optimal parameters for the AFIRMA indicator may require some experimentation and testing. -- **Computational Resources**: The AFIRMA indicator is computationally more intensive than traditional moving averages due to the use of cubic spline fitting. \ No newline at end of file diff --git a/docs/indicators/averages/afirma/analysis.md b/docs/indicators/averages/afirma/analysis.md deleted file mode 100644 index 8392e240..00000000 --- a/docs/indicators/averages/afirma/analysis.md +++ /dev/null @@ -1,60 +0,0 @@ -# AFIRMA: Benchmark Analysis - -This analysis evaluates the Autoregressive Finite Impulse Response Moving Average (AFIRMA) across four core benchmarks: accuracy, timeliness, overshooting, and smoothness. These benchmarks provide a comprehensive view of AFIRMA's performance characteristics and serve as a basis for comparison with other moving averages. - -## Accuracy (closeness to the original data) - -AFIRMA generally exhibits high accuracy in representing the original price data due to its sophisticated approach combining digital filtering and cubic spline fitting. - -- **Strengths**: - - The digital filter component helps to reduce noise while preserving important price trends. - - Cubic spline fitting for recent candlesticks ensures that the most current price movements are accurately represented. - -- **Considerations**: - - Accuracy can vary based on parameter settings. Incorrect parameter selection might lead to over-smoothing or under-smoothing, potentially reducing accuracy. - - In highly volatile markets, AFIRMA may sacrifice some accuracy for smoothness, especially if the parameters are set to prioritize noise reduction. - -## Timeliness (amount of lag) - -AFIRMA is designed to minimize lag, which is one of its key advantages over traditional moving averages. - -- **Strengths**: - - The combination of ARMA modeling and FIR filtering allows AFIRMA to respond quickly to price changes. - - Cubic spline fitting of recent data points further reduces lag for the most current price movements. - -- **Considerations**: - - While AFIRMA generally has less lag than traditional MAs, it's not entirely lag-free. Some minimal lag may still be present, especially with longer period settings. - - The amount of lag can be influenced by parameter settings. Optimizing for minimal lag might come at the cost of increased noise sensitivity. - -## Overshooting (overcompensation during reversals) - -AFIRMA's design helps to mitigate overshooting during price reversals, but the extent can vary based on settings and market conditions. - -- **Strengths**: - - The digital filtering component helps to dampen extreme price movements, reducing the likelihood of significant overshooting. - - Cubic spline fitting allows for smoother transitions during reversals, potentially minimizing overshoot. - -- **Considerations**: - - Overshooting can still occur, especially in markets with sudden, sharp reversals. - - The degree of overshooting can be influenced by parameter settings. More aggressive settings might increase responsiveness but also the risk of overshooting. - -## Smoothness (continuous 2nd derivative, less jagged flow) - -AFIRMA generally produces a smoother line than many traditional moving averages, which is one of its defining characteristics. - -- **Strengths**: - - The digital filtering component effectively smooths out minor price fluctuations and noise. - - Cubic spline fitting ensures a smooth transition between historical and current data points. - - The combination of these techniques results in a visually smooth line that can make trend identification easier. - -- **Considerations**: - - The degree of smoothness can be adjusted through parameter settings. Excessive smoothing might lead to a loss of responsiveness to genuine price changes. - - In some cases, the smooth line might mask short-term volatility that could be relevant for certain trading strategies. - -## Conclusion - -AFIRMA demonstrates strong performance across all four benchmarks, particularly excelling in accuracy, timeliness, and smoothness. Its complex approach allows it to balance these often competing characteristics more effectively than many traditional moving averages. - -However, it's important to note that AFIRMA's performance can be significantly influenced by its parameter settings. Optimal use of AFIRMA requires careful tuning of these parameters to balance accuracy, timeliness, overshooting resistance, and smoothness for the specific asset and timeframe being analyzed. - -When compared to other moving averages, AFIRMA generally offers superior or comparable performance across these benchmarks. However, this comes at the cost of increased complexity and computational requirements. Traders and analysts should weigh these factors when deciding whether to incorporate AFIRMA into their technical analysis toolkit. \ No newline at end of file diff --git a/docs/indicators/averages/afirma/calc.md b/docs/indicators/averages/afirma/calc.md deleted file mode 100644 index fcc2255d..00000000 --- a/docs/indicators/averages/afirma/calc.md +++ /dev/null @@ -1,67 +0,0 @@ -# The Math Behind AFIRMA - -## Components of AFIRMA - -AFIRMA is a hybrid beast, combining two main components: - -- Autoregressive Moving Average (ARMA) -- Finite Impulse Response (FIR) filter - -### ARMA Component - -$ X_t = c + \epsilon_t + \sum_{i=1}^p \phi_i X_{t-i} + \sum_{j=1}^q \theta_j \epsilon_{t-j} $ - -Where: -- $X_t$ is the time series value at time $t$
-- $c$ is a constant
-- $\phi_i$ are the parameters of the autoregressive term
-- $\theta_j$ are the parameters of the moving average term
-- $\epsilon_t$ is white noise
- -### FIR Component - -$ y[n] = \sum_{i=0}^{N-1} b_i \cdot x[n-i] $ - -Where: -- $y[n]$ is the output signal -- $x[n]$ is the input signal -- $b_i$ are the filter coefficients -- $N$ is the filter order - -### AFIRMA: Putting It All Together - -AFIRMA combines these components and adds cubic spline fitting to the mix. The general form can be expressed as: - -$ AFIRMA_t = ARMA_t + FIR_t + CS_t $ - -Where: -- $ARMA_t$ is the ARMA component at time $t$ -- $FIR_t$ is the FIR component at time $t$ -- $CS_t$ is the cubic spline fitting component at time $t$ - -### Digital Filtering Process - -- The price data is passed through the digital filter to smooth out fluctuations. -- The filter coefficients are optimized based on the specified parameters (Periods, Taps, Window). - -### Cubic Spline Fitting - -For the most recent bars: - -- A cubic spline is fitted to the data points using the least squares method. -- This ensures a smooth transition between the filtered data and the most recent price movements. - -### Parameter Definitions - -The AFIRMA indicator allows for the adjustment of three main parameters: - -- **Periods**: Affects the overall smoothness of the indicator. -- *Taps*: Influences the complexity of the digital filter. -- *Window*: Determines the number of recent bars to which the cubic spline fitting is applied. - -### Computational Process - -- Apply the ARMA model to the price data. -- Pass the result through the FIR filter. -- Apply cubic spline fitting to the most recent data points. -- Combine the results to produce the final AFIRMA value. diff --git a/docs/indicators/averages/afirma/charts.dib b/docs/indicators/averages/afirma/charts.dib deleted file mode 100644 index 7d93d388..00000000 --- a/docs/indicators/averages/afirma/charts.dib +++ /dev/null @@ -1,63 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "AFIRMA"; -int taps = 6; -int periods = 6; -Afirma.WindowType window = Afirma.WindowType.BlackmanHarris; - -Func Indicator = (taps, periods, windows) => new Afirma(taps: taps, periods: periods, window: window); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(taps, periods, window); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({taps}, {periods}, {window.ToString()})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{taps}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/afirma/charts.md b/docs/indicators/averages/afirma/charts.md deleted file mode 100644 index d4b19d30..00000000 --- a/docs/indicators/averages/afirma/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# AFIRMA: Charts - -![](img/AFIRMA6_Spike.svg) ![](img/AFIRMA6_Impulse.svg) ![](img/AFIRMA6_Triangle.svg) ![](img/AFIRMA6_Sawtooth.svg) ![](img/AFIRMA6_Sine.svg) ![](img/AFIRMA6_Chirp.svg) ![](img/AFIRMA6_White.svg) ![](img/AFIRMA6_Gauss.svg) ![](img/AFIRMA6_B.svg) ![](img/AFIRMA6_HF.svg) ![](img/AFIRMA6_ImpulseHF.svg) ![](img/AFIRMA6_SawtoothHF.svg) ![](img/AFIRMA6_SineG.svg) ![](img/AFIRMA6_ChirpG.svg) ![](img/AFIRMA6_Complex.svg) ![](img/AFIRMA6_Market.svg) diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_B.svg b/docs/indicators/averages/afirma/img/AFIRMA6_B.svg deleted file mode 100644 index 43dcf35a..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg deleted file mode 100644 index b1826d0d..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg b/docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg deleted file mode 100644 index 2c61faa3..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg deleted file mode 100644 index 4a1b92bc..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg deleted file mode 100644 index 6e6747fb..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_HF.svg b/docs/indicators/averages/afirma/img/AFIRMA6_HF.svg deleted file mode 100644 index ec93b5b8..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg deleted file mode 100644 index 878244c4..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg b/docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg deleted file mode 100644 index bff64afa..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Market.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Market.svg deleted file mode 100644 index 6f006235..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg deleted file mode 100644 index a4d68182..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg b/docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg deleted file mode 100644 index 7cdb3f2b..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg deleted file mode 100644 index c08c7024..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Sine - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg b/docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg deleted file mode 100644 index d731a839..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg deleted file mode 100644 index 004c96d0..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg deleted file mode 100644 index e675197d..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_White.svg b/docs/indicators/averages/afirma/img/AFIRMA6_White.svg deleted file mode 100644 index b649a062..00000000 --- a/docs/indicators/averages/afirma/img/AFIRMA6_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - AFIRMA(6, 6, BlackmanHarris) - - diff --git a/docs/indicators/averages/alma/alma.md b/docs/indicators/averages/alma/alma.md deleted file mode 100644 index df1c80af..00000000 --- a/docs/indicators/averages/alma/alma.md +++ /dev/null @@ -1,53 +0,0 @@ -## ALMA: Arnaud Legoux Moving Average - -### Concept - -ALMA is a moving average designed to reduce the lag of traditional moving averages while maintaining smoothness. It uses a Gaussian distribution to weight the price data, allowing for greater flexibility in balancing smoothness and responsiveness. - -### Origin - -ALMA was developed by *Arnaud Legoux and Dimitrios Kouzis-Loukas*, introduced in 2009. It was created to address the limitations of traditional moving averages, particularly the lag issue in trend identification and signal generation. - -### Key Features - -1. **Gaussian Distribution**: Uses a Gaussian (normal) distribution to weight price data, concentrating the most weight around a specific point. -2. **Offset Parameter**: Allows shifting the Gaussian distribution to the left or right, affecting the lag and responsiveness. -3. **Sigma Parameter**: Controls the width of the Gaussian distribution, affecting the smoothness of the average. -4. **Lag Reduction**: Designed to minimize lag while maintaining a smooth output. - -### Usage - -1. **Trend Identification**: ALMA can identify trends more quickly than traditional moving averages due to its reduced lag. -2. **Signal Generation**: Crossovers between ALMA and price, or between different ALMA settings, can generate trading signals. -3. **Support and Resistance**: ALMA can act as dynamic support and resistance levels. -4. **Smoothing Price Action**: Useful for smoothing noisy price data while preserving important trend information. - -### Advantages - -- Reduces lag compared to simple and exponential moving averages. -- Highly customizable through its offset and sigma parameters. -- Can be tuned to be more responsive or more smooth based on trading preferences. -- Potentially more effective in capturing short-term price movements. - -### Considerations - -- **Offset Parameter**: Ranges from 0 to 1, determining the distribution's center of weight. - - 0 results in a simple moving average (more lag, very smooth). - - 1 creates a weighted average focused on the most recent prices (less lag, less smooth). - - 0.85 is often used as a default, balancing lag reduction and smoothness. - -- **Sigma Parameter**: Controls the Gaussian distribution's width. - - Lower values create a narrower distribution, focusing on fewer price bars. - - Higher values create a wider distribution, incorporating more price bars. - - 6 is often used as a default value. - -- **Period**: As with other moving averages, determines how many price bars are included in the calculation. - -- **Balancing Responsiveness and Stability**: - - Adjusting offset and sigma allows fine-tuning between quick response to price changes and stability in noisy markets. - - Higher offset and lower sigma increase responsiveness but may lead to more false signals in volatile markets. - - Lower offset and higher sigma increase smoothness but may introduce more lag. - -- **Computational Complexity**: More complex to calculate than simple moving averages, which may be a consideration in high-frequency trading systems. - -- **Interpretation**: Due to its unique weighting system, ALMA may behave differently from traditional moving averages in certain market conditions, requiring careful interpretation. \ No newline at end of file diff --git a/docs/indicators/averages/alma/analysis.md b/docs/indicators/averages/alma/analysis.md deleted file mode 100644 index 87bf847d..00000000 --- a/docs/indicators/averages/alma/analysis.md +++ /dev/null @@ -1,51 +0,0 @@ -# ALMA: Benchmark Analysis - -This analysis evaluates the Arnaud Legoux Moving Average (ALMA) across four core benchmarks: accuracy, timeliness, overshooting, and smoothness. These benchmarks provide a comprehensive view of ALMA's performance characteristics and serve as a basis for comparison with other moving averages. - -## Accuracy (closeness to the original data) - -ALMA generally exhibits good accuracy in representing the original price data due to its Gaussian distribution-based weighting system. - -- **Strengths**: - - The Gaussian distribution weighting helps to reduce noise while preserving important price trends. - - The offset parameter allows for fine-tuning of the balance between recent and historical data representation. - -- **Considerations**: - - Accuracy can vary based on parameter settings. Incorrect parameter selection might lead to over-smoothing or under-smoothing, potentially reducing accuracy. - - In highly volatile markets, ALMA may sacrifice some accuracy for smoothness, especially if the sigma parameter is set to prioritize noise reduction. - -## Timeliness (amount of lag) - -ALMA is designed to minimize lag, which is one of its key advantages over traditional moving averages. - -- **Strengths**: - - The offset parameter allows ALMA to be more responsive to recent price changes, potentially reducing lag. - - The ability to adjust the window size provides flexibility in balancing timeliness and stability. - -- **Considerations**: - - While ALMA generally has less lag than traditional MAs, it's not entirely lag-free. Some minimal lag may still be present, especially with larger window sizes. - - The amount of lag can be influenced by parameter settings. Optimizing for minimal lag might come at the cost of increased noise sensitivity. - -## Overshooting (overcompensation during reversals) - -ALMA's design helps to mitigate overshooting during price reversals, but the extent can vary based on settings and market conditions. - -- **Strengths**: - - The Gaussian distribution weighting helps to dampen extreme price movements, reducing the likelihood of significant overshooting. - - The sigma parameter allows for control over the smoothness of transitions, potentially minimizing overshoot. - -- **Considerations**: - - Overshooting can still occur, especially in markets with sudden, sharp reversals. - - The degree of overshooting can be influenced by parameter settings. More aggressive settings (lower sigma, higher offset) might increase responsiveness but also the risk of overshooting. - -## Smoothness (continuous 2nd derivative, less jagged flow) - -ALMA generally produces a smoother line than many traditional moving averages, which is one of its defining characteristics. - -- **Strengths**: - - The Gaussian distribution weighting effectively smooths out minor price fluctuations and noise. - - The sigma parameter provides direct control over the smoothness of the line. - - The resulting smooth line can make trend identification easier. - -- **Considerations**: - - The degree of smoothness can be adjusted through parameter settings. \ No newline at end of file diff --git a/docs/indicators/averages/alma/calc.md b/docs/indicators/averages/alma/calc.md deleted file mode 100644 index 7c9bc48b..00000000 --- a/docs/indicators/averages/alma/calc.md +++ /dev/null @@ -1,45 +0,0 @@ -# The Math Behind ALMA - -## Components of ALMA - -ALMA is a single-formula moving average that incorporates elements of several advanced techniques: - -- Gaussian distribution -- Weighted moving average -- Offset parameter - -### ALMA Formula - -$ ALMA_t = \sum_{i=0}^{n-1} w_i \cdot P_{t-i} $ - -Where: -- $ALMA_t$ is the ALMA value at time $t$ -- $n$ is the window size (number of periods) -- $P_{t-i}$ is the price at time $t-i$ -- $w_i$ are the weights - -### Weight Calculation - -The weights $w_i$ are calculated using a Gaussian distribution function with an offset: - -$ w_i = \exp\left(-\frac{(i - m)^2}{2s^2}\right) $ - -Where: -- $i$ is the position of the price in the window (0 to $n-1$) -- $m$ is the offset of the Gaussian distribution, calculated as $m = \text{floor}(offset \cdot (n - 1))$ -- $s$ is the standard deviation of the Gaussian distribution, calculated as $s = \frac{n}{sigma}$ - -### Parameter Definitions - -ALMA uses three main parameters: - -- **Window size** ($n$): Affects the overall reactivity of the indicator. -- **Offset**: Influences the lag of the moving average. Lower values reduce lag but may increase noise. -- **Sigma**: Controls the smoothness of the indicator. Higher values increase smoothness but may increase lag. - -### Computational Process - -For each new data point: -- Calculate the weights for the entire window. -- Apply these weights to the most recent $n$ prices. -- Sum the weighted prices to produce the final ALMA value. diff --git a/docs/indicators/averages/alma/charts.dib b/docs/indicators/averages/alma/charts.dib deleted file mode 100644 index c43f9194..00000000 --- a/docs/indicators/averages/alma/charts.dib +++ /dev/null @@ -1,62 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "ALMA"; -int p = 10; -double offset = 0.85; -double sigma = 6.0; -Func Indicator = period => new Alma(period, offset: offset, sigma: sigma); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p}, {offset:F2}, {sigma:F2})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/alma/charts.md b/docs/indicators/averages/alma/charts.md deleted file mode 100644 index 64e9389b..00000000 --- a/docs/indicators/averages/alma/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# ALMA Charts - -![](img/ALMA10_Spike.svg) ![](img/ALMA10_Impulse.svg) ![](img/ALMA10_Triangle.svg) ![](img/ALMA10_Sawtooth.svg) ![](img/ALMA10_Sine.svg) ![](img/ALMA10_Chirp.svg) ![](img/ALMA10_White.svg) ![](img/ALMA10_Gauss.svg) ![](img/ALMA10_B.svg) ![](img/ALMA10_HF.svg) ![](img/ALMA10_ImpulseHF.svg) ![](img/ALMA10_SawtoothHF.svg) ![](img/ALMA10_SineG.svg) ![](img/ALMA10_ChirpG.svg) ![](img/ALMA10_Complex.svg) ![](img/ALMA10_Market.svg) diff --git a/docs/indicators/averages/alma/img/ALMA10_B.svg b/docs/indicators/averages/alma/img/ALMA10_B.svg deleted file mode 100644 index aa9eebf0..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Chirp.svg b/docs/indicators/averages/alma/img/ALMA10_Chirp.svg deleted file mode 100644 index 6eb00d70..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_ChirpG.svg b/docs/indicators/averages/alma/img/ALMA10_ChirpG.svg deleted file mode 100644 index 54c3e238..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Complex.svg b/docs/indicators/averages/alma/img/ALMA10_Complex.svg deleted file mode 100644 index 79a14269..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Gauss.svg b/docs/indicators/averages/alma/img/ALMA10_Gauss.svg deleted file mode 100644 index 0a0bfca3..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_HF.svg b/docs/indicators/averages/alma/img/ALMA10_HF.svg deleted file mode 100644 index 40dd1bc2..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Impulse.svg b/docs/indicators/averages/alma/img/ALMA10_Impulse.svg deleted file mode 100644 index 6ad12bbb..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Impulse.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_ImpulseHF.svg b/docs/indicators/averages/alma/img/ALMA10_ImpulseHF.svg deleted file mode 100644 index dabf368c..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Market.svg b/docs/indicators/averages/alma/img/ALMA10_Market.svg deleted file mode 100644 index f73a1a92..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Sawtooth.svg b/docs/indicators/averages/alma/img/ALMA10_Sawtooth.svg deleted file mode 100644 index 2639137f..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Sawtooth.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_SawtoothHF.svg b/docs/indicators/averages/alma/img/ALMA10_SawtoothHF.svg deleted file mode 100644 index 7a2b2f8e..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Sine.svg b/docs/indicators/averages/alma/img/ALMA10_Sine.svg deleted file mode 100644 index 77d36a43..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Sine.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Sine - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_SineG.svg b/docs/indicators/averages/alma/img/ALMA10_SineG.svg deleted file mode 100644 index 625dbe46..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Spike.svg b/docs/indicators/averages/alma/img/ALMA10_Spike.svg deleted file mode 100644 index 56323b11..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Spike.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_Triangle.svg b/docs/indicators/averages/alma/img/ALMA10_Triangle.svg deleted file mode 100644 index 691d7693..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/alma/img/ALMA10_White.svg b/docs/indicators/averages/alma/img/ALMA10_White.svg deleted file mode 100644 index b1524b93..00000000 --- a/docs/indicators/averages/alma/img/ALMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - ALMA(10, 0.85, 6.00) - - diff --git a/docs/indicators/averages/convolution/convolution.md b/docs/indicators/averages/convolution/convolution.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/dema/analysis.md b/docs/indicators/averages/dema/analysis.md deleted file mode 100644 index ee4ada70..00000000 --- a/docs/indicators/averages/dema/analysis.md +++ /dev/null @@ -1,65 +0,0 @@ -# DEMA: Benchmark Analysis - -This analysis evaluates the Double Exponential Moving Average (DEMA) across four core benchmarks: accuracy, timeliness, overshooting, and smoothness. - -## Accuracy (closeness to the original data) - -DEMA generally provides a good balance between accuracy and smoothing. - -- **Strengths**: - - The double smoothing process helps to reduce noise while preserving important price trends. - - More accurate than a simple EMA, especially during trend changes. - -- **Considerations**: - - In highly volatile markets, DEMA may sacrifice some accuracy for smoothness. - - Accuracy can vary based on the period setting. Shorter periods increase accuracy but may introduce more noise. - -## Timeliness (amount of lag) - -DEMA is designed to reduce lag compared to traditional moving averages, which is one of its key advantages. - -- **Strengths**: - - The double smoothing formula effectively reduces lag compared to standard EMAs. - - Responds more quickly to price changes than simple or exponential moving averages. - -- **Considerations**: - - While DEMA has less lag than traditional MAs, it's not entirely lag-free. - - Shorter periods reduce lag but may increase sensitivity to noise. - -## Overshooting (overcompensation during reversals) - -DEMA is known for significant overshooting during price reversals, which is one of its main drawbacks. - -- **Weaknesses**: - - Prone to substantial overshooting, especially during sharp price reversals. - - The double exponential smoothing, while reducing lag, can exaggerate price movements during trend changes. - -- **Considerations**: - - Overshooting is particularly pronounced in volatile markets or during sudden trend reversals. - - Shorter periods may further increase the risk and magnitude of overshooting. - - This characteristic can lead to false signals or exaggerated price projections, potentially misleading traders. - -## Smoothness (continuous 2nd derivative, less jagged flow) - -DEMA produces a relatively smooth line, balancing smoothness with responsiveness. - -- **Strengths**: - - Smoother than a standard EMA, making trend identification easier. - - The double smoothing process effectively reduces minor fluctuations. - -- **Considerations**: - - Less smooth than higher-order moving averages or those with explicit smoothing parameters. - - The degree of smoothness is primarily controlled by the period setting, offering less flexibility than some advanced moving averages. - -## Conclusion - -DEMA demonstrates mixed performance across the four benchmarks. It excels in reducing lag and maintains a good degree of smoothness, but its tendency to overshoot significantly during price reversals is a major drawback. - -DEMA's performance is influenced by its single parameter (the period). While this simplicity is an advantage for ease of use, it also means there's less flexibility to mitigate its overshooting tendency. - -Compared to more complex moving averages like AFIRMA or ALMA, DEMA offers simplicity and excellent lag reduction. However, its proneness to overshooting can make it less reliable during volatile market conditions or during trend reversals. - -Traders and analysts should carefully consider DEMA's strengths and weaknesses. While it offers improved lag reduction over simple moving averages, its overshooting characteristic can lead to false signals. This makes it potentially risky to use on its own, especially in volatile markets. -DEMA might be most effectively used in conjunction with other indicators that can help confirm signals and mitigate the risk of false readings due to overshooting. It may be particularly useful in strongly trending markets where its lag reduction is beneficial and the risk of reversal (and thus overshooting) is lower. - -In summary, DEMA's simplicity and lag reduction make it an interesting tool, but its tendency to overshoot means it should be used with caution and preferably as part of a broader analytical approach rather than as a standalone indicator. \ No newline at end of file diff --git a/docs/indicators/averages/dema/calc.md b/docs/indicators/averages/dema/calc.md deleted file mode 100644 index bf9035dc..00000000 --- a/docs/indicators/averages/dema/calc.md +++ /dev/null @@ -1,48 +0,0 @@ -# The Math Behind DEMA - -## Components of DEMA - -DEMA is composed of two main components: - -1. Exponential Moving Average (EMA) -2. A "double smoothing" factor - -Let's break these down: - -### EMA Calculation - -The Exponential Moving Average (EMA) is calculated as: - -$ EMA_t = \alpha \cdot P_t + (1 - \alpha) \cdot EMA_{t-1} $ - -Where: -- $EMA_t$ is the EMA value at time $t$ -- $P_t$ is the price at time $t$ -- $\alpha$ is the smoothing factor, calculated as $\frac{2}{n+1}$ -- $n$ is the number of periods - -### DEMA Formula - -The DEMA is then calculated using the following formula: - -$ DEMA_t = 2 \cdot EMA_t - EMA(EMA_t) $ - -Where: -- $DEMA_t$ is the DEMA value at time $t$ -- $EMA_t$ is the EMA of the price -- $EMA(EMA_t)$ is the EMA of the EMA - -## Calculation Process - -1. Calculate the EMA of the price series. -2. Calculate another EMA on the result of step 1. -3. Multiply the first EMA by 2. -4. Subtract the second EMA from the result of step 3. - -This process effectively reduces lag while maintaining smoothness. - -## Parameter - -DEMA uses a single parameter: - -- **Period** ($n$): Determines the number of periods used in the EMA calculations. This affects the overall reactivity and smoothness of the indicator. diff --git a/docs/indicators/averages/dema/charts.dib b/docs/indicators/averages/dema/charts.dib deleted file mode 100644 index 8b2f0f40..00000000 --- a/docs/indicators/averages/dema/charts.dib +++ /dev/null @@ -1,60 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "DEMA"; -int p = 10; -Func Indicator = period => new Dema(period); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/dema/charts.md b/docs/indicators/averages/dema/charts.md deleted file mode 100644 index af4ac622..00000000 --- a/docs/indicators/averages/dema/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# DEMA Charts - -![](img/DEMA10_Spike.svg) ![](img/DEMA10_Impulse.svg) ![](img/DEMA10_Triangle.svg) ![](img/DEMA10_Sawtooth.svg) ![](img/DEMA10_Sine.svg) ![](img/DEMA10_Chirp.svg) ![](img/DEMA10_White.svg) ![](img/DEMA10_Gauss.svg) ![](img/DEMA10_B.svg) ![](img/DEMA10_HF.svg) ![](img/DEMA10_ImpulseHF.svg) ![](img/DEMA10_SawtoothHF.svg) ![](img/DEMA10_SineG.svg) ![](img/DEMA10_ChirpG.svg) ![](img/DEMA10_Complex.svg) ![](img/DEMA10_Market.svg) diff --git a/docs/indicators/averages/dema/dema.md b/docs/indicators/averages/dema/dema.md deleted file mode 100644 index 6d82fb2b..00000000 --- a/docs/indicators/averages/dema/dema.md +++ /dev/null @@ -1,59 +0,0 @@ -## DEMA: Double Exponential Moving Average - -### Concept - -DEMA is an enhanced version of the Exponential Moving Average (EMA) designed to reduce lag while maintaining smoothness. It achieves this by calculating an EMA of an EMA and then using a formula to reduce the inherent lag - at the expense of overshooting the signal line. - -### Origin - -DEMA was developed by Patrick Mulloy and first introduced in the February 1994 issue of *Technical Analysis of Stocks & Commodities magazine*. It was created to address the lag issue in traditional moving averages, particularly in trend identification and signal generation. - -### Key Features - -1. **Double Smoothing**: Uses two EMAs in its calculation, providing a smoother output than a single EMA. -2. **Lag Reduction**: Employs a formula to reduce the lag typically associated with moving averages. -3. **Responsiveness**: More responsive to price changes than a standard EMA of the same period, at the expense of overshooting. -4. **Trend Sensitivity**: Better at capturing trends and reacting to reversals than traditional moving averages. - -### Usage - -1. **Trend Identification**: DEMA can identify trends more quickly than traditional moving averages due to its reduced lag. -2. **Signal Generation**: Crossovers between DEMA and price, or between different DEMA settings, can generate trading signals. -3. **Support and Resistance**: DEMA can act as dynamic support and resistance levels. -4. **Smoothing Price Action**: Useful for smoothing noisy price data while preserving important trend information. - -### Advantages - -- Reduces lag compared to simple and exponential moving averages. -- More responsive to price changes than traditional EMAs. -- Maintains smoothness despite increased responsiveness. -- Can be more effective in capturing short to medium-term price movements. -- Simple to understand conceptually, building on the familiar EMA. - -### Considerations - -- **Period**: As with other moving averages, determines how many price bars are included in the calculation. The period affects both EMAs used in the DEMA calculation. - -- **Calculation**: The formula for DEMA is: - DEMA = 2 * EMA(price) - EMA(EMA(price))
- This formula effectively doubles the percentage of EMA weight applied to the most recent price. - -- **Sensitivity**: - - DEMA is more sensitive to price changes than a standard EMA of the same period. - - This increased sensitivity can lead to earlier signals but may also result in more false signals in choppy markets. - -- **Balancing Responsiveness and Stability**: - - Shorter periods increase responsiveness but may lead to more false signals in volatile markets. - - Longer periods increase smoothness but may introduce more lag. - -- **Comparison to Other MAs**: - - DEMA typically responds faster than EMA, SMA, or triangular MA of the same period. - - It may be less smooth than a triple exponential moving average (TEMA) but with less lag. - -- **Whipsaws**: Due to its responsiveness, DEMA may be prone to whipsaws in ranging or choppy markets. - -- **Multiple Time Frame Analysis**: Using DEMAs on different time frames can provide a more comprehensive view of trends and potential reversals. - -- **Computational Complexity**: Slightly more complex to calculate than simple or exponential moving averages, which may be a minor consideration in high-frequency trading systems. - -- **Interpretation**: While more responsive than traditional EMAs, traders should still be aware that DEMA is a lagging indicator by nature, and should be used in conjunction with other technical analysis tools for confirmation. \ No newline at end of file diff --git a/docs/indicators/averages/dema/img/DEMA10_B.svg b/docs/indicators/averages/dema/img/DEMA10_B.svg deleted file mode 100644 index 3a5390ab..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Chirp.svg b/docs/indicators/averages/dema/img/DEMA10_Chirp.svg deleted file mode 100644 index 404a6274..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_ChirpG.svg b/docs/indicators/averages/dema/img/DEMA10_ChirpG.svg deleted file mode 100644 index 7f27ab8e..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Complex.svg b/docs/indicators/averages/dema/img/DEMA10_Complex.svg deleted file mode 100644 index 931f69c1..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Gauss.svg b/docs/indicators/averages/dema/img/DEMA10_Gauss.svg deleted file mode 100644 index 19af7216..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_HF.svg b/docs/indicators/averages/dema/img/DEMA10_HF.svg deleted file mode 100644 index 17be89df..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Impulse.svg b/docs/indicators/averages/dema/img/DEMA10_Impulse.svg deleted file mode 100644 index 927ace82..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Impulse.svg +++ /dev/null @@ -1,342 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_ImpulseHF.svg b/docs/indicators/averages/dema/img/DEMA10_ImpulseHF.svg deleted file mode 100644 index 3905bb23..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Market.svg b/docs/indicators/averages/dema/img/DEMA10_Market.svg deleted file mode 100644 index e6364a06..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Sawtooth.svg b/docs/indicators/averages/dema/img/DEMA10_Sawtooth.svg deleted file mode 100644 index b21d2cff..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Sawtooth.svg +++ /dev/null @@ -1,362 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -5 - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_SawtoothHF.svg b/docs/indicators/averages/dema/img/DEMA10_SawtoothHF.svg deleted file mode 100644 index c69f61a3..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Sine.svg b/docs/indicators/averages/dema/img/DEMA10_Sine.svg deleted file mode 100644 index 30fa7e82..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Sine.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Sine - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_SineG.svg b/docs/indicators/averages/dema/img/DEMA10_SineG.svg deleted file mode 100644 index b0bab4fe..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Spike.svg b/docs/indicators/averages/dema/img/DEMA10_Spike.svg deleted file mode 100644 index 6d0c6fcb..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Spike.svg +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_Triangle.svg b/docs/indicators/averages/dema/img/DEMA10_Triangle.svg deleted file mode 100644 index d5f7bf0a..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - DEMA(10) - - diff --git a/docs/indicators/averages/dema/img/DEMA10_White.svg b/docs/indicators/averages/dema/img/DEMA10_White.svg deleted file mode 100644 index ba53cde0..00000000 --- a/docs/indicators/averages/dema/img/DEMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - DEMA(10) - - diff --git a/docs/indicators/averages/dsma/analysis.md b/docs/indicators/averages/dsma/analysis.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/dsma/calc.md b/docs/indicators/averages/dsma/calc.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/dsma/charts.dib b/docs/indicators/averages/dsma/charts.dib deleted file mode 100644 index b759e556..00000000 --- a/docs/indicators/averages/dsma/charts.dib +++ /dev/null @@ -1,61 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "DSMA"; -int p = 10; -double scale = 0.5; -Func Indicator = (period, scale) => new Dsma(period, scale); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p, scale); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p}, {scale:F2})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/dsma/charts.md b/docs/indicators/averages/dsma/charts.md deleted file mode 100644 index 1df86ea9..00000000 --- a/docs/indicators/averages/dsma/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# DSMA Charts - -![](img/DSMA10_Spike.svg) ![](img/DSMA10_Impulse.svg) ![](img/DSMA10_Triangle.svg) ![](img/DSMA10_Sawtooth.svg) ![](img/DSMA10_Sine.svg) ![](img/DSMA10_Chirp.svg) ![](img/DSMA10_White.svg) ![](img/DSMA10_Gauss.svg) ![](img/DSMA10_B.svg) ![](img/DSMA10_HF.svg) ![](img/DSMA10_ImpulseHF.svg) ![](img/DSMA10_SawtoothHF.svg) ![](img/DSMA10_SineG.svg) ![](img/DSMA10_ChirpG.svg) ![](img/DSMA10_Complex.svg) ![](img/DSMA10_Market.svg) diff --git a/docs/indicators/averages/dsma/dsma.md b/docs/indicators/averages/dsma/dsma.md deleted file mode 100644 index 2a7446b9..00000000 --- a/docs/indicators/averages/dsma/dsma.md +++ /dev/null @@ -1,62 +0,0 @@ -## DSMA: Deviation Scaled Moving Average - -### Concept - -DSMA is an adaptive moving average that adjusts its responsiveness based on the volatility of the price action. It uses a scaling factor derived from the standard deviation of prices to modify the weight of the most recent price in the average calculation. - -### Origin - -DSMA was developed by Tushar Chande and appeared in his book "*Beyond Technical Analysis*" (1997). It was created to address the limitations of fixed-parameter moving averages by incorporating a measure of market volatility into the calculation. - -### Key Features - -1. **Volatility Adaptation**: Adjusts its behavior based on market volatility, becoming more responsive in volatile markets and more stable in quiet markets. -2. **Standard Deviation Scaling**: Uses the standard deviation of prices to scale the weight of the most recent price. -3. **Self-Adjusting**: Automatically adapts to changing market conditions without manual parameter adjustments. Overshooting is sharp but short. -4. **Lag Reduction**: Designed to reduce lag in volatile markets while maintaining smoothness in stable markets. - -### Usage - -1. **Trend Identification**: DSMA can identify trends more effectively than traditional moving averages, especially in markets with changing volatility. -2. **Signal Generation**: Crossovers between DSMA and price, or between different DSMA settings, can generate trading signals. -3. **Dynamic Support and Resistance**: The DSMA line can act as dynamic support and resistance levels that adapt to market volatility. -4. **Volatility Analysis**: The behavior of DSMA relative to price can provide insights into market volatility and potential trend changes. - -### Advantages - -- Adapts automatically to changes in market volatility. -- Reduces lag in volatile markets while maintaining smoothness in stable markets. -- Potentially more effective in capturing price movements across different market conditions. -- Eliminates the need for frequent manual adjustments of moving average parameters. - -### Considerations - -- **Period**: Determines the number of price bars used in both the moving average and standard deviation calculations. - -- **Scaling Factor**: The standard deviation is used to create a scaling factor that adjusts the weight of the most recent price. This factor is typically constrained within a range (e.g., 0.1 to 1.0) to prevent extreme values. - -- **Calculation**: The general form of the DSMA calculation is: - DSMA = α * Price + (1 - α) * Previous DSMA - Where α is determined by the scaling factor derived from the standard deviation. - -- **Sensitivity to Volatility Changes**: - - In high volatility periods, DSMA becomes more responsive, potentially providing earlier signals. - - In low volatility periods, DSMA becomes more smooth, potentially reducing false signals. - -- **Comparison to Fixed-Parameter MAs**: - - DSMA may outperform fixed-parameter moving averages in markets with varying volatility. - - It may provide a good balance between the responsiveness of shorter-term MAs and the stability of longer-term MAs. - -- **Whipsaws**: While DSMA adapts to volatility, it may still be subject to whipsaws, especially during periods of volatility transition. - -- **Computational Complexity**: More complex to calculate than simple moving averages due to the standard deviation calculation and scaling factor application. - -- **Interpretation**: - - The distance between price and DSMA can provide insights into market volatility and potential overbought/oversold conditions. - - Traders should be aware of how DSMA behaves in different volatility environments for effective interpretation. - -- **Parameter Optimization**: While DSMA is self-adjusting, the choice of period and any constraints on the scaling factor may still require optimization for specific trading strategies or markets. - -- **Multiple Time Frame Analysis**: Using DSMAs on different time frames can provide a more comprehensive view of trends and volatility across various time horizons. - -- **Complementary Indicators**: DSMA can be particularly effective when used in conjunction with other volatility-based indicators or oscillators for confirmation of signals. \ No newline at end of file diff --git a/docs/indicators/averages/dsma/img/DSMA10_B.svg b/docs/indicators/averages/dsma/img/DSMA10_B.svg deleted file mode 100644 index 9b830e86..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Chirp.svg b/docs/indicators/averages/dsma/img/DSMA10_Chirp.svg deleted file mode 100644 index ee006f26..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_ChirpG.svg b/docs/indicators/averages/dsma/img/DSMA10_ChirpG.svg deleted file mode 100644 index 8ef73fe9..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Complex.svg b/docs/indicators/averages/dsma/img/DSMA10_Complex.svg deleted file mode 100644 index 3d5a2f97..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Gauss.svg b/docs/indicators/averages/dsma/img/DSMA10_Gauss.svg deleted file mode 100644 index a71e42f0..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_HF.svg b/docs/indicators/averages/dsma/img/DSMA10_HF.svg deleted file mode 100644 index 971d3156..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Impulse.svg b/docs/indicators/averages/dsma/img/DSMA10_Impulse.svg deleted file mode 100644 index 96a2a7cf..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Impulse.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_ImpulseHF.svg b/docs/indicators/averages/dsma/img/DSMA10_ImpulseHF.svg deleted file mode 100644 index 80130b8e..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Market.svg b/docs/indicators/averages/dsma/img/DSMA10_Market.svg deleted file mode 100644 index d8badc3b..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Sawtooth.svg b/docs/indicators/averages/dsma/img/DSMA10_Sawtooth.svg deleted file mode 100644 index f03cbb58..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Sawtooth.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_SawtoothHF.svg b/docs/indicators/averages/dsma/img/DSMA10_SawtoothHF.svg deleted file mode 100644 index 3fe385c3..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Sine.svg b/docs/indicators/averages/dsma/img/DSMA10_Sine.svg deleted file mode 100644 index e24f46e1..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Sine.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Sine - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_SineG.svg b/docs/indicators/averages/dsma/img/DSMA10_SineG.svg deleted file mode 100644 index 0427fa08..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Spike.svg b/docs/indicators/averages/dsma/img/DSMA10_Spike.svg deleted file mode 100644 index 8281c498..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Spike.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_Triangle.svg b/docs/indicators/averages/dsma/img/DSMA10_Triangle.svg deleted file mode 100644 index 62a2cbe1..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dsma/img/DSMA10_White.svg b/docs/indicators/averages/dsma/img/DSMA10_White.svg deleted file mode 100644 index 4b465bea..00000000 --- a/docs/indicators/averages/dsma/img/DSMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - DSMA(10, 0.50) - - diff --git a/docs/indicators/averages/dwma/analysis.md b/docs/indicators/averages/dwma/analysis.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/dwma/calc.md b/docs/indicators/averages/dwma/calc.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/dwma/charts.dib b/docs/indicators/averages/dwma/charts.dib deleted file mode 100644 index 8542000b..00000000 --- a/docs/indicators/averages/dwma/charts.dib +++ /dev/null @@ -1,60 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "DWMA"; -int p = 10; -Func Indicator = period => new Dwma(period); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/dwma/charts.md b/docs/indicators/averages/dwma/charts.md deleted file mode 100644 index b29c1235..00000000 --- a/docs/indicators/averages/dwma/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# DWMA Charts - -![](img/DWMA10_Spike.svg) ![](img/DWMA10_Impulse.svg) ![](img/DWMA10_Triangle.svg) ![](img/DWMA10_Sawtooth.svg) ![](img/DWMA10_Sine.svg) ![](img/DWMA10_Chirp.svg) ![](img/DWMA10_White.svg) ![](img/DWMA10_Gauss.svg) ![](img/DWMA10_B.svg) ![](img/DWMA10_HF.svg) ![](img/DWMA10_ImpulseHF.svg) ![](img/DWMA10_SawtoothHF.svg) ![](img/DWMA10_SineG.svg) ![](img/DWMA10_ChirpG.svg) ![](img/DWMA10_Complex.svg) ![](img/DWMA10_Market.svg) diff --git a/docs/indicators/averages/dwma/dwma.md b/docs/indicators/averages/dwma/dwma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/dwma/img/DWMA10_B.svg b/docs/indicators/averages/dwma/img/DWMA10_B.svg deleted file mode 100644 index 08e5651a..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Chirp.svg b/docs/indicators/averages/dwma/img/DWMA10_Chirp.svg deleted file mode 100644 index 251d571e..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_ChirpG.svg b/docs/indicators/averages/dwma/img/DWMA10_ChirpG.svg deleted file mode 100644 index cd4f6cc4..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Complex.svg b/docs/indicators/averages/dwma/img/DWMA10_Complex.svg deleted file mode 100644 index c9cfb0c8..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Gauss.svg b/docs/indicators/averages/dwma/img/DWMA10_Gauss.svg deleted file mode 100644 index 13a5e373..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_HF.svg b/docs/indicators/averages/dwma/img/DWMA10_HF.svg deleted file mode 100644 index 08028b45..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Impulse.svg b/docs/indicators/averages/dwma/img/DWMA10_Impulse.svg deleted file mode 100644 index 8a8957e7..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Impulse.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_ImpulseHF.svg b/docs/indicators/averages/dwma/img/DWMA10_ImpulseHF.svg deleted file mode 100644 index b0286f37..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Market.svg b/docs/indicators/averages/dwma/img/DWMA10_Market.svg deleted file mode 100644 index eb1b87b6..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Sawtooth.svg b/docs/indicators/averages/dwma/img/DWMA10_Sawtooth.svg deleted file mode 100644 index 0393a32a..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Sawtooth.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_SawtoothHF.svg b/docs/indicators/averages/dwma/img/DWMA10_SawtoothHF.svg deleted file mode 100644 index 12b7c88c..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Sine.svg b/docs/indicators/averages/dwma/img/DWMA10_Sine.svg deleted file mode 100644 index e81ae1b2..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Sine.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Sine - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_SineG.svg b/docs/indicators/averages/dwma/img/DWMA10_SineG.svg deleted file mode 100644 index 1265ef2e..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Spike.svg b/docs/indicators/averages/dwma/img/DWMA10_Spike.svg deleted file mode 100644 index 1a42610d..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Spike.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_Triangle.svg b/docs/indicators/averages/dwma/img/DWMA10_Triangle.svg deleted file mode 100644 index aa055fa2..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - DWMA(10) - - diff --git a/docs/indicators/averages/dwma/img/DWMA10_White.svg b/docs/indicators/averages/dwma/img/DWMA10_White.svg deleted file mode 100644 index 497dd03e..00000000 --- a/docs/indicators/averages/dwma/img/DWMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - DWMA(10) - - diff --git a/docs/indicators/averages/ema/analysis.md b/docs/indicators/averages/ema/analysis.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/ema/calc.md b/docs/indicators/averages/ema/calc.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/ema/calculation.md b/docs/indicators/averages/ema/calculation.md deleted file mode 100644 index 5793805e..00000000 --- a/docs/indicators/averages/ema/calculation.md +++ /dev/null @@ -1,55 +0,0 @@ -## EMA - Calculation Method - -The EMA calculation utilizes a weighting multiplier, typically denoted as the smoothing factor ($alpha$). This factor is calculated as: - -$alpha = \frac{2}{period + 1}$ - -where 'period' represents the chosen period for the EMA. - -The general formula for EMA required for arithmetic operations: - -$EMA_n = (data_{n} \times alpha) + (EMA_{n-1} \times (1 - alpha))$ - -or in optimized form (requires only three arithmetic operations instead of four): - -$EMA_n = {alpha}\times ({data_{n}} - EMA_{n-1}) + EMA_{n-1}$ - - - -When calculating the Exponential Moving Average (EMA) and there is not enough data (n < period), several approaches can be considered. Each method has its own pros and cons: - -#### 1. Assume all previous values were 0 - -$EMA_0 = 0$ \ -$EMA_n = alpha \times (data_n - EMA_{n-1}) + EMA_{n-1}$ - -- Will lead to significant underestimation of EMA in early periods - -#### 2. Calculate as if all previous values were the same as the first value - -$EMA_0 = data_0$ \ -$EMA_n = alpha \times (data_n - EMA_{n-1}) + EMA_{n-1}$ - -- Will overestimate early EMA if initial data point is far from representative - -#### 3. Use SMA instead of EMA for the first period - -$EMA_n = \left\{ \begin{array}{cl} -\frac{1}{p}\left( data_{n}-data_{n-p}\right)+SMA_{n-1} & : \ n \leq period \\ -{alpha}\times ({data_{n}} - EMA_{n-1}) + EMA_{n-1} & : \ n > period -\end{array} \right.$ - -- Creates a discontinuity when switching from SMA to EMA - - - -### Conclusion - -The choice of method depends on the specific requirements of the application: - -- Method 1 is suitable for applications where underestimation in early periods is acceptable. -- Method 2 is beneficial when a smooth transition is crucial and the initial data point is representative. -- Method 3 is appropriate when simplicity is preferred and a clear distinction between SMA and EMA is acceptable. -- Method 4 offers a good balance between adaptability and maintaining the EMA concept, but may require additional explanation to users. - - diff --git a/docs/indicators/averages/ema/charts.dib b/docs/indicators/averages/ema/charts.dib deleted file mode 100644 index aef824dc..00000000 --- a/docs/indicators/averages/ema/charts.dib +++ /dev/null @@ -1,60 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "EMA"; -int p = 10; -Func Indicator = period => new Ema(period); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/ema/charts.md b/docs/indicators/averages/ema/charts.md deleted file mode 100644 index ddcd25f0..00000000 --- a/docs/indicators/averages/ema/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# EMA Charts - -![](img/EMA10_Spike.svg) ![](img/EMA10_Impulse.svg) ![](img/EMA10_Triangle.svg) ![](img/EMA10_Sawtooth.svg) ![](img/EMA10_Sine.svg) ![](img/EMA10_Chirp.svg) ![](img/EMA10_White.svg) ![](img/EMA10_Gauss.svg) ![](img/EMA10_B.svg) ![](img/EMA10_HF.svg) ![](img/EMA10_ImpulseHF.svg) ![](img/EMA10_SawtoothHF.svg) ![](img/EMA10_SineG.svg) ![](img/EMA10_ChirpG.svg) ![](img/EMA10_Complex.svg) ![](img/EMA10_Market.svg) diff --git a/docs/indicators/averages/ema/ema.md b/docs/indicators/averages/ema/ema.md deleted file mode 100644 index 6b303acd..00000000 --- a/docs/indicators/averages/ema/ema.md +++ /dev/null @@ -1,4 +0,0 @@ -## EMA: Exponential Moving Average - -The Exponential Moving Average (EMA) is one of the oldest statistical tools used in time series analysis, particularly in financial markets. It is a type of Infinite Impulse Response (IIR) filter that incorporates all past data into its calculation, albeit with exponentially decreasing weights. - diff --git a/docs/indicators/averages/ema/img/EMA10_B.svg b/docs/indicators/averages/ema/img/EMA10_B.svg deleted file mode 100644 index b41c4506..00000000 --- a/docs/indicators/averages/ema/img/EMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Chirp.svg b/docs/indicators/averages/ema/img/EMA10_Chirp.svg deleted file mode 100644 index 47172237..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_ChirpG.svg b/docs/indicators/averages/ema/img/EMA10_ChirpG.svg deleted file mode 100644 index 923d5b13..00000000 --- a/docs/indicators/averages/ema/img/EMA10_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Complex.svg b/docs/indicators/averages/ema/img/EMA10_Complex.svg deleted file mode 100644 index b714fb89..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Gauss.svg b/docs/indicators/averages/ema/img/EMA10_Gauss.svg deleted file mode 100644 index 5539019a..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_HF.svg b/docs/indicators/averages/ema/img/EMA10_HF.svg deleted file mode 100644 index d59b82dd..00000000 --- a/docs/indicators/averages/ema/img/EMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Impulse.svg b/docs/indicators/averages/ema/img/EMA10_Impulse.svg deleted file mode 100644 index 703e1d87..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Impulse.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_ImpulseHF.svg b/docs/indicators/averages/ema/img/EMA10_ImpulseHF.svg deleted file mode 100644 index ba2483f4..00000000 --- a/docs/indicators/averages/ema/img/EMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Market.svg b/docs/indicators/averages/ema/img/EMA10_Market.svg deleted file mode 100644 index 5d7b41eb..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Sawtooth.svg b/docs/indicators/averages/ema/img/EMA10_Sawtooth.svg deleted file mode 100644 index 9db62420..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Sawtooth.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_SawtoothHF.svg b/docs/indicators/averages/ema/img/EMA10_SawtoothHF.svg deleted file mode 100644 index 867e705a..00000000 --- a/docs/indicators/averages/ema/img/EMA10_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Sine.svg b/docs/indicators/averages/ema/img/EMA10_Sine.svg deleted file mode 100644 index 9abeb095..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Sine.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Sine - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_SineG.svg b/docs/indicators/averages/ema/img/EMA10_SineG.svg deleted file mode 100644 index 7aa35836..00000000 --- a/docs/indicators/averages/ema/img/EMA10_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Spike.svg b/docs/indicators/averages/ema/img/EMA10_Spike.svg deleted file mode 100644 index 9850ccba..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Spike.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_Triangle.svg b/docs/indicators/averages/ema/img/EMA10_Triangle.svg deleted file mode 100644 index 7c95c5b2..00000000 --- a/docs/indicators/averages/ema/img/EMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - EMA(10) - - diff --git a/docs/indicators/averages/ema/img/EMA10_White.svg b/docs/indicators/averages/ema/img/EMA10_White.svg deleted file mode 100644 index f10da3cd..00000000 --- a/docs/indicators/averages/ema/img/EMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - EMA(10) - - diff --git a/docs/indicators/averages/ema/quality.md b/docs/indicators/averages/ema/quality.md deleted file mode 100644 index 87a4a71c..00000000 --- a/docs/indicators/averages/ema/quality.md +++ /dev/null @@ -1,48 +0,0 @@ -## EMA - Qualitative Ratings - -**Smoothness: 3/5** - EMA provides moderate smoothing. It's smoother than raw price data but less smooth than a Simple Moving Average (SMA) of the same period. The exponential weighting can sometimes allow short-term fluctuations to influence the average more than in an SMA. - -**Sensitivity: 4/5** - EMA can be quite sensitive to price changes, especially with high alpha values that prioritize more recent values. The exponential weighting means it reacts more quickly to new data compared to an SMA, making it more responsive to recent price movements and potential trend changes. - -**Overshooting: 5/5** - EMA, by its mathematical formulation, does not overshoot the latest price. It always falls between the most recent price and the previous EMA value. This property makes it excellent at avoiding overshooting, which is a significant advantage over some other types of moving averages that can extend beyond the range of actual prices. - -**Lag: 2/5** - EMA reduces lag compared to an SMA of the same period, but still introduces a very noticeable delay. While it responds more quickly to price changes than an SMA, it still lags behind the actual price movements, especially in rapidly trending markets or during significant reversals. - -### EMA - Key Characteristics - -- **IIR nature:** As an IIR filter, EMA's current value depends on **all** past inputs, theoretically extending the need for historical values back to infinity. IIR nature of EMA is a reason that EMA requires at least 1 - (1 - α)^N points to get to desired percentile of accuracy and be deemed 'warmed-up' for trading: -``` -EMA(5): 13 points to reach 95% accuracy -EMA(10): 27 ponts to reach 95% accuracy -EMA(20): 55 points to reach 95% accuracy -EMA(50): 138 points to reach 95% accuracy -EMA(100): 277 points to reach 95% accuracy -``` - -- **Weighted calculation:** Recent data points carry more significance, with weights decreasing exponentially for older data. The *period* number of bars represents only 86.5% of weights of calculated Ema. - -![EMA Weights](../../../img/emaweights.svg) - -- **Period parameter:** Period has no meaningful value beyond trivialization of calculating alpha. Weighting coefficient *alpha* is calculated from *period* as `alpha = 2/(period+1)`, making initial set of alphas: - -``` -Period (N) | Alpha (α) ------------|----------- - 1 | 1.00 - 2 | 0.67 - 3 | 0.50 - 4 | 0.40 - 5 | 0.33 - 6 | 0.29 - 7 | 0.25 - 8 | 0.22 - 9 | 0.20 - 10 | 0.18 -``` - -But alpha factor can be any value between 1.00 and 0.00, not just discrete numbers calculated from Period. For fine-tuning trading strategies, avoid using period for any indicator in exponential (EMA) family. - -- **Reduced lag:** EMA exhibits less delay in reflecting trend changes compared to Simple Moving Average (SMA) as it weights more recent values progressively more. - - - diff --git a/docs/indicators/averages/epma/epma.md b/docs/indicators/averages/epma/epma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/frama/frama.md b/docs/indicators/averages/frama/frama.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/fwma/fwma.md b/docs/indicators/averages/fwma/fwma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/gma/gma.md b/docs/indicators/averages/gma/gma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/hma/hma.md b/docs/indicators/averages/hma/hma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/htit/htit.md b/docs/indicators/averages/htit/htit.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/hwma/hwma.md b/docs/indicators/averages/hwma/hwma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/jma/calc.md b/docs/indicators/averages/jma/calc.md deleted file mode 100644 index 86c9c3f4..00000000 --- a/docs/indicators/averages/jma/calc.md +++ /dev/null @@ -1,48 +0,0 @@ -# JMA Calculation - -### Initial Parameters: - -$\beta = factor \cdot \frac{period - 1}{factor \cdot (period - 1) + 2}$ - -$len1 = \frac{\ln(\sqrt{period - 1})}{\ln(2)} + 2$ - -$pow1 = \max(len1 - 2, 0.5)$ - -$phase \in [0.5, 2.5]$ (clamped to $(phase \cdot 0.01) + 1.5$) - -### Volatility Calculations: - -$del1_t = price_t - upperBand_{t-1}$ - -$del2_t = price_t - lowerBand_{t-1}$ - -$volty_t = \max(|del1_t|, |del2_t|)$ - -$vSum_t = \frac{\sum_{i=t-buffer+1}^t volty_i}{buffer}$ - -$avgVolty_t = \text{mean}(vSum_{t-64:t})$ - -$rVolty_t = \text{clamp}(\frac{volty_t}{avgVolty_t}, 1, len1^{1/pow1})$ - -### Band Calculations: - -$pow2_t = rVolty_t^{pow1}$ - -$K_v = \beta^{\sqrt{pow2_t}}$ - - -$upperBand_t = price_t - K_v \cdot del1_t$ - - - -$\alpha_t = \beta^{pow2_t}$ - -$ma1_t = price_t + \alpha_t(ma1_{t-1} - price_t)$ - -$det0_t = price_t + \beta(det0_{t-1} - price_t + ma1_t) - ma1_t$ - -$ma2_t = ma1_t + phase \cdot det0_t$ - -$det1_t = (ma2_t - jma_{t-1})(1-\alpha_t)^2 + \alpha_t^2 \cdot det1_{t-1}$ - -$jma_t = jma_{t-1} + det1_t$ \ No newline at end of file diff --git a/docs/indicators/averages/jma/jma.md b/docs/indicators/averages/jma/jma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/kama/kama.md b/docs/indicators/averages/kama/kama.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/ltma/ltma.md b/docs/indicators/averages/ltma/ltma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/maaf/maaf.md b/docs/indicators/averages/maaf/maaf.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/mama/mama.md b/docs/indicators/averages/mama/mama.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/mgdi/mgdi.md b/docs/indicators/averages/mgdi/mgdi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/mma/mma.md b/docs/indicators/averages/mma/mma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/pwma/pwma.md b/docs/indicators/averages/pwma/pwma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/qema/qema.md b/docs/indicators/averages/qema/qema.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/rema/rema.md b/docs/indicators/averages/rema/rema.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/rma/rma.md b/docs/indicators/averages/rma/rma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/sinema/sinema.md b/docs/indicators/averages/sinema/sinema.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/sma/calc.md b/docs/indicators/averages/sma/calc.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/sma/charts.dib b/docs/indicators/averages/sma/charts.dib deleted file mode 100644 index dbdb13ba..00000000 --- a/docs/indicators/averages/sma/charts.dib +++ /dev/null @@ -1,60 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "SMA"; -int p = 10; -Func Indicator = period => new Sma(period); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/sma/charts.md b/docs/indicators/averages/sma/charts.md deleted file mode 100644 index 2130241b..00000000 --- a/docs/indicators/averages/sma/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# SMA Charts - -![](img/SMA10_Spike.svg) ![](img/SMA10_Impulse.svg) ![](img/SMA10_Triangle.svg) ![](img/SMA10_Sawtooth.svg) ![](img/SMA10_Sine.svg) ![](img/SMA10_Chirp.svg) ![](img/SMA10_White.svg) ![](img/SMA10_Gauss.svg) ![](img/SMA10_B.svg) ![](img/SMA10_HF.svg) ![](img/SMA10_ImpulseHF.svg) ![](img/SMA10_SawtoothHF.svg) ![](img/SMA10_SineG.svg) ![](img/SMA10_ChirpG.svg) ![](img/SMA10_Complex.svg) ![](img/SMA10_Market.svg) diff --git a/docs/indicators/averages/sma/img/SMA10_B.svg b/docs/indicators/averages/sma/img/SMA10_B.svg deleted file mode 100644 index a46f63de..00000000 --- a/docs/indicators/averages/sma/img/SMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Chirp.svg b/docs/indicators/averages/sma/img/SMA10_Chirp.svg deleted file mode 100644 index c7e76419..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Chirp.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Chirp - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_ChirpG.svg b/docs/indicators/averages/sma/img/SMA10_ChirpG.svg deleted file mode 100644 index 9e5f5029..00000000 --- a/docs/indicators/averages/sma/img/SMA10_ChirpG.svg +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Complex.svg b/docs/indicators/averages/sma/img/SMA10_Complex.svg deleted file mode 100644 index b6d1bd9c..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Complex.svg +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Gauss.svg b/docs/indicators/averages/sma/img/SMA10_Gauss.svg deleted file mode 100644 index e965054b..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_HF.svg b/docs/indicators/averages/sma/img/SMA10_HF.svg deleted file mode 100644 index 25035a25..00000000 --- a/docs/indicators/averages/sma/img/SMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Impulse.svg b/docs/indicators/averages/sma/img/SMA10_Impulse.svg deleted file mode 100644 index 3de92634..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Impulse.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_ImpulseHF.svg b/docs/indicators/averages/sma/img/SMA10_ImpulseHF.svg deleted file mode 100644 index 3c6a8507..00000000 --- a/docs/indicators/averages/sma/img/SMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Market.svg b/docs/indicators/averages/sma/img/SMA10_Market.svg deleted file mode 100644 index 741aac20..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Sawtooth.svg b/docs/indicators/averages/sma/img/SMA10_Sawtooth.svg deleted file mode 100644 index e45ddf26..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Sawtooth.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_SawtoothHF.svg b/docs/indicators/averages/sma/img/SMA10_SawtoothHF.svg deleted file mode 100644 index aa6fdc64..00000000 --- a/docs/indicators/averages/sma/img/SMA10_SawtoothHF.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Sine.svg b/docs/indicators/averages/sma/img/SMA10_Sine.svg deleted file mode 100644 index a69849cc..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Sine.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - Sine - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_SineG.svg b/docs/indicators/averages/sma/img/SMA10_SineG.svg deleted file mode 100644 index db73aa27..00000000 --- a/docs/indicators/averages/sma/img/SMA10_SineG.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Spike.svg b/docs/indicators/averages/sma/img/SMA10_Spike.svg deleted file mode 100644 index c3c45a07..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Spike.svg +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_Triangle.svg b/docs/indicators/averages/sma/img/SMA10_Triangle.svg deleted file mode 100644 index 4bc032ff..00000000 --- a/docs/indicators/averages/sma/img/SMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - SMA(10) - - diff --git a/docs/indicators/averages/sma/img/SMA10_White.svg b/docs/indicators/averages/sma/img/SMA10_White.svg deleted file mode 100644 index 992e0c05..00000000 --- a/docs/indicators/averages/sma/img/SMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - SMA(10) - - diff --git a/docs/indicators/averages/sma/sma.md b/docs/indicators/averages/sma/sma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/smma/smma.md b/docs/indicators/averages/smma/smma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/t3/t3.md b/docs/indicators/averages/t3/t3.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/tema/analysis.md b/docs/indicators/averages/tema/analysis.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/tema/calc.md b/docs/indicators/averages/tema/calc.md deleted file mode 100644 index 631b5647..00000000 --- a/docs/indicators/averages/tema/calc.md +++ /dev/null @@ -1,52 +0,0 @@ -# The Math Behind TEMA - -## Components of TEMA - -TEMA is composed of three main components: - -1. Exponential Moving Average (EMA) -2. A "triple smoothing" factor - -Let's break these down: - -### EMA Calculation - -The Exponential Moving Average (EMA) is calculated as: - -$ EMA_t = \alpha \cdot P_t + (1 - \alpha) \cdot EMA_{t-1} $ - -Where: -- $EMA_t$ is the EMA value at time $t$ -- $P_t$ is the price at time $t$ -- $\alpha$ is the smoothing factor, calculated as $\frac{2}{n+1}$ -- $n$ is the number of periods - -### TEMA Formula - -The TEMA is then calculated using the following formula: - -$ TEMA_t = 3 \cdot EMA_t - 3 \cdot EMA(EMA_t) + EMA(EMA(EMA_t)) $ - -Where: -- $TEMA_t$ is the TEMA value at time $t$ -- $EMA_t$ is the EMA of the price -- $EMA(EMA_t)$ is the EMA of the EMA -- $EMA(EMA(EMA_t))$ is the EMA of the EMA of the EMA - -## Calculation Process - -1. Calculate the EMA of the price series (EMA1). -2. Calculate another EMA on the result of step 1 (EMA2). -3. Calculate a third EMA on the result of step 2 (EMA3). -4. Multiply EMA1 by 3. -5. Multiply EMA2 by 3. -6. Subtract EMA2 * 3 from EMA1 * 3. -7. Add EMA3 to the result. - -This process effectively reduces lag while maintaining smoothness and attempting to minimize overshooting. - -## Parameter - -TEMA uses a single parameter: - -- **Period** ($n$): Determines the number of periods used in the EMA calculations. This affects the overall reactivity and smoothness of the indicator. \ No newline at end of file diff --git a/docs/indicators/averages/tema/charts.dib b/docs/indicators/averages/tema/charts.dib deleted file mode 100644 index 956337cb..00000000 --- a/docs/indicators/averages/tema/charts.dib +++ /dev/null @@ -1,60 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget: ScottPlot" - -using QuanTAlib; -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; - -QuanTAlib.Formatters.Initialize(); -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -Dictionary Data = new Dictionary -{ - { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, - { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, - { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }, - { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, - { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, - { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, - { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, - { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, - { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, - { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, - { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, - { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, - { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, - { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, - { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } - -}; - -#!csharp - -String Name = "TEMA"; -int p = 10; -Func Indicator = period => new Tema(period); - -foreach (var item in Data) { - string Signal = item.Key; - double[] Input = item.Value; - TSeries Output = new(); - var ma = Indicator(p); - foreach (var value in Input) { Output.Add(ma.Calc(value)); } - Plot plt = new(); - var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; - var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p})"); - plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); -} diff --git a/docs/indicators/averages/tema/charts.md b/docs/indicators/averages/tema/charts.md deleted file mode 100644 index a7309bfd..00000000 --- a/docs/indicators/averages/tema/charts.md +++ /dev/null @@ -1,3 +0,0 @@ -# TEMA Charts - -![](img/TEMA10_Spike.svg) ![](img/TEMA10_Impulse.svg) ![](img/TEMA10_Triangle.svg) ![](img/TEMA10_Sawtooth.svg) ![](img/TEMA10_Sine.svg) ![](img/TEMA10_Chirp.svg) ![](img/TEMA10_White.svg) ![](img/TEMA10_Gauss.svg) ![](img/TEMA10_B.svg) ![](img/TEMA10_HF.svg) ![](img/TEMA10_ImpulseHF.svg) ![](img/TEMA10_SawtoothHF.svg) ![](img/TEMA10_SineG.svg) ![](img/TEMA10_ChirpG.svg) ![](img/TEMA10_Complex.svg) ![](img/TEMA10_Market.svg) diff --git a/docs/indicators/averages/tema/img/TEMA10_B.svg b/docs/indicators/averages/tema/img/TEMA10_B.svg deleted file mode 100644 index e0b2fac7..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_B.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - B - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Chirp.svg b/docs/indicators/averages/tema/img/TEMA10_Chirp.svg deleted file mode 100644 index 88cd9d6e..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Chirp.svg +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Chirp - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_ChirpG.svg b/docs/indicators/averages/tema/img/TEMA10_ChirpG.svg deleted file mode 100644 index 0cb96318..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_ChirpG.svg +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ChirpG - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Complex.svg b/docs/indicators/averages/tema/img/TEMA10_Complex.svg deleted file mode 100644 index fa50d5dd..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Complex.svg +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 170 - - - - 172 - - - - 174 - - - - 176 - - - - 178 - - - - - - - - - - - - - - - - - - - - - - - - - - - Complex - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Gauss.svg b/docs/indicators/averages/tema/img/TEMA10_Gauss.svg deleted file mode 100644 index f56510ae..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Gauss.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - Gauss - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_HF.svg b/docs/indicators/averages/tema/img/TEMA10_HF.svg deleted file mode 100644 index 6227f0fc..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_HF.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - HF - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Impulse.svg b/docs/indicators/averages/tema/img/TEMA10_Impulse.svg deleted file mode 100644 index e4d9cf92..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Impulse.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - 1.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Impulse - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg b/docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg deleted file mode 100644 index 90c19c1d..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - ImpulseHF - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Market.svg b/docs/indicators/averages/tema/img/TEMA10_Market.svg deleted file mode 100644 index f3b8bef4..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Market.svg +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 - - - - 66 - - - - 68 - - - - 70 - - - - 72 - - - - 74 - - - - 76 - - - - 78 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Market - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg b/docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg deleted file mode 100644 index 4481c708..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg +++ /dev/null @@ -1,364 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -5 - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sawtooth - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg b/docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg deleted file mode 100644 index 9a6da825..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -10 - - - - 0 - - - - 10 - - - - 20 - - - - 30 - - - - 40 - - - - - - - - - - - - - - - - - - - - - - - - - SawtoothHF - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Sine.svg b/docs/indicators/averages/tema/img/TEMA10_Sine.svg deleted file mode 100644 index 9c3950fa..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Sine.svg +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Sine - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_SineG.svg b/docs/indicators/averages/tema/img/TEMA10_SineG.svg deleted file mode 100644 index ac43a37a..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_SineG.svg +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.5 - - - - -1 - - - - -0.5 - - - - 0 - - - - 0.5 - - - - 1 - - - - 1.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SineG - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Spike.svg b/docs/indicators/averages/tema/img/TEMA10_Spike.svg deleted file mode 100644 index de7a15bf..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Spike.svg +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0.2 - - - - 0.4 - - - - 0.6 - - - - 0.8 - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Spike - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_Triangle.svg b/docs/indicators/averages/tema/img/TEMA10_Triangle.svg deleted file mode 100644 index 1a6e063e..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_Triangle.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Triangle - TEMA(10) - - diff --git a/docs/indicators/averages/tema/img/TEMA10_White.svg b/docs/indicators/averages/tema/img/TEMA10_White.svg deleted file mode 100644 index 69601237..00000000 --- a/docs/indicators/averages/tema/img/TEMA10_White.svg +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 5 - - - - 10 - - - - 15 - - - - 20 - - - - 25 - - - - 30 - - - - 35 - - - - 40 - - - - 45 - - - - 50 - - - - 55 - - - - 60 - - - - 65 - - - - 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.4 - - - - -0.2 - - - - 0 - - - - 0.2 - - - - 0.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - White - TEMA(10) - - diff --git a/docs/indicators/averages/tema/tema.md b/docs/indicators/averages/tema/tema.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/trima/trima.md b/docs/indicators/averages/trima/trima.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/vidya/vidya.md b/docs/indicators/averages/vidya/vidya.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/wma/wma.md b/docs/indicators/averages/wma/wma.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/averages/zlema/zlema.md b/docs/indicators/averages/zlema/zlema.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/indicators.md b/docs/indicators/indicators.md deleted file mode 100644 index 5ea890c9..00000000 --- a/docs/indicators/indicators.md +++ /dev/null @@ -1,208 +0,0 @@ -# Indicators in QuanTAlib - -| **Category** | **Status** | **Completion** | -|--------------|:----------:|:--------------:| -| Basic Transforms | 6 of 6 | 100% | -| Averages & Trends | 33 of 33 | 100% | -| Momentum | 16 of 16 | 100% | -| Oscillators | 24 of 29 | 83% | -| Volatility | 29 of 35 | 83% | -| Volume | 19 of 19 | 100% | -| Numerical Analysis | 15 of 19 | 79% | -| Errors | 16 of 16 | 100% | -| Patterns | 0 of 8 | 0% | -| **Total** | **158 of 181** | **87%** | - -|Technical Indicator Name| Class Name| -|-----------|:----------:| -|**BASIC TRANSFORMS**|| -|OC2 - Midpoint price|`.OC2`| -|HL2 - Median Price|`.HL2`| -|HLC3 - Typical Price|`.HLC3`| -|OHL3 - Mean Price|`.OHL3`| -|OHLC4 - Average Price|`.OHLC4`| -|HLCC4 - Weighted Price|`.HLCC4`| -|**AVERAGES & TRENDS**|| -|AFIRMA - Adaptive FIR Moving Average|`Afirma`| -|ALMA - Arnaud Legoux Moving Average|`Alma`| -|DEMA - Double Exponential Moving Average|`Dema`| -|DSMA - Dynamic Simple Moving Average|`Dsma`| -|DWMA - Dynamic Weighted Moving Average|`Dwma`| -|EMA - Exponential Moving Average|`Ema`| -|EPMA - Endpoint Moving Average|`Epma`| -|FRAMA - Fractal Adaptive Moving Average|`Frama`| -|FWMA - Forward Weighted Moving Average|`Fwma`| -|GMA - Gaussian Moving Average|`Gma`| -|HMA - Hull Moving Average|`Hma`| -|HTIT - Hilbert Transform Instantaneous Trendline|`Htit`| -|HWMA - Hann Weighted Moving Average|`Hwma`| -|JMA - Jurik Moving Average|`Jma`| -|KAMA - Kaufman Adaptive Moving Average|`Kama`| -|LTMA - Linear Time Moving Average|`Ltma`| -|MAAF - Moving Average Adaptive Filter|`Maaf`| -|MAMA* - MESA Adaptive Moving Average (MAMA, FAMA)|`Mama`| -|MGDI - McGinley Dynamic Indicator|`Mgdi`| -|MMA - Modified Moving Average|`Mma`| -|PWMA - Parabolic Weighted Moving Average|`Pwma`| -|QEMA - Quick Exponential Moving Average|`Qema`| -|REMA - Regularized Exponential Moving Average|`Rema`| -|RMA - Running Moving Average|`Rma`| -|SINEMA - Sine-weighted Moving Average|`Sinema`| -|SMA - Simple Moving Average|`Sma`| -|SMMA - Smoothed Moving Average|`Smma`| -|T3 - Triple Exponential Moving Average (T3)|`T3`| -|TEMA - Triple Exponential Moving Average|`Tema`| -|TRIMA - Triangular Moving Average|`Trima`| -|VIDYA - Variable Index Dynamic Average|`Vidya`| -|WMA - Weighted Moving Average|`Wma`| -|ZLEMA - Zero-Lag Exponential Moving Average|`Zlema`| -|**MOMENTUM INDICATORS**|| -|ADX - Average Directional Movement Index|`Adx`| -|ADXR - Average Directional Movement Index Rating|`Adxr`| -|APO - Absolute Price Oscillator|`Apo`| -|DMI* - Directional Movement Index (DI+, DI-)|`Dmi`| -|DMX - Jurik Directional Movement Index|`Dmx`| -|DPO - Detrended Price Oscillator|`Dpo`| -|MACD* - Moving Average Convergence/Divergence|`Macd`| -|MOM - Momentum|`Mom`| -|PMO - Price Momentum Oscillator|`Pmo`| -|PO - Price Oscillator|`Po`| -|PPO - Percentage Price Oscillator|`Ppo`| -|PRS - Price Relative Strength|`Prs`| -|ROC - Rate of Change|`Roc`| -|TRIX - 1-day ROC of TEMA|`Trix`| -|VEL - Jurik Signal Velocity|`Vel`| -|VORTEX* - Vortex Indicator (VI+, VI-)|`Vortex`| -|**OSCILLATORS**|| -|AC - Acceleration Oscillator|`Ac`| -|AO - Awesome Oscillator|`Ao`| -|AROON* - Aroon oscillator (Up, Down)|`Aroon`| -|BOP - Balance of Power|`Bop`| -|CCI - Commodity Channel Index|`Cci`| -|CFO - Chande Forcast Oscillator|`Cfo`| -|CMO - Chande Momentum Oscillator|`Cmo`| -|CHOP - Choppiness Index|`Chop`| -|COG - Ehler's Center of Gravity|`Cog`| -|COPPOCK - Coppock Curve|`Coppock`| -|CRSI - Connor RSI|`Crsi`| -|🚧 CTI - Ehler's Correlation Trend Indicator|`Cti`| -|DOSC - Derivative Oscillator|`Dosc`| -|EFI - Elder Ray's Force Index|`Efi`| -|🚧 FISHER - Fisher Transform|`Fisher`| -|🚧 FOSC - Forecast Oscillator|`Fosc`| -|🚧 GATOR* - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth)|`Gator`| -|🚧 KDJ* - KDJ Indicator (K, D, J lines)|`Kdj`| -|🚧 KRI - Kairi Relative Index|`Kri`| -|RSI - Relative Strength Index|`Rsi`| -|RSX - Jurik Trend Strength Index|`Rsx`| -|🚧 RVGI* - Relative Vigor Index (RVGI, Signal)|`Rvgi`| -|SMI - Stochastic Momentum Index|`Smi`| -|SRSI* - Stochastic RSI (SRSI, Signal)|`Srsi`| -|STC - Schaff Trend Cycle|`Stc`| -|STOCH* - Stochastic Oscillator (%K, %D)|`Stoch`| -|TSI - True Strength Index|`Tsi`| -|UO - Ultimate Oscillator|`Uo`| -|WILLR - Larry Williams' %R|`Willr`| -|**PATTERNS**|| -|🚧 DOJI - Doji Candlestick Pattern|`Doji`| -|🚧 ER* - Elder Ray Pattern (Bull Power, Bear Power)|`Er`| -|🚧 MARU - Marubozu Candlestick Pattern|`Maru`| -|🚧 PIV* - Pivot Points (Support 1-3, Pivot, Resistance 1-3)|`Piv`| -|🚧 PP* - Price Pivots (Support 1-3, Pivot, Resistance 1-3)|`Pp`| -|🚧 RPP* - Rolling Pivot Points (Support 1-3, Pivot, Resistance 1-3)|`Rpp`| -|🚧 WF - Williams Fractal|`Wf`| -|🚧 ZZ - Zig Zag Pattern|`Zz`| -|**VOLATILITY INDICATORS**|| -|ADR - Average Daily Range|`Adr`| -|AP - Andrew's Pitchfork|`Ap`| -|ATR - Average True Range|`Atr`| -|ATRP - Average True Range Percent|`Atrp`| -|ATRS - ATR Trailing Stop|`Atrs`| -|BB* - Bollinger Bands® (Upper, Middle, Lower)|`Bb`| -|CCV - Close-to-Close Volatility|`Ccv`| -|CE - Chandelier Exit|`Ce`| -|CV - Conditional Volatility (ARCH/GARCH)|`Cv`| -|CVI - Chaikin's Volatility|`Cvi`| -|🚧 DC* - Donchian Channels (Upper, Middle, Lower)|`Dc`| -|EWMA - Exponential Weighted Moving Average Volatility|`Ewma`| -|FCB - Fractal Chaos Bands|`Fcb`| -|GKV - Garman-Klass Volatility|`Gkv`| -|HLV - High-Low Volatility|`Hlv`| -|HV - Historical Volatility|`Hv`| -|🚧 ICH* - Ichimoku Cloud (Conversion, Base, Span A, Span B, Lagging Span)|`Ich`| -|JVOLTY - Jurik Volatility|`Jvolty`| -|🚧 KC* - Keltner Channels (Upper, Middle, Lower)|`Kc`| -|🚧 NATR - Normalized Average True Range|`Natr`| -|🚧 PCH - Price Channel Indicator|`Pch`| -|🚧 PSAR* - Parabolic Stop and Reverse (Value, Trend)|`Psar`| -|🚧 PV - Parkinson Volatility|`Pv`| -|🚧 RSV - Rogers-Satchell Volatility|`Rsv`| -|RV - Realized Volatility|`Rv`| -|RVI - Relative Volatility Index|`Rvi`| -|🚧 STARC* - Starc Bands (Upper, Middle, Lower)|`Starc`| -|🚧 SV - Stochastic Volatility|`Sv`| -|TR - True Range|`Tr`| -|UI - Ulcer Index|`Ui`| -|VC* - Volatility Cone (Mean, Upper Bound, Lower Bound)|`Vc`| -|VOV - Volatility of Volatility|`Vov`| -|VR - Volatility Ratio|`Vr`| -|VS* - Volatility Stop (Long Stop, Short Stop)|`Vs`| -|🚧 YZV - Yang-Zhang Volatility|`Yzv`| -|**VOLUME INDICATORS**|| -|ADL - Chaikin Accumulation Distribution Line|`Adl`| -|ADOSC - Chaikin Accumulation Distribution Oscillator|`Adosc`| -|AOBV - Archer On-Balance Volume|`Aobv`| -|CMF - Chaikin Money Flow|`Cmf`| -|EOM - Ease of Movement|`Eom`| -|KVO - Klinger Volume Oscillator|`Kvo`| -|MFI - Money Flow Index|`Mfi`| -|NVI - Negative Volume Index|`Nvi`| -|OBV - On-Balance Volume|`Obv`| -|PVI - Positive Volume Index|`Pvi`| -|PVOL - Price-Volume|`Pvol`| -|PVO - Percentage Volume Oscillator|`Pvo`| -|PVR - Price Volume Rank|`Pvr`| -|PVT - Price Volume Trend|`Pvt`| -|TVI - Trade Volume Index|`Tvi`| -|VF - Volume Force|`Vf`| -|VP - Volume Profile|`Vp`| -|VWAP - Volume Weighted Average Price|`Vwap`| -|VWMA - Volume Weighted Moving Average|`Vwma`| -|**NUMERICAL ANALYSIS**|| -|BETA* - Beta coefficient (Beta, R-squared)|`Beta`| -|CORR* - Correlation Coefficient (Correlation, P-value)|`Corr`| -|CURVATURE - Rate of Change in Direction or Slope|`Curvature`| -|ENTROPY - Measure of Uncertainty or Disorder|`Entropy`| -|HUBER - Huber Loss|`Huber`| -|HURST - Hurst Exponent|`Hurst`| -|KURTOSIS - Measure of Tails/Peakedness|`Kurtosis`| -|MAX - Maximum with exponential decay|`Max`| -|MEDIAN - Middle value|`Median`| -|MIN - Minimum with exponential decay|`Min`| -|MODE - Most Frequent Value|`Mode`| -|PERCENTILE - Rank Order|`Percentile`| -|🚧 RSQUARED* - Coefficient of Determination (R-squared, Adjusted R-squared)|`Rsquared`| -|SKEW - Skewness, asymmetry of distribution|`Skew`| -|SLOPE - Rate of Change, Linear Regression|`Slope`| -|STDDEV - Standard Deviation, Measure of Spread|`Stddev`| -|🚧 THEIL* - Theil's U Statistics (U1, U2)|`Theil`| -|🚧 TSF* - Time Series Forecast (Forecast, Confidence Interval)|`Tsf`| -|VARIANCE - Average of Squared Deviations|`Variance`| -|ZSCORE - Standardized Score|`Zscore`| -|**ERRORS**|| -|HUBER - Huber Loss|`Huber`| -|MAE - Mean Absolute Error|`Mae`| -|MAPD - Mean Absolute Percentage Deviation|`Mapd`| -|MAPE - Mean Absolute Percentage Error|`Mape`| -|MASE - Mean Absolute Scaled Error|`Mase`| -|MDA - Mean Directional Accuracy|`Mda`| -|ME - Mean Error|`Me`| -|MPE - Mean Percentage Error|`Mpe`| -|MSE - Mean Squared Error|`Mse`| -|MSLE - Mean Squared Logarithmic Error|`Msle`| -|RAE - Relative Absolute Error|`Rae`| -|RMSE - Root Mean Squared Error|`Rmse`| -|RMSLE - Root Mean Squared Logarithmic Error|`Rmsle`| -|RSE - Relative Squared Error|`Rse`| -|RSQUARED - R-Squared (Coefficient of Determination)|`Rsquared`| -|SMAPE - Symmetric Mean Absolute Percentage Error|`Smape`| diff --git a/docs/indicators/momentum/adx/description.md b/docs/indicators/momentum/adx/description.md deleted file mode 100644 index eb6166ac..00000000 --- a/docs/indicators/momentum/adx/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# ADX - Average Directional Index - -The Average Directional Index (ADX) is your market's GPS for trend strength - it doesn't tell you which direction to go, but it sure lets you know if you're on the expressway or stuck in local traffic. While most indicators focus on price direction, ADX stands apart by measuring the raw power behind a trend, helping traders distinguish between markets that are truly trending and those that are just making noise. Think of it as your trend quality assurance system, providing a standardized measure from 0-100 that helps you avoid the classic trap of seeing trends where there are only trading ranges. - -## Origin and Sources -**Creator**: J. Welles Wilder Jr. (yes, the same mathematical wizard behind RSI) introduced ADX in his groundbreaking 1978 book. - -**Historical Context**: Developed alongside his Directional Movement System (DMS), ADX emerged from Wilder's frustration with existing trend indicators that couldn't reliably distinguish between trending and ranging markets. - -**Fun Fact**: Wilder originally recommended calculating ADX by hand using 14-day periods. With just a calculator and daily prices, it took about an hour to compute a single ADX value. Today's computers do it in microseconds! - -## Core Concept -Think of ADX as a trend strength meter that works like a car's speedometer - but instead of measuring speed, it measures how forcefully price is moving in a single direction. It does this by tracking both upward and downward price movements, then combining them into a single reading that tells you how strong the overall trend is, regardless of direction. - -*Pro Tip* 🎯: While ADX values above 25 traditionally indicate a trend, crypto traders often use 20 as their threshold due to the market's inherent volatility. - -## Key Features -- **Trend Strength Measurement**: Like a seismograph for market moves, ADX measures the power of price movement regardless of direction -- **Range/Trend Differentiation**: Acts as your market state detector, helping distinguish between trending and choppy conditions -- **Momentum Confirmation**: Shows whether a trend is gaining steam or running out of gas - -## Real-World Application -### When to Use -- **Trend Confirmation**: Before entering trend-following trades, check if ADX confirms a strong trend -- **Range Detection**: When ADX is low, prepare for range-trading opportunities -- **Exit Timing**: Watch for declining ADX values in strong trends for potential exit signals - -### Common Pitfalls -1. **The Lag Trap**: ADX is like looking in the rearview mirror - it confirms trends but won't catch reversals early -2. **Direction Confusion**: A high ADX is like a wind speed meter - it tells you the wind is strong but not which way it's blowing -3. **Threshold Fixation**: Don't treat ADX levels like speed limits - market context matters more than fixed numbers - -## Complementary Indicators -- **Moving Averages**: Like having both a compass (direction) and speedometer (ADX) for your trades -- **MACD**: Adds momentum context to your trend strength readings -- **Bollinger Bands**: Helps confirm whether price volatility matches trend strength - -## Further Reading -- "New Concepts in Technical Trading Systems" by J. Welles Wilder -- "Technical Analysis of the Financial Markets" by John J. Murphy -- The definitive ADX chapter in "Technical Analysis Explained" by Martin Pring - -*Remember*: ADX is like a weather radar for trends - it won't tell you where the market's going, but it'll sure let you know if there's a storm brewing. Use it to confirm trend conditions before applying your directional strategies. \ No newline at end of file diff --git a/docs/indicators/momentum/adxr/description.md b/docs/indicators/momentum/adxr/description.md deleted file mode 100644 index af48ed41..00000000 --- a/docs/indicators/momentum/adxr/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# ADXR - Average Directional Index Rating - -The Average Directional Index Rating (ADXR) takes the already powerful ADX and adds a time machine element. By comparing current trend strength to historical trend strength, ADXR helps traders spot shifts in trend momentum before they become obvious. Think of it as having both a speedometer and a speed history - it tells you not just how fast you're going, but whether you're accelerating or slowing down compared to a previous period. - -## Origin and Sources -**Creator**: Another gem from J. Welles Wilder Jr.'s technical analysis toolkit, ADXR builds upon his original ADX indicator. - -**Historical Context**: ADXR was developed to address a key limitation of ADX - the need for trend acceleration context. By comparing current and historical trend strength, ADXR adds a new dimension to trend analysis. - -**Fun Fact**: Wilder was particularly proud of this refinement, noting that ADXR often signaled trend changes several days before they became apparent in price action. - -## Core Concept -Think of ADXR as a trend momentum gauge. It compares today's trend strength to trend strength from a previous period (typically 14 days ago) to determine if trending momentum is building or fading. Like watching a car's acceleration rather than just its speed, ADXR helps you understand the changing dynamics of trend strength. - -*Pro Tip* 🎯: Look for ADXR divergence from price - when price makes new highs but ADXR makes lower highs, the trend might be losing steam despite appearances. - -## Key Features -- **Trend Acceleration**: Measures whether trend strength is increasing or decreasing -- **Early Warning System**: Often signals potential trend changes before price confirmation -- **Momentum Context**: Adds historical perspective to current trend strength - -## Real-World Application -### When to Use -- **Trend Quality Assessment**: Perfect for gauging whether a trend is gaining or losing momentum -- **Entry Timing**: Use strengthening ADXR readings to confirm trend trade entries -- **Exit Signals**: Weakening ADXR can signal time to tighten stops or take profits - -### Common Pitfalls -1. **Whipsaw Risk**: Like a car's tachometer, readings can fluctuate rapidly in choppy markets -2. **False Signals**: Not every ADXR decline leads to a trend reversal -3. **Time Frame Tension**: Different time frames can show conflicting ADXR signals - -## Complementary Indicators -- **ADX**: The foundation indicator - use ADXR to add acceleration context -- **Price Action**: Confirm ADXR signals with support/resistance breaks -- **Volume**: High volume with rising ADXR suggests strong trend momentum - -## Further Reading -- "New Concepts in Technical Trading Systems" by J. Welles Wilder -- "Technical Analysis of the Financial Markets" by John J. Murphy -- "Trading with the Average Directional Index" in Technical Analysis of Stocks & Commodities magazine - -*Remember*: ADXR is like having trend strength in stereo - comparing past and present to compose a fuller picture of market momentum. Use it to fine-tune your trend trading entries and exits, but always confirm with price action. \ No newline at end of file diff --git a/docs/indicators/momentum/apo/description.md b/docs/indicators/momentum/apo/description.md deleted file mode 100644 index 0d34822f..00000000 --- a/docs/indicators/momentum/apo/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# APO - Absolute Price Oscillator - -The Absolute Price Oscillator (APO) cuts through market noise with elegant simplicity - it's the purest expression of the difference between two moving averages. While its cousin the MACD gets more attention at the trading party, APO shows up without the fancy signal line and histogram, delivering raw momentum readings in actual price terms. Think of it as your market's speedometer that shows the exact speed difference between fast and slow price movements. - -## Origin and Sources -**Creator**: While the exact origin is debated, APO emerged from the moving average crossover systems popular in the 1970s and 1980s. - -**Historical Context**: Developed as traders sought a simpler alternative to percentage-based oscillators, APO provides momentum readings in actual price units, making it especially valuable for position sizing. - -**Fun Fact**: APO's value in absolute price terms means it naturally adjusts to different price ranges - a feature particularly appreciated by institutional traders managing large positions. - -## Core Concept -Think of APO as measuring the gap between two moving averages in plain price terms. Like measuring the distance between two cars traveling at different speeds, APO tells you exactly how far apart the fast and slow moving averages are. When this gap widens, momentum is increasing; when it narrows, momentum is weakening. - -*Pro Tip* 🎯: Use APO values to help size your positions - larger APO readings often indicate stronger trends and might justify larger position sizes. - -## Key Features -- **Absolute Values**: Shows momentum in actual price units rather than percentages -- **Trend Direction**: Positive/negative readings clearly show trend direction -- **Position Sizing Tool**: Price-based readings help inform position sizing decisions - -## Real-World Application -### When to Use -- **Trend Identification**: Zero-line crosses signal potential trend changes -- **Momentum Assessment**: Growing APO values suggest strengthening trends -- **Position Sizing**: Use APO magnitude to adjust position sizes proportionally - -### Common Pitfalls -1. **Price Level Dependency**: Same APO value means different things at different price levels -2. **Timing Lag**: As a moving average-based indicator, APO lags price action -3. **False Signals**: Small crosses around zero don't always indicate meaningful trend changes - -## Complementary Indicators -- **Volume**: Confirms whether APO moves have strong backing -- **Price Action**: Use support/resistance to confirm APO signals -- **Volatility Indicators**: Help contextualize APO readings in different market conditions - -## Further Reading -- "Technical Analysis Explained" by Martin Pring -- "Technical Analysis of the Financial Markets" by John Murphy -- "Moving Averages: 60 Years of Research" in Journal of Portfolio Management - -*Remember*: APO is like a market speedometer showing the exact speed difference in price terms. Its beauty lies in its simplicity - when the fast average pulls away from the slow, momentum is building; when they come together, momentum is waning. Use these clear signals to guide both timing and position sizing. \ No newline at end of file diff --git a/docs/indicators/momentum/dmi/description.md b/docs/indicators/momentum/dmi/description.md deleted file mode 100644 index 373184e3..00000000 --- a/docs/indicators/momentum/dmi/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# DMI - Directional Movement Index - -The Directional Movement Index (DMI) is your market's compass, but instead of pointing north, it points to the direction of maximum force. While most indicators blur the line between up and down movement, DMI keeps them crystal clear by separately measuring bullish and bearish pressure. Think of it as having two force meters - one for buyers (+DI) and one for sellers (-DI), letting you see exactly who's winning the market tug-of-war. - -## Origin and Sources -**Creator**: J. Welles Wilder Jr. introduced DMI as part of his Directional Movement System, alongside ADX. - -**Historical Context**: Developed in the 1970s commodity markets, DMI was designed to solve a specific problem: determining not just trend strength, but which side (buyers or sellers) was controlling the market. - -**Fun Fact**: Wilder considered DMI the foundation of his entire trading system - ADX was actually created as a supplement to DMI, not the other way around! - -## Core Concept -Think of DMI as two competing teams in a tug-of-war. The +DI line represents the buying team's strength, while the -DI line shows the selling team's power. When +DI is higher than -DI, the buyers are winning; when -DI is higher, the sellers have the upper hand. The greater the gap between the lines, the more dominant one side is over the other. - -*Pro Tip* 🎯: Don't just trade crossovers - the best signals often come when one DI line is substantially stronger than the other and ADX confirms the trend strength. - -## Key Features -- **Directional Clarity**: Separate measurement of bullish and bearish pressure -- **Crossover Signals**: +DI and -DI crossovers suggest potential trend changes -- **Trend Confirmation**: Works with ADX to confirm trend direction and strength - -## Real-World Application -### When to Use -- **Trend Direction**: Use DI line positions to confirm trend direction -- **Entry Points**: DI crossovers with strong ADX suggest potential entries -- **Strength Assessment**: Compare DI line separation to gauge trend dominance - -### Common Pitfalls -1. **False Crossovers**: Not every DI crossover leads to a significant move -2. **Whipsaw Markets**: DMI can give conflicting signals in choppy conditions -3. **Timing Issues**: Like all trend indicators, DMI lags price action - -## Complementary Indicators -- **ADX**: The perfect partner - DMI shows direction, ADX shows strength -- **Price Action**: Use support/resistance to confirm DMI signals -- **Volume**: Higher volume on DI crosses suggests more reliable signals - -## Further Reading -- "New Concepts in Technical Trading Systems" by J. Welles Wilder -- "Trading with Directional Movement" by Martin Pring -- "The Definitive Guide to Directional Movement" in Technical Analysis of Stocks & Commodities - -*Remember*: DMI is like having a referee in the eternal bull-bear battle, calling out which team is stronger at any given moment. Use it to identify who's in control of the market, but always wait for confirmation before taking action. \ No newline at end of file diff --git a/docs/indicators/momentum/dmx/description.md b/docs/indicators/momentum/dmx/description.md deleted file mode 100644 index c86fe6ae..00000000 --- a/docs/indicators/momentum/dmx/description.md +++ /dev/null @@ -1,20 +0,0 @@ -# DMX - Directional Movement Index (Jurik) - -The DMX is one of Mark Jurik's enhanced technical indicators, building upon Wilder's directional concepts through his innovative JMA (Jurik Moving Average) technology. Think of it as a high-definition version of traditional directional indicators - it applies Jurik's sophisticated filtering techniques to reveal clearer trend signals with less noise. Like upgrading from standard to high-definition TV, DMX offers a sharper, clearer picture of market direction. - -## Origin and Sources -**Creator**: Mark Jurik developed DMX as part of his suite of enhanced technical indicators using JMA technology. - -**Historical Context**: Created to address the limitations of traditional directional indicators in modern electronic markets, DMX represents a significant advancement in directional movement analysis through adaptive filtering techniques. - -**Fun Fact**: The JMA technology behind DMX was developed after years of research into digital signal processing and its applications to financial markets. - -## Core Concept -Think of DMX as a traditional directional indicator upgraded with advanced noise filtering technology. Using Jurik's adaptive smoothing techniques, it provides cleaner directional signals while maintaining responsiveness to genuine market moves. The result is an indicator that catches major trends but ignores much of the minor price noise that triggers false signals in traditional indicators. - -[Rest of documentation remains similar but properly contextualized within Jurik's work] - -## Further Reading -- "JMA Technical Documentation" by Mark Jurik -- Jurik Research Technical Papers -- "Digital Signal Processing in Technical Analysis" featuring Jurik's work \ No newline at end of file diff --git a/docs/indicators/momentum/dpo/description.md b/docs/indicators/momentum/dpo/description.md deleted file mode 100644 index cdb3853f..00000000 --- a/docs/indicators/momentum/dpo/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# DPO - Detrended Price Oscillator - -The Detrended Price Oscillator (DPO) is like your market time machine - it strips away the long-term trend to reveal hidden price cycles. Unlike most oscillators that focus on momentum or trend, DPO has one mission: show you where we are in the current price cycle by eliminating the larger trend's influence. Think of it as removing the tide to see the waves more clearly. - -## Origin and Sources -**Creator**: Initially developed by technicians seeking to isolate price cycles for forecasting. - -**Historical Context**: Emerged from early market studies of price cycles and the need to separate shorter-term trading opportunities from longer-term trends. - -**Fun Fact**: DPO's cycle-finding ability makes it particularly popular among traders who follow W.D. Gann's theories about market timing and cycles. - -## Core Concept -Think of DPO as your trend eraser - it removes the overall price direction to highlight shorter-term cycles. It does this by comparing current price to a displaced moving average, effectively showing you where price is relative to its historical trend. The result? You can spot trading cycles that might be invisible when looking at price alone. - -*Pro Tip* 🎯: The traditional 20-day DPO setting aims to identify monthly cycles, but adjust this period to match the trading cycles you're hunting. - -## Key Features -- **Cycle Identification**: Reveals trading cycles hidden by larger trends -- **Trend Elimination**: Removes directional bias for clearer cycle analysis -- **Zero Line**: Helps identify overbought/oversold conditions relative to the cycle - -## Real-World Application -### When to Use -- **Cycle Trading**: Identify potential turning points in regular market cycles -- **Mean Reversion**: Spot prices stretched too far from their cyclic average -- **Market Timing**: Use cycle positioning to optimize entry/exit points - -### Common Pitfalls -1. **Trend Ignorance**: Remember, DPO intentionally ignores the main trend -2. **Period Selection**: Wrong lookback period means measuring the wrong cycle -3. **False Cycles**: Not all markets have regular, tradeable cycles - -## Complementary Indicators -- **Moving Averages**: Show the trend DPO is removing -- **RSI/Stochastics**: Confirm cycle extremes with momentum -- **Volume**: Validate cycle turns with volume confirmation - -## Further Reading -- "Cycles: The Mysterious Forces That Trigger Events" by Edward R. Dewey -- "Technical Analysis of Stock Trends" by Robert D. Edwards and John Magee -- "The Profit Magic of Stock Transaction Timing" by J.M. Hurst - -*Remember*: DPO is like a market metal detector that ignores the sand (trend) to find the hidden treasures (cycles) beneath. Use it to spot recurring patterns in price movement, but always remember that not every beep signals buried treasure - sometimes it's just noise. \ No newline at end of file diff --git a/docs/indicators/momentum/mom/description.md b/docs/indicators/momentum/mom/description.md deleted file mode 100644 index 5b250363..00000000 --- a/docs/indicators/momentum/mom/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# MOM - Momentum Indicator - -The Momentum indicator (MOM) is price comparison in its purest form - it simply shows you how much price has changed over a set period. Like measuring the distance between two snapshots in time, MOM tells you whether prices are moving faster or slower, higher or lower than before. It's technical analysis at its most fundamental: measuring the speed of price change. - -## Origin and Sources -**Creator**: One of the earliest technical indicators, momentum calculations have been used since the early days of technical analysis. - -**Historical Context**: Emerged from early market observations that price movements tend to continue in the same direction until momentum begins to fade. - -**Fun Fact**: While seemingly simple, momentum was one of the first indicators to quantify what legendary traders like Jesse Livermore observed intuitively about price movement. - -## Core Concept -Think of MOM as your market speedometer - it measures how fast price is moving by comparing current price to a previous price. A positive reading means price is higher than X periods ago; negative means lower. The bigger the number, the faster the move. Simple, yet powerful. - -*Pro Tip* 🎯: Watch for momentum divergence from price - when price makes new highs but momentum makes lower highs, the trend might be running out of steam. - -## Key Features -- **Raw Price Change**: Shows absolute price difference over time -- **Zero Line**: Clear trend direction indicator -- **Divergence Signals**: Early warning system for potential trend changes - -## Real-World Application -### When to Use -- **Trend Strength**: Gauge how powerfully price is moving -- **Reversal Spotting**: Look for momentum divergence from price -- **Entry Timing**: Use momentum confirmation for trend trades - -### Common Pitfalls -1. **False Signals**: Not every momentum dip means trend reversal -2. **Time Period Choice**: Different lookback periods can give conflicting signals -3. **Price Scale Dependency**: Same momentum values mean different things at different price levels - -## Complementary Indicators -- **Moving Averages**: Confirm trend direction -- **Volume**: Validate momentum signals -- **RSI**: Add oversold/overbought context to momentum readings - -## Further Reading -- "Technical Analysis of Stock Trends" by Edwards and Magee -- "Technical Analysis of the Financial Markets" by John Murphy -- "Momentum, Direction, and Divergence" by William Blau - -*Remember*: MOM is like a market thermometer - it tells you the temperature of price movement right now compared to before. Simple but essential, it's often the foundation for more complex momentum-based trading strategies. diff --git a/docs/indicators/momentum/pmo/description.md b/docs/indicators/momentum/pmo/description.md deleted file mode 100644 index 7560ac56..00000000 --- a/docs/indicators/momentum/pmo/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# PMO - Price Momentum Oscillator - -The Price Momentum Oscillator (PMO) is like a momentum indicator with built-in smoothing superpowers. Created by Carl Swenlin, it's essentially a super-refined version of ROC (Rate of Change) that uses double exponential smoothing to produce exceptionally clean momentum signals. Think of it as momentum viewed through a premium lens - sharper, clearer, and more focused. - -## Origin and Sources -**Creator**: Carl Swenlin developed PMO to address the noise issues in traditional momentum indicators. - -**Historical Context**: Emerged from Swenlin's work on improving momentum measurements through careful optimization of exponential smoothing techniques. - -**Fun Fact**: The PMO's formula was specifically designed to maintain sensitivity while eliminating the spiky, erratic movements that plague simpler momentum indicators. - -## Core Concept -Think of PMO as a momentum indicator that's been sent to finishing school. It starts with simple ROC calculations but then applies two stages of exponential smoothing to refine the signal. The result is like having a momentum indicator with built-in noise cancellation - smooth enough to be readable, but responsive enough to catch important moves. - -*Pro Tip* 🎯: Watch the PMO signal line crossovers, but pay special attention when they occur near historical extreme levels - these often provide the highest probability signals. - -## Key Features -- **Double Smoothing**: Two-stage exponential smoothing for cleaner signals -- **Signal Line**: Additional validation through signal line crossovers -- **Bounded Range**: Unlike raw momentum, PMO tends to stay within historical ranges - -## Real-World Application -### When to Use -- **Trend Confirmation**: Validate trend strength with smooth momentum readings -- **Divergence Analysis**: Look for clear divergences with price -- **Overbought/Oversold**: Use historical extremes for mean reversion trades - -### Common Pitfalls -1. **Smoothing Lag**: The price of smooth signals is some delay -2. **Range Shifts**: Long-term ranges can shift in strong trends -3. **Time Frame Conflicts**: Different time frames can show conflicting PMO signals - -## Complementary Indicators -- **Moving Averages**: Frame the bigger trend context -- **Volume**: Validate PMO signals with volume confirmation -- **MACD**: Compare PMO's smooth signals with MACD for confirmation - -## Further Reading -- "Technical Analysis: The Complete Resource for Financial Market Technicians" featuring Swenlin's work -- DecisionPoint's PMO documentation by Carl Swenlin -- "Momentum Analysis and Stock Market Strategies" in Technical Analysis of Stocks & Commodities - -*Remember*: PMO is like having a premium noise-canceling headset for momentum signals - it costs you a bit in terms of lag, but rewards you with crystal-clear readings of market momentum. Perfect for traders who value signal clarity over speed. \ No newline at end of file diff --git a/docs/indicators/momentum/po/description.md b/docs/indicators/momentum/po/description.md deleted file mode 100644 index d27371eb..00000000 --- a/docs/indicators/momentum/po/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# PO - Price Oscillator - -The Price Oscillator (PO) strips price comparison down to its essence - it's simply the difference between two moving averages expressed in absolute terms. While its percentage-based cousin PPO gets more attention, PO speaks in the language traders understand best: pure price. Think of it as MACD without the complications, showing you the raw gap between fast and slow market movements. - -## Origin and Sources -**Creator**: Evolved from early moving average crossover systems in technical analysis. - -**Historical Context**: Developed as traders sought a simpler way to measure the spread between moving averages without percentage conversions. - -**Fun Fact**: While less famous than MACD or PPO, PO is often preferred by futures traders and large position managers because its absolute price measurements help with position sizing. - -## Core Concept -Think of PO as measuring the distance between two cars traveling at different speeds. The faster moving average is one car, the slower moving average is another, and PO tells you exactly how far apart they are in price terms. When they're getting further apart, momentum is building; when they're getting closer, momentum is waning. - -*Pro Tip* 🎯: Since PO uses absolute price differences, its signals need to be scaled relative to the price level - a 5-point spread means something very different on a $20 stock versus a $200 stock. - -## Key Features -- **Absolute Measurement**: Shows moving average spread in actual price terms -- **Zero Line**: Clear trend direction indicator -- **Momentum Gauge**: Spread width indicates trend strength - -## Real-World Application -### When to Use -- **Trend Direction**: Zero-line crossovers signal trend changes -- **Momentum Assessment**: Widening spread suggests strengthening trend -- **Position Sizing**: Use spread width to help scale position sizes - -### Common Pitfalls -1. **Price Level Dependency**: Must adjust interpretation for price level -2. **Moving Average Lag**: Inherent lag from using two moving averages -3. **Scaling Issues**: Different markets need different interpretation scales - -## Complementary Indicators -- **Volume**: Validate PO signals with volume confirmation -- **Price Action**: Use support/resistance to confirm PO signals -- **Volatility Indicators**: Help contextualize PO spreads - -## Further Reading -- "Technical Analysis of the Financial Markets" by John Murphy -- "Technical Analysis Using Multiple Timeframes" by Brian Shannon -- "Moving Average Studies in Technical Analysis" in Technical Analysis Journal - -*Remember*: PO is like a market ruler measuring the gap between fast and slow moving averages in actual price terms. Its beauty lies in its simplicity - when the fast average pulls away from the slow, momentum is building; when they come together, momentum is waning. Just remember to adjust your ruler's scale to match your market's price level. \ No newline at end of file diff --git a/docs/indicators/momentum/ppo/description.md b/docs/indicators/momentum/ppo/description.md deleted file mode 100644 index ee1bbfef..00000000 --- a/docs/indicators/momentum/ppo/description.md +++ /dev/null @@ -1,48 +0,0 @@ -# PPO - Percentage Price Oscillator - -The Percentage Price Oscillator (PPO) is MACD's more versatile cousin - it shows the percentage difference between two moving averages rather than the absolute difference. Think of it as a universal translator for price momentum - because it speaks in percentages, it lets you compare momentum across different price levels, time periods, and even different instruments. Perfect for traders who need to compare apples to oranges. - -## Origin and Sources -**Creator**: Evolved from the MACD concept, adapted to address the need for comparable momentum readings across different securities. - -**Historical Context**: Developed as traders and analysts needed a way to compare momentum across various stocks and markets with widely different price levels. - -**Fun Fact**: While often overshadowed by MACD, PPO is actually more versatile for cross-market analysis and is preferred by many institutional traders for multi-asset strategies. - -## Core Concept -Think of PPO as measuring the gap between two moving averages in percentage terms. Instead of saying "these averages are 10 points apart," PPO says "these averages are 5% apart." This simple shift to percentages makes it possible to compare momentum across any markets - whether you're looking at a $5 stock or a $500 stock, a 5% gap means the same thing. - -*Pro Tip* 🎯: PPO values tend to be more consistent across time than MACD, making historical comparison more reliable even after significant price changes. - -## Key Features -- **Percentage-Based**: Comparable across different price levels -- **Cross-Market Analysis**: Can compare momentum across different securities -- **Standard Signals**: Zero-line crossovers, signal line crossovers, and divergences -- **Histogram View**: Visual representation of momentum strength - -## Real-World Application -### When to Use -- **Multi-Market Analysis**: Compare momentum across different securities -- **Portfolio Scanning**: Screen for strongest momentum across your universe -- **Historical Analysis**: Compare current momentum to historical periods -- **Trend Changes**: Spot momentum shifts through signal line crossovers - -### Common Pitfalls -1. **False Signals**: Not every crossover is tradeable -2. **Time Frame Conflicts**: Different periods can show conflicting signals -3. **Context Matters**: Market conditions affect reliability of signals -4. **Divergence Traps**: Not all divergences lead to reversals - -## Complementary Indicators -- **Volume**: Confirm PPO signals with volume -- **Relative Strength**: Compare PPO readings across sector/market -- **Volatility Indicators**: Help qualify PPO signals in different volatility regimes -- **Price Action**: Use support/resistance to confirm PPO signals - -## Further Reading -- "Technical Analysis of the Financial Markets" by John Murphy -- "Technical Analysis Using Multiple Timeframes" by Brian Shannon -- "Momentum, Direction, and Divergence" by William Blau -- "The Visual Investor" by John Murphy - -*Remember*: PPO is like having a universal translator for momentum - it converts price movements into percentages so you can compare momentum anywhere. Perfect for traders who need to track momentum across multiple markets or time periods. Just remember that like any translation, some nuance might be lost in conversion. \ No newline at end of file diff --git a/docs/indicators/momentum/prs/description.md b/docs/indicators/momentum/prs/description.md deleted file mode 100644 index 5342a9ec..00000000 --- a/docs/indicators/momentum/prs/description.md +++ /dev/null @@ -1,48 +0,0 @@ -# PRS - Price Relative Strength - -Price Relative Strength (PRS) is your market's performance comparator - it shows how one security is performing versus another by dividing their prices. Think of it as a financial tug-of-war scorer, keeping track of which security is winning the performance battle. Not to be confused with RSI (Relative Strength Index), PRS focuses on comparative performance rather than internal momentum. - -## Origin and Sources -**Creator**: Evolved from early technical analysis practices of comparing different securities' performance. - -**Historical Context**: Gained prominence in the 1950s and 1960s as sector rotation and relative performance analysis became key components of portfolio management. - -**Fun Fact**: While simple in calculation, PRS became a cornerstone of modern sector rotation strategies and is a fundamental tool in the famous IBD (Investor's Business Daily) stock selection methodology. - -## Core Concept -Think of PRS as a performance ratio calculator - it simply divides one security's price by another's (often an index or sector benchmark) to create a ratio. When the ratio rises, your security is outperforming; when it falls, it's underperforming. It's like having a continuous performance scoreboard. - -*Pro Tip* 🎯: The slope of the PRS line is often more important than its absolute level - accelerating relative strength often precedes significant outperformance. - -## Key Features -- **Direct Comparison**: Clear view of relative performance -- **Trend Identification**: Shows leadership/laggard relationships -- **Rotation Detection**: Helps identify sector/stock rotation patterns -- **Strength Confirmation**: Validates breakouts through relative strength - -## Real-World Application -### When to Use -- **Stock Selection**: Find strongest stocks within a sector -- **Sector Analysis**: Identify leading/lagging sectors -- **Portfolio Management**: Guide rotation decisions -- **Risk Assessment**: Monitor relative weakness for position sizing - -### Common Pitfalls -1. **Base Selection**: Wrong comparison base can lead to misleading signals -2. **Time Frame Mismatch**: Different time frames can show conflicting relationships -3. **Correlation Assumptions**: High correlation periods can suddenly break down -4. **Volume Ignorance**: Price relationships without volume can mislead - -## Complementary Indicators -- **Volume**: Validate relative strength moves -- **Moving Averages**: Smooth PRS for clearer trends -- **Momentum Indicators**: Confirm relative strength trends -- **Volatility Measures**: Context for relative performance - -## Further Reading -- "Technical Analysis of Stock Market Trends" by Edwards and Magee -- "How to Make Money in Stocks" by William O'Neil -- "Intermarket Analysis" by John Murphy -- "The Art of Relative Strength Investing" in Technical Analysis Journal - -*Remember*: PRS is like a continuous performance scorekeeper for your markets - it tells you who's winning the performance game at any given time. Perfect for finding market leaders and avoiding laggards, but remember that today's winner isn't guaranteed tomorrow's championship. \ No newline at end of file diff --git a/docs/indicators/momentum/roc/description.md b/docs/indicators/momentum/roc/description.md deleted file mode 100644 index a72c7608..00000000 --- a/docs/indicators/momentum/roc/description.md +++ /dev/null @@ -1,48 +0,0 @@ -# ROC - Rate of Change - -The Rate of Change (ROC) is momentum distilled to its purest form - it simply shows you the percentage change in price over a set period. Think of it as your market's speedometer, measuring how fast price is moving in percentage terms. Unlike complex oscillators, ROC gives you raw, unfiltered price velocity that's immediately comparable across any market. - -## Origin and Sources -**Creator**: One of the oldest technical indicators, ROC emerged from early market observations about momentum. - -**Historical Context**: Developed in the early days of technical analysis when traders needed a simple way to quantify price changes over time. - -**Fun Fact**: While newer momentum indicators have added layers of sophistication, ROC remains popular in quantitative trading systems due to its simplicity and lack of lag. - -## Core Concept -Think of ROC as your market's speedometer calibrated in percentage terms. It answers one simple question: "How much has price changed over X periods?" A 10% ROC means price is 10% higher than X periods ago; -10% means it's 10% lower. This simplicity makes it instantly comparable across any market or time period. - -*Pro Tip* 🎯: Watch for ROC divergence from price when both are making extremes - if price makes a new high but ROC doesn't, momentum might be waning. - -## Key Features -- **Pure Momentum**: Unsmoothed, direct measurement of price change -- **Zero Line**: Clear trend direction indicator -- **Cross-Market Comparison**: Percentage basis allows direct comparison -- **Leading Indicator**: Often shows momentum shifts before price - -## Real-World Application -### When to Use -- **Trend Strength**: Gauge momentum behind price moves -- **Divergence Trading**: Spot momentum/price disagreements -- **Market Comparison**: Compare strength across different securities -- **Trend Confirmation**: Validate price breakouts - -### Common Pitfalls -1. **Noise Sensitivity**: Unsmoothed calculation means more whipsaws -2. **Period Selection**: Different lookback periods can give conflicting signals -3. **Base Effect**: Large past moves can distort current readings -4. **False Divergences**: Not all divergences lead to reversals - -## Complementary Indicators -- **Moving Averages**: Smooth ROC for clearer signals -- **Volume**: Confirm momentum with volume -- **Price Action**: Use support/resistance with ROC -- **Volatility Indicators**: Context for ROC readings - -## Further Reading -- "Technical Analysis of Stock Trends" by Edwards and Magee -- "Technical Analysis of the Financial Markets" by John Murphy -- "Momentum, Direction, and Divergence" by William Blau -- "The New Science of Technical Analysis" by Thomas DeMark - -*Remember*: ROC is like a high-performance car's speedometer - it gives you raw, unfiltered readings of market velocity. Its beauty lies in its simplicity and universality. Perfect for those who prefer their momentum straight up, no smoothing added. Just remember that sometimes a smooth ride might be preferable to a bumpy one. \ No newline at end of file diff --git a/docs/indicators/momentum/trix/description.md b/docs/indicators/momentum/trix/description.md deleted file mode 100644 index ad15dcdd..00000000 --- a/docs/indicators/momentum/trix/description.md +++ /dev/null @@ -1,48 +0,0 @@ -# TRIX - Triple Exponential Average - -TRIX is the momentum indicator that went to graduate school - it applies triple exponential smoothing to remove price noise while keeping the essence of the trend. Think of it as ROC with three layers of sophisticated filtering, designed to show you significant trends while ignoring minor price fluctuations. Its name comes from the "triple" smoothing process, not from any similarity to the breakfast cereal! - -## Origin and Sources -**Creator**: Jack Hutson introduced TRIX in the 1980s through articles in Technical Analysis of Stocks & Commodities magazine. - -**Historical Context**: Developed to address the need for a momentum indicator that could ignore minor price movements while remaining sensitive to significant trends. - -**Fun Fact**: Despite its complex calculation, TRIX was one of the first indicators specifically designed to be calculated by early personal computers, making it a pioneer in the computational technical analysis era. - -## Core Concept -Think of TRIX as a trend distillery - it takes price data and runs it through three rounds of exponential smoothing, then calculates the rate of change of the result. Like filtering water through multiple stages, each smoothing removes more noise, leaving you with purer trend signals. The final ROC calculation shows you how fast this purified trend is changing. - -*Pro Tip* 🎯: Use the zero line as your trend filter - when TRIX is above zero, the filtered trend is up; below zero, it's down. But the most powerful signals often come from divergences with price. - -## Key Features -- **Triple Smoothing**: Exceptional noise reduction -- **Momentum of Trend**: Shows speed of trend changes -- **Zero Line**: Clear trend direction reference -- **Signal Line**: Additional confirmation through signal line crossovers - -## Real-World Application -### When to Use -- **Trend Confirmation**: Validate longer-term trend changes -- **Divergence Trading**: Spot high-probability reversal setups -- **Filter**: Screen out minor market movements -- **Entry/Exit Timing**: Use zero-line or signal line crossovers - -### Common Pitfalls -1. **Lag**: Triple smoothing means significant delay -2. **Whipsaws**: Even with smoothing, ranging markets can produce false signals -3. **Period Sensitivity**: Different lookback periods can show conflicting signals -4. **Over-filtering**: Can miss important shorter-term moves - -## Complementary Indicators -- **Price Action**: Use support/resistance with TRIX signals -- **Volume**: Confirm trend changes with volume -- **Faster Indicators**: Balance TRIX's lag with quicker signals -- **Volatility Indicators**: Context for signal reliability - -## Further Reading -- "Technical Analysis of Stocks & Commodities" - Original TRIX articles by Jack Hutson -- "Technical Analysis: The Complete Resource for Financial Market Technicians" -- "Trend Following: How to Make a Fortune in Bull, Bear, and Black Swan Markets" -- "The Encyclopedia of Technical Market Indicators" - -*Remember*: TRIX is like having a sophisticated trend-spotting algorithm from the 1980s - it might be slower than modern alternatives, but its triple-filtered signals can help you avoid false moves that trap traders using simpler tools. Perfect for position traders who want to focus on significant trends while ignoring market noise. Just remember that all that filtering comes at the cost of timeliness. \ No newline at end of file diff --git a/docs/indicators/momentum/tsi/description.md b/docs/indicators/momentum/tsi/description.md deleted file mode 100644 index f52ac78e..00000000 --- a/docs/indicators/momentum/tsi/description.md +++ /dev/null @@ -1,48 +0,0 @@ -# TSI - True Strength Index - -The True Strength Index (TSI) is like a precision scale for price momentum - it shows not just the direction and magnitude of price movement, but its underlying strength through double-smoothing both price change and its absolute value. Think of it as momentum with built-in signal clarity, designed to separate true price strength from market noise. - -## Origin and Sources -**Creator**: William Blau developed TSI and introduced it in 1991 in Technical Analysis of Stocks & Commodities magazine. - -**Historical Context**: Created to address the need for a momentum indicator that could clearly show both trend direction and underlying strength while minimizing false signals. - -**Fun Fact**: Blau, a physicist by training, applied concepts from signal processing theory to create TSI, making it one of the first indicators to use sophisticated signal smoothing techniques. - -## Core Concept -Think of TSI as measuring price momentum through a noise-canceling system. It tracks two things: price changes and the absolute values of those changes. By double-smoothing both and creating a ratio between them, TSI reveals the true strength behind price movements. Like having both a speedometer and an engine performance gauge, it tells you not just how fast price is moving, but how much power is behind the move. - -*Pro Tip* 🎯: Watch for TSI crossing its signal line while near extreme levels - these often provide the highest probability trading signals. - -## Key Features -- **Double Smoothing**: Exceptional noise reduction in momentum readings -- **Bounded Oscillator**: Values typically range between +100 and -100 -- **Signal Line**: Additional confirmation through crossovers -- **Center Line**: Clear trend direction reference at zero - -## Real-World Application -### When to Use -- **Trend Direction**: Zero-line helps confirm trend -- **Momentum Confirmation**: Validate price moves -- **Divergence Trading**: Spot potential reversals -- **Entry/Exit Timing**: Use signal line crossovers - -### Common Pitfalls -1. **Lag**: Double smoothing creates notable delay -2. **Complex Calculation**: More difficult to fine-tune than simpler indicators -3. **Multiple Parameters**: More variables to optimize -4. **Time Frame Sensitivity**: Different settings needed for different time frames - -## Complementary Indicators -- **Price Action**: Confirm TSI signals with support/resistance -- **Volume**: Validate strength readings with volume -- **Trend Indicators**: Provide context for TSI signals -- **Volatility Measures**: Help qualify signal reliability - -## Further Reading -- "Momentum, Direction, and Divergence" by William Blau -- "The New Technical Trader" by Tushar Chande -- "Technical Analysis of Stocks & Commodities" - Original TSI articles -- "Advanced Technical Analysis Concepts" - -*Remember*: TSI is like having a sophisticated strength meter for price movements - it might take longer to give you a reading than simpler tools, but its double-smoothed signals can help you avoid false moves that trap other traders. Perfect for those who want to measure not just price momentum, but the quality of that momentum. Just don't expect it to catch every quick market move - sometimes being smooth means being slow. \ No newline at end of file diff --git a/docs/indicators/momentum/vel/description.md b/docs/indicators/momentum/vel/description.md deleted file mode 100644 index e2b77ff0..00000000 --- a/docs/indicators/momentum/vel/description.md +++ /dev/null @@ -1,43 +0,0 @@ -# VEL - Velocity (Jurik) - -VEL represents Mark Jurik's enhanced take on momentum measurement, applying his sophisticated JMA (Jurik Moving Average) technology to create a more refined momentum indicator. Think of it as momentum measurement with noise-canceling headphones - it filters out market static to give you a clearer signal of genuine price velocity. - -## Origin and Sources -**Creator**: Mark Jurik developed VEL as part of his suite of advanced technical indicators. - -**Historical Context**: Created to address the limitations of traditional momentum indicators in modern, noisy markets through advanced digital signal processing techniques. - -**Fun Fact**: The adaptive filtering technology in VEL comes from principles originally developed for radar and sonar systems. - -## Core Concept -Think of VEL as momentum's graduate degree - it measures price change like traditional momentum but applies sophisticated filtering to separate real movement from market noise. Using Jurik's adaptive techniques, it provides smoother, more reliable readings of price velocity while maintaining responsiveness to genuine market moves. - -*Pro Tip* 🎯: VEL's smoother signals often provide clearer divergence patterns than traditional momentum. - -## Key Features -- **Adaptive Filtering**: Automatically adjusts to market conditions -- **Noise Reduction**: Cleaner signals than traditional momentum -- **True Velocity**: Better measurement of actual price movement speed - -## Real-World Application -### When to Use -- **Trend Confirmation**: Verify trend strength with less noise -- **Reversal Detection**: Spot high-probability turning points -- **Market State Analysis**: Gauge true market velocity regardless of conditions - -### Common Pitfalls -1. **Over-filtering**: Sometimes important short-term signals get smoothed away -2. **Complexity**: More parameters to understand and optimize -3. **Lag Consideration**: Smoother signals mean slightly later signals - -## Complementary Indicators -- **Price Action**: Primary validation of VEL signals -- **Volume**: Confirm velocity changes with volume -- **Other Jurik Indicators**: Often work well together in a unified system - -## Further Reading -- "JMA Technical Documentation" by Mark Jurik -- Jurik Research Technical Papers -- "Digital Processing Techniques in Technical Analysis" - -*Remember*: VEL is like a precision radar for price movement - it might take more time to master than basic momentum, but it rewards you with clearer signals and fewer false alarms. Use it when you need more reliable momentum readings in noisy markets. \ No newline at end of file diff --git a/docs/indicators/momentum/vortex/description.md b/docs/indicators/momentum/vortex/description.md deleted file mode 100644 index cfe20be8..00000000 --- a/docs/indicators/momentum/vortex/description.md +++ /dev/null @@ -1,48 +0,0 @@ -# Vortex - Vortex Indicator - -The Vortex Indicator is your market's compass for trending direction with a twist - it simultaneously tracks both positive and negative price movement trends. Think of it as having two trend trackers that compete to show which direction has true momentum. Named after the vortex pattern in nature, it aims to capture the swirling, cyclical nature of price trends. - -## Origin and Sources -**Creator**: Etienne Botes and Douglas Siepman introduced the Vortex Indicator in the January 2010 edition of Technical Analysis of Stocks & Commodities magazine. - -**Historical Context**: Developed by studying the relationship between highs and lows across multiple periods, inspired by the vortex pattern found in nature. - -**Fun Fact**: The creators were inspired by Viktor Schauberger's study of natural flow systems and vortices in water, applying these natural principles to market movements. - -## Core Concept -Think of Vortex as tracking two competing forces in the market - upward trending movement (VI+) and downward trending movement (VI-). Like watching two rivers merge and create a vortex, VI measures the strength of both bullish and bearish price movements over time. When VI+ crosses above VI-, an uptrend may be starting; when VI- crosses above VI+, a downtrend may be forming. - -*Pro Tip* 🎯: Look for VI crossovers that occur after a strong trend in the opposite direction - these often signal high-probability reversal points. - -## Key Features -- **Dual Lines**: VI+ and VI- track both trend directions simultaneously -- **Crossover Signals**: Clear trend change identification -- **Trend Strength**: Distance between lines shows trend power -- **Natural Design**: Based on principles found in natural systems - -## Real-World Application -### When to Use -- **Trend Identification**: Spot potential trend beginnings -- **Trend Confirmation**: Validate existing trends -- **Reversal Detection**: Identify possible trend changes -- **Trend Strength Analysis**: Gauge momentum behind moves - -### Common Pitfalls -1. **Whipsaws**: Can give false signals in choppy markets -2. **Period Sensitivity**: Different lookback periods affect signal timing -3. **Lag Factor**: Like all trend indicators, confirms after the fact -4. **False Crossovers**: Not every crossover leads to a trend - -## Complementary Indicators -- **ADX**: Confirm trend strength -- **Moving Averages**: Provide broader trend context -- **Volume**: Validate trend signals -- **Support/Resistance**: Frame entry/exit points - -## Further Reading -- "Technical Analysis of Stocks & Commodities" - Original 2010 Vortex article -- "The Technical Analysis Course" by Thomas Meyers -- "Living In the Flow: Viktor Schauberger's Water Science" -- "Technical Analysis: Modern Perspectives" by Gordon Scott - -*Remember*: Vortex is like having a weather vane that shows both wind directions at once - it helps you see which force is stronger in the market. Perfect for trend traders who want to track both bullish and bearish pressure simultaneously. Just remember that like real weather patterns, market trends can be unpredictable and change quickly. \ No newline at end of file diff --git a/docs/indicators/oscillators/ac/ac.md b/docs/indicators/oscillators/ac/ac.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/ao/ao.md b/docs/indicators/oscillators/ao/ao.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/aroon/aroon.md b/docs/indicators/oscillators/aroon/aroon.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/bop/bop.md b/docs/indicators/oscillators/bop/bop.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/cci/cci.md b/docs/indicators/oscillators/cci/cci.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/cfo/cfo.md b/docs/indicators/oscillators/cfo/cfo.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/cmo/cmo.md b/docs/indicators/oscillators/cmo/cmo.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/rsi/rsi.md b/docs/indicators/oscillators/rsi/rsi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/oscillators/rsx/rsx.md b/docs/indicators/oscillators/rsx/rsx.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/curvature/curvature.md b/docs/indicators/statistics/curvature/curvature.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/entropy/entropy.md b/docs/indicators/statistics/entropy/entropy.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/kurtosis/kurtosis.md b/docs/indicators/statistics/kurtosis/kurtosis.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/list.md b/docs/indicators/statistics/list.md deleted file mode 100644 index 77166046..00000000 --- a/docs/indicators/statistics/list.md +++ /dev/null @@ -1,52 +0,0 @@ -# Top 50 Fundamental Statistical Functions - -- Mean (Arithmetic Average) -- Median -- Mode -- Range -- Variance -- Standard Deviation -- Coefficient of Variation -- Percentiles -- Quartiles -- Interquartile Range (IQR) -- Skewness -- Kurtosis -- Covariance -- Correlation Coefficient (Pearson) -- Spearman's Rank Correlation -- Mean Absolute Error (MAE) -- Mean Squared Error (MSE) -- Root Mean Square Error (RMSE) -- Mean Absolute Percentage Error (MAPE) -- R-squared (Coefficient of Determination) -- Adjusted R-squared -- Z-score (Standard Score) -- T-score -- F-statistic -- Chi-square Statistic -- P-value -- Confidence Interval -- Standard Error -- Margin of Error -- Effect Size (Cohen's d, Hedges' g) -- Odds Ratio -- Relative Risk -- Poisson Distribution -- Normal Distribution (Gaussian) -- Binomial Distribution -- Exponential Distribution -- Weibull Distribution -- Log-normal Distribution -- Student's t-Distribution -- F-Distribution -- Beta Distribution -- Gamma Distribution -- Geometric Mean -- Harmonic Mean -- Moving Average -- Exponential Moving Average -- Weighted Average -- Cumulative Sum -- Autocorrelation Function (ACF) -- Partial Autocorrelation Function (PACF) \ No newline at end of file diff --git a/docs/indicators/statistics/max/max.md b/docs/indicators/statistics/max/max.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/median/median.md b/docs/indicators/statistics/median/median.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/min/min.md b/docs/indicators/statistics/min/min.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/mode/mode.md b/docs/indicators/statistics/mode/mode.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/percentile/percentile.md b/docs/indicators/statistics/percentile/percentile.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/skew/skew.md b/docs/indicators/statistics/skew/skew.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/slope/slope.md b/docs/indicators/statistics/slope/slope.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/stddev/stddev.md b/docs/indicators/statistics/stddev/stddev.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/variance/variance.md b/docs/indicators/statistics/variance/variance.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/statistics/zscore/zscore.md b/docs/indicators/statistics/zscore/zscore.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/atr/atr.md b/docs/indicators/volatility/atr/atr.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/hv/hv.md b/docs/indicators/volatility/hv/hv.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/jvolty/jvolty.md b/docs/indicators/volatility/jvolty/jvolty.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/rv/rv.md b/docs/indicators/volatility/rv/rv.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/rvi/calc.md b/docs/indicators/volatility/rvi/calc.md deleted file mode 100644 index eeb283a4..00000000 --- a/docs/indicators/volatility/rvi/calc.md +++ /dev/null @@ -1,50 +0,0 @@ -# The Math Behind RVI - -## Components of RVI - -The **Relative Volatility Index (RVI)** measures the direction of volatility in the market, using components like: - -- Standard deviation of price changes -- Simple moving average (SMA) to smooth volatility -- Separation of up and down price movements - -### RVI Formula - -The RVI is calculated using the following formula: - -$$ -\text{RVI}_t = 100 \times \frac{\text{SMA}(\sigma_{\text{up}}, N)}{\text{SMA}(\sigma_{\text{up}}, N) + \text{SMA}(\sigma_{\text{down}}, N)} -$$ - -Where: -- \( \text{RVI}_t \) is the RVI value at time \( t \) -- \( \sigma_{\text{up}} \) is the standard deviation of up moves over the lookback period \( N \) -- \( \sigma_{\text{down}} \) is the standard deviation of down moves over the lookback period \( N \) -- \( \text{SMA} \) represents the simple moving average applied over \( N \) periods - -### Up and Down Move Calculation - -The standard deviations \( \sigma_{\text{up}} \) and \( \sigma_{\text{down}} \) are calculated based on the price changes: - -$$ -\Delta \text{Price} = \text{Close}_t - \text{Close}_{t-1} -$$ - -- If \( \Delta \text{Price} > 0 \), it contributes to \( \sigma_{\text{up}} \) -- If \( \Delta \text{Price} < 0 \), it contributes to \( \sigma_{\text{down}} \) - -### Parameter Definitions - -RVI uses the following main parameters: - -- **Lookback period** (\( N \)): The number of periods used to calculate the standard deviations and SMAs. A typical value is 14. -- **Smoothing with SMA**: The standard deviations of up and down moves are smoothed using a simple moving average (SMA), making the RVI less sensitive to short-term fluctuations. - -### Computational Process - -For each new data point: -- Calculate the price change (\( \Delta \text{Price} \)) from the previous period. -- Separate the price changes into up moves and down moves. -- Compute the standard deviations (\( \sigma_{\text{up}} \) and \( \sigma_{\text{down}} \)) over the last \( N \) periods. -- Apply the simple moving average (SMA) to both up and down standard deviations. -- Use the RVI formula to produce the final RVI value. diff --git a/docs/indicators/volatility/rvi/rvi.md b/docs/indicators/volatility/rvi/rvi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/tr/tr.md b/docs/indicators/volatility/tr/tr.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/ui/ui.md b/docs/indicators/volatility/ui/ui.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/vc/vc.md b/docs/indicators/volatility/vc/vc.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/vov/vov.md b/docs/indicators/volatility/vov/vov.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/vr/vr.md b/docs/indicators/volatility/vr/vr.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volatility/vs/vs.md b/docs/indicators/volatility/vs/vs.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/adl/adl.md b/docs/indicators/volume/adl/adl.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/adosc/adosc.md b/docs/indicators/volume/adosc/adosc.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/aobv/aobv.md b/docs/indicators/volume/aobv/aobv.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/cmf/cmf.md b/docs/indicators/volume/cmf/cmf.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/eom/eom.md b/docs/indicators/volume/eom/eom.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/kvo/kvo.md b/docs/indicators/volume/kvo/kvo.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/mfi/mfi.md b/docs/indicators/volume/mfi/mfi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/nvi/nvi.md b/docs/indicators/volume/nvi/nvi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/obv/obv.md b/docs/indicators/volume/obv/obv.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/pvi/pvi.md b/docs/indicators/volume/pvi/pvi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/pvo/pvo.md b/docs/indicators/volume/pvo/pvo.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/pvol/pvol.md b/docs/indicators/volume/pvol/pvol.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/pvr/pvr.md b/docs/indicators/volume/pvr/pvr.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/pvt/pvt.md b/docs/indicators/volume/pvt/pvt.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/indicators/volume/tvi/tvi.md b/docs/indicators/volume/tvi/tvi.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index f3ee745e..00000000 --- a/docs/readme.md +++ /dev/null @@ -1,47 +0,0 @@ -[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=mihakralj_QuanTAlib&metric=ncloc)](https://sonarcloud.io/summary/overall?id=mihakralj_QuanTAlib) -[![Codacy grade](https://img.shields.io/codacy/grade/b1f9109222234c87bce45f1fd4c63aee?style=flat-square)](https://app.codacy.com/gh/mihakralj/QuanTAlib/dashboard) -[![codecov](https://codecov.io/gh/mihakralj/QuanTAlib/branch/main/graph/badge.svg?style=flat-square&token=YNMJRGKMTJ?style=flat-square)](https://codecov.io/gh/mihakralj/QuanTAlib) -[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=mihakralj_QuanTAlib&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=mihakralj_QuanTAlib) -[![CodeFactor](https://www.codefactor.io/repository/github/mihakralj/quantalib/badge/main)](https://www.codefactor.io/repository/github/mihakralj/quantalib/overview/main) - -[![Nuget](https://img.shields.io/nuget/v/QuanTAlib?style=flat-square)](https://www.nuget.org/packages/QuanTAlib/) -![GitHub last commit](https://img.shields.io/github/last-commit/mihakralj/QuanTAlib) -[![Nuget](https://img.shields.io/nuget/dt/QuanTAlib?style=flat-square)](https://www.nuget.org/packages/QuanTAlib/) -[![GitHub watchers](https://img.shields.io/github/watchers/mihakralj/QuanTAlib?style=flat-square)](https://github.com/mihakralj/QuanTAlib/watchers) -[![.NET8.0](https://img.shields.io/badge/.NET-8.0-blue?style=flat-square)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) - -![Alt text](./img/quotes.gif) - -# QuanTAlib - quantitative technical indicators for Quantower - -**Quan**titative **TA** **lib**rary (QuanTAlib) is a C# library of classess and methods for quantitative technical analysis useful for analyzing quotes with [Quantower](https://www.quantower.com/) and other C#-based trading platforms. - -[**Visit documentation pages**](https://mihakralj.github.io/QuanTAlib/#/)
-[**List of indicators - implemented and planned**](indicators/indicators.md) - -**QuanTAlib** is a C# library written with some specific design criteria in mind. Here is why there is '_yet another C# TA library_': - -- QuanTAlib focuses on **[real-time data analysis](essays/realtime.md)**: As new data items arrives, indicators don't have to re-calculate the entire history and can generate a result directly from the last item -- **Allow updates/corrections** of the last quote - QuanTAlib is re-calculating the last value as many times as required before continuing to the new bar -- **Calculate early data right** - calculated data is as valid as mathematically possible from the first value onwards - no blackout or warming-up periods. All indicators return data from the first bar, alongside with a flag `isHot` - defining if calculation is already stable. - -## Installation to Quantower - -- `` is the directory where Quantower is installed - where `Start.lnk` launcher is. Copy any or all `dll` files as below: -- Copy `Averages.dll` from Releases to `\Settings\Scripts\Indicators\Averages\Averages.dll` -- Copy `Statistics.dll` from Releases to `\Settings\Scripts\Indicators\Statistics\Statistics.dll` -- Copy `Volatility.dll` from Releases to `\Settings\Scripts\Indicators\Volatility\Volatility.dll` -- Copy `SyntheticVendor.dll` from Releases to `\Settings\Scripts\Vendors\SyntheticVendor\SyntheticVendor.dll` - - - -QuanTAlib is intended for developers and users of Quantower, therefore it does not focus on privind sources of OHLCV quotes. There are some very basic data feeds available to use in the learning process: `GBM_Feed` for Random (Geometric Brownian Motion) data, and `SyntheticVendor` data generator for Quantower. - -### Validation - -QuanTAlib uses validation tests with four other TA libraries to assure accuracy and validity of results: - -- [TA-LIB](https://www.ta-lib.org/function.html) -- [Skender Stock Indicators](https://dotnet.stockindicators.dev/) -- [Tulip Indicators](https://tulipindicators.org/) - diff --git a/docs/setup/dotpeek.md b/docs/setup/dotpeek.md deleted file mode 100644 index b9ccb5d6..00000000 --- a/docs/setup/dotpeek.md +++ /dev/null @@ -1,46 +0,0 @@ -# Unearthing Quantower Secrets with dotPeek - -## Step 1: Acquire Your Digital Pickaxe (dotPeek) - -1. Visit JetBrains' dotPeek download page: https://www.jetbrains.com/decompiler/download/ -2. Click the **Download** button (it's big and blue, kinda hard to miss) -3. Once downloaded, run the installer - -## Step 2: Fire Up dotPeek - -1. Launch dotPeek (look for the DP icon ) -2. Marvel at its sleek interface from early 2000's (but who needs fancy UI, right?) - -## Step 3: Load the *TradingPlatform.BusinessLayer.dll* - -1. File > Open > Navigate to your Quantower installation folder, like `D:\Quantower\TradingPlatform\v1.140.14\bin` -2. Find and open `TradingPlatform.BusinessLayer.dll` -4. Watch as dotPeek works its magic, decompiling the assembly - -## Step 4: Uncover the Secrets - -1. Expand the assembly tree in the left pane and look for interesting namespaces and classes - - `\Scripts\Indicators\Moving Averages\` is a good starting point - -3. Double-click on classes to view their decompiled source -4. Pay attention to: - - Public and internal classes/methods - - Interfaces and abstract classes - - Attributes and custom annotations - - Hardcoded values and constants - -## Step 5: Document Your Findings - -1. Use dotPeek's "Save All" feature to export the decompiled source -2. Create a document to note interesting discoveries and stuff that Quantower documentation didn't tell you -3. Some parts of Quantower are obfuscated. Which is funny, in the era of generative AI and easy-peasy de-obfuscation ability. - -## Ethical Considerations - -Remember, with great power comes great responsibility: -- Respect Quantower's intellectual property -- Consider contributing to Quantower's documentation if you find features worth documenting - -Happy exploring! May your code be clean and your discoveries plentiful. - -![dotpeek](../img/dotpeek.png) \ No newline at end of file diff --git a/docs/setup/quantower.md b/docs/setup/quantower.md deleted file mode 100644 index d1068c9f..00000000 --- a/docs/setup/quantower.md +++ /dev/null @@ -1 +0,0 @@ -# Setup \ No newline at end of file diff --git a/docs/setup/vscode.md b/docs/setup/vscode.md deleted file mode 100644 index 85248d3e..00000000 --- a/docs/setup/vscode.md +++ /dev/null @@ -1,89 +0,0 @@ -# Development Environment Setup in VS Code - -Call me grizzled old man, but I do not like to use [full Visual Studio](https://help.quantower.com/quantower/quantower-algo/installing-visual-studio) environment for my coding work. Here is the setup for VS Code projects for Quantower, so you can build your own as well. - -### Prerequisites - -- [VS Code](https://code.visualstudio.com/) - obviously -- [.NET SDK](https://dotnet.microsoft.com/en-us/download) - you should probably have this already -- [C# Dev Kit Extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) - so VS Code can understand C# -- [C# Base language support Extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) - I *think* this is a prereq for C# Dev Kit and will install automatically -- [Polyglot Notebooks Extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) - optional, but really recommended for tinkering with C# code - -### Installation Steps - -1. Create a new `myIndicator.csproj` file in a directory of your choice - it doesn't have to be anywhere in Quantower directory structure -2. Add all standard elements to `myIndicator.csproj` -3. We need to tell dotnet compiler how to find `TradingPlatform.BusinessLayer.dll` assembly. it is hiding deep in the bowels of Quantower directory structure, including an ever-changing version directory. Luckily msbuild magick can help: - -``` XML - - - D:\Quantower - - $([System.IO.Directory]::GetDirectories("$(QuantowerRoot)\TradingPlatform", "v1*")[0]) - - - - - $(QuantowerPath)\bin\TradingPlatform.BusinessLayer.dll - - - - TradingPlatform.BusinessLayer.xml - - -``` -4. Each time dotnet compiler creates a new dll assembly, we need to copy it to the `.\Scripts\Indicatiors` directory so Quantower can use it. Let's automate this with a post-build event in our `myIndicator.csproj`: - -``` xml - - - - -``` - -Below is a sample complete `.csproj` file for a Quantower indicator - it should allow building the .dll assembly and copying it to Quantower structure with `dotnet build` command: - -``` xml - - - en-US - net8.0 - enable - enable - true - preview - false - false - true - AnyCPU - False - bin\$(Configuration)\ - False - full - true - true - true - snupkg - AnyCPU - - - - D:\Quantower - $([System.IO.Directory]::GetDirectories("$(QuantowerRoot)\TradingPlatform", "v1*")[0]) - - - - $(QuantowerPath)\bin\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - -``` \ No newline at end of file diff --git a/ilspy/TradingPlatform.BusinessLayer.cs b/ilspy/TradingPlatform.BusinessLayer.cs new file mode 100644 index 00000000..cd7bbb5d --- /dev/null +++ b/ilspy/TradingPlatform.BusinessLayer.cs @@ -0,0 +1,114089 @@ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.Metrics; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Json; +using System.Net.Mail; +using System.Net.NetworkInformation; +using System.Net.Security; +using System.Net.Sockets; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Versioning; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Windows.Input; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; +using {C306A0DD-1657-4827-8B17-3122184442EB}; +using AuthenticodeExaminer; +using CancelAllOpenOrdersRequests; +using CommandLine; +using FluentFTP; +using IdentityModel.Client; +using IdentityModel.OidcClient; +using IdentityModel.OidcClient.Browser; +using IdentityModel.OidcClient.Results; +using NGettext; +using NGettext.Loaders; +using Platform.Utils; +using ProtoBuf; +using TradingPlatform.BusinessLayer; +using TradingPlatform.BusinessLayer.Abstractions.Misc; +using TradingPlatform.BusinessLayer.Chart; +using TradingPlatform.BusinessLayer.DataBinding; +using TradingPlatform.BusinessLayer.DataBinding.Exceptions; +using TradingPlatform.BusinessLayer.DataBinding.Mvvm; +using TradingPlatform.BusinessLayer.GlobalVariables; +using TradingPlatform.BusinessLayer.History.Aggregations; +using TradingPlatform.BusinessLayer.History.Storage; +using TradingPlatform.BusinessLayer.Integration; +using TradingPlatform.BusinessLayer.Integration.Limitation; +using TradingPlatform.BusinessLayer.Licence; +using TradingPlatform.BusinessLayer.LocalOrders; +using TradingPlatform.BusinessLayer.Media.Messengers; +using TradingPlatform.BusinessLayer.Modules; +using TradingPlatform.BusinessLayer.Modules.PlaceOrderStrategies; +using TradingPlatform.BusinessLayer.Native; +using TradingPlatform.BusinessLayer.PowerTrades; +using TradingPlatform.BusinessLayer.Serialization; +using TradingPlatform.BusinessLayer.Settings.Condition; +using TradingPlatform.BusinessLayer.Settings.OTP; +using TradingPlatform.BusinessLayer.TimeSync; +using TradingPlatform.BusinessLayer.Utils; +using TradingPlatform.BusinessLayer.Utils.Comparers; +using TradingPlatform.BusinessLayer.Utils.EqualityComparers; +using TradingPlatform.BusinessLayer.Utils.Extensions; +using TradingPlatform.BusinessLayer.Utils.Limitation; +using TradingPlatform.BusinessLayer.Utils.Sounds; +using TradingPlatform.BusinessLayer.Utils.Storage; +using TradingPlatform.BusinessLayer.Utils.TaskSchedulers; +using TradingPlatform.BusinessLayer.Utils.TradingProtection; +using TradingPlatform.BusinessLayer.Utils.UserTradesLocalStorage; +using TradingPlatform.BusinessLayer.VolumeAnalysis.Storage; +using ?; + +[assembly: CompilationRelaxations(8)] +[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] +[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] +[assembly: InternalsVisibleTo("TradingPlatform.BusinessLayer.Tests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] +[assembly: AssemblyCompany("QUANTOWER")] +[assembly: AssemblyConfiguration("Release")] +[assembly: AssemblyCopyright("Copyright cQUANTOWER 2017")] +[assembly: AssemblyFileVersion("1.144.12.0")] +[assembly: AssemblyInformationalVersion("1.144.12+955059d4fca78a19dda63cf80aa2b7a03c9f0221")] +[assembly: AssemblyProduct("Quantower")] +[assembly: AssemblyTitle("TradingPlatform.BusinessLayer")] +[assembly: AssemblyVersion("1.144.12.0")] +[module: RefSafetyRules(11)] +namespace ? +{ + internal static class ? + { + public static string ?(this Assembly P_0) + { + return P_0.?()?.Product; + } + + public static string ?(this Assembly P_0) + { + object obj = P_0.?()?.Version; + if (obj == null) + { + AssemblyFileVersionAttribute assemblyFileVersionAttribute = P_0.?(); + if (assemblyFileVersionAttribute == null) + { + return null; + } + obj = assemblyFileVersionAttribute.Version; + } + return (string)obj; + } + + public static ? ?(this Assembly P_0) where ? : Attribute + { + return P_0.GetCustomAttributes(typeof(?), inherit: false).FirstOrDefault() as ?; + } + } + internal static class ? + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ?(Assembly P_0, Assembly P_1) + { + if (P_0.?() != P_1.?()) + { + Environment.Exit(0); + } + if (P_0.?() != P_1.?()) + { + Environment.Exit(0); + } + } + } + internal static class ? + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(AuthenticodeSignature P_0) + { + return P_0.SigningCertificate.Thumbprint.ToUpper() == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + + internal bool ?(AuthenticodeSignature P_0) + { + return P_0.SigningCertificate.Thumbprint.ToUpper() == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ?(string P_0) + { + if (!?(P_0)) + { + Environment.Exit(0); + } + } + + internal static bool ?(string P_0) + { + try + { + FileInspector fileInspector = new FileInspector(P_0); + SignatureCheckResult signatureCheckResult = fileInspector.Validate(); + IEnumerable signatures = fileInspector.GetSignatures(); + if (Path.GetFileName(P_0) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + if (signatureCheckResult != SignatureCheckResult.Valid) + { + return false; + } + if (!signatures.Any((AuthenticodeSignature authenticodeSignature) => authenticodeSignature.SigningCertificate.Thumbprint.ToUpper() == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + return false; + } + } + else + { + if (signatureCheckResult != SignatureCheckResult.Valid && signatureCheckResult != SignatureCheckResult.UntrustedRoot) + { + return false; + } + if (!signatures.Any((AuthenticodeSignature authenticodeSignature) => authenticodeSignature.SigningCertificate.Thumbprint.ToUpper() == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + return false; + } + } + return true; + } + catch (Exception) + { + return false; + } + } + } +} +namespace Platform.Utils +{ + public static class Encryptor + { + [CompilerGenerated] + private static string ?; + + public static string UnicDeviceId + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = text; + } + } + + internal static string ?(string P_0) + { + if (string.IsNullOrEmpty(P_0)) + { + return P_0; + } + string result = string.Empty; + try + { + using Aes aes = Aes.Create(); + byte[] bytes = Encoding.UTF8.GetBytes(UnicDeviceId); + int count = Math.Min(aes.IV.Length, bytes.Length); + byte[] array = new byte[aes.IV.Length]; + Buffer.BlockCopy(bytes, 0, array, 0, count); + using ICryptoTransform transform = aes.CreateEncryptor(array, aes.IV); + using MemoryStream memoryStream = new MemoryStream(); + using (CryptoStream stream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write)) + { + using StreamWriter streamWriter = new StreamWriter(stream); + streamWriter.Write(P_0); + } + byte[] iV = aes.IV; + byte[] array2 = memoryStream.ToArray(); + byte[] array3 = new byte[iV.Length + array2.Length]; + Buffer.BlockCopy(iV, 0, array3, 0, iV.Length); + Buffer.BlockCopy(array2, 0, array3, iV.Length, array2.Length); + result = Convert.ToBase64String(array3); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return result; + } + + internal static string ?(string P_0) + { + if (string.IsNullOrEmpty(P_0)) + { + return P_0; + } + string result = null; + try + { + byte[] array = Convert.FromBase64String(P_0); + using Aes aes = Aes.Create(); + byte[] array2 = new byte[aes.IV.Length]; + byte[] array3 = new byte[array.Length - array2.Length]; + Buffer.BlockCopy(array, 0, array2, 0, array2.Length); + Buffer.BlockCopy(array, array2.Length, array3, 0, array.Length - array2.Length); + byte[] bytes = Encoding.UTF8.GetBytes(UnicDeviceId); + int count = Math.Min(aes.IV.Length, bytes.Length); + byte[] array4 = new byte[aes.IV.Length]; + Buffer.BlockCopy(bytes, 0, array4, 0, count); + using ICryptoTransform transform = aes.CreateDecryptor(array4, array2); + using MemoryStream stream = new MemoryStream(array3); + using CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read); + using StreamReader streamReader = new StreamReader(stream2); + result = streamReader.ReadToEnd(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return result; + } + } +} +namespace CancelAllOpenOrdersRequests +{ + public class CancelAllOpenOrdersOnSymbolRequest : RequestParameters, ISubTradingOperation + { + [CompilerGenerated] + private readonly SymbolComplexIdentifier ??; + + [CompilerGenerated] + private readonly string[] ??; + + [CompilerGenerated] + private readonly GroupTradingOperation ??; + + public override RequestType Type => RequestType.Custom; + + public SymbolComplexIdentifier SymbolComplexIdentifier + { + [CompilerGenerated] + get + { + return ??; + } + } + + public string[] OrderIdArray + { + [CompilerGenerated] + get + { + return ??; + } + } + + public GroupTradingOperation ParentOperation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public CancelAllOpenOrdersOnSymbolRequest(SymbolComplexIdentifier symbolComplexIdentifier, params string[] orderIdArray) + { + ?? = symbolComplexIdentifier; + ?? = orderIdArray; + } + } + public class CancelAllOpenOrdersOnAccountRequest : RequestParameters, ISubTradingOperation + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly GroupTradingOperation ??; + + public override RequestType Type => RequestType.Custom; + + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + } + + public GroupTradingOperation ParentOperation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public CancelAllOpenOrdersOnAccountRequest(string accountId) + { + ?? = accountId; + } + } + public class CancelAllOpenOrdersOnSymbolAndAccountRequest : RequestParameters, ISubTradingOperation + { + [CompilerGenerated] + private readonly SymbolComplexIdentifier ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly GroupTradingOperation ??; + + public override RequestType Type => RequestType.Custom; + + public SymbolComplexIdentifier SymbolComplexIdentifier + { + [CompilerGenerated] + get + { + return ??; + } + } + + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + } + + public GroupTradingOperation ParentOperation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public CancelAllOpenOrdersOnSymbolAndAccountRequest(SymbolComplexIdentifier symbolComplexIdentifier, string accountId) + { + ?? = symbolComplexIdentifier; + ?? = accountId; + } + } + public static class CancelRules + { + public const string ALLOW_CANCEL_ALL_OPEN_ORDERS_ON_SYMBOL = "Allow CancelAllOpenOrdersOnSymbol"; + + public const string ALLOW_CANCEL_ALL_OPEN_ORDERS_ON_ACCOUNT = "Allow CancelAllOpenOrdersOnAccount"; + + public const string ALLOW_CANCEL_ALL_OPEN_ORDERS_ON_SYMBOL_AND_ACCOUNT = "Allow CancelAllOpenOrdersOnSymbolAndAccount"; + } +} +namespace TradingPlatform.BusinessLayer +{ + public interface IConnectionBindedObject + { + string ConnectionId { get; } + } + public interface IConnectionStateDependent + { + ConnectionDependency GetConnectionStateDependency(); + + void OnConnectionStateChanged(Connection connection, ConnectionStateChangedEventArgs e); + } + public interface IHistoryItem : ICloneable + { + DateTime TimeLeft { get; } + + long TicksLeft { get; set; } + + long TicksRight { get; set; } + + double this[PriceType priceType] { get; } + + VolumeAnalysisData VolumeAnalysisData { get; set; } + + void SetData(string key, object value); + + bool TryGetData(string key, out TData data); + } + public interface IHistoryProcessor : IDisposable + { + SubscribeQuoteType? GetSubscribeQuoteType { get; } + + event HistoryEventHandler NewHistoryItem; + + event HistoryEventHandler HistoryItemUpdated; + + void Initialize(HistoryRequestParameters historyRequestParameters); + + IList AggregateHistory(HistoryHolder historyHolder); + + void ProcessQuote(MessageQuote messageQuote); + + void CorrectHistoryRequestBorders(HistoryRequestParameters historyRequestParameters); + + string GetTimeToNextBar(); + } + public interface IBusinessObjectsProvider + { + /// + /// Gets s list + /// + Symbol[] Symbols { get; } + + /// + /// Gets symbol types list + /// + SymbolType[] SymbolTypes { get; } + + /// + /// Gets s list + /// + Account[] Accounts { get; } + + /// + /// Gets s list + /// + Asset[] Assets { get; } + + /// + /// Gets Exchanges list + /// + Exchange[] Exchanges { get; } + + /// + /// Gets Orders list + /// + Order[] Orders { get; } + + /// + /// Gets Order Types list + /// + OrderType[] OrderTypes { get; } + + /// + /// Gets Positions list + /// + Position[] Positions { get; } + + /// + /// Gets Closed Positions list + /// + ClosedPosition[] ClosedPositions { get; } + + /// + /// Gets Corporate Actions list + /// + CorporateAction[] CorporateActions { get; } + + /// + /// Gets Report Types list + /// + ReportType[] ReportTypes { get; } + + DeliveredAsset[] DeliveredAssets { get; } + + AccountOperation[] AccountOperations { get; } + + /// + /// Gets s list + /// + TradingSignal[] TradingSignals { get; } + } + public interface ICurrentAccount + { + Account CurrentAccount { get; set; } + } + public interface ICurrentSymbol + { + Symbol CurrentSymbol { get; set; } + } + public interface ICustomizable + { + IList Settings { get; set; } + } + public interface ISetAsDefault + { + IList DefaultSetting { get; } + + void SetAsDefault(); + } + public interface ISaveAsTemplate : ISetAsDefault + { + IChartObjectTemplate[] AvailableTemplates { get; } + + void SaveAsTemplate(); + + void ApplyTemplate(IChartObjectTemplate template); + + void RenameTemplate(IChartObjectTemplate template); + + void RemoveTemplate(IChartObjectTemplate template); + } + public interface ICustomizableVisualGroups + { + void ProcessSettingsVisualGroups(IList settings); + } + public interface IHistoryTypeIndicator + { + HistoryType HistoryType { get; } + } +} +namespace ? +{ + internal interface ? + { + void ?(Indicator P_0); + } +} +namespace TradingPlatform.BusinessLayer +{ + public interface IIndicatorsCollection + { + void AddIndicator(Indicator indicator); + + void RemoveIndicator(Indicator indicator); + } + public interface IRangeWatchlistIndicator : IWatchlistIndicator + { + TimeSpan MinHistoryRange { get; } + } + public interface ISessionObserverIndicator + { + ISessionsContainer SessionContainer { get; } + } + public interface IVolumeAnalysisIndicator + { + bool IsRequirePriceLevelsCalculation { get; } + + void VolumeAnalysisData_Loaded(); + } + public interface IWatchlistIndicator + { + int MinHistoryDepths { get; } + } + public interface IOrder : ITradingObject, IUniqueID + { + /// + /// The ID of the order group. This group created when trades done by the MAM account. + /// + string GroupId { get; } + + /// + /// Total quantity of the order + /// + double TotalQuantity { get; } + + /// + /// Gets OrderType + /// + OrderType OrderType { get; } + + /// + /// Gets order price value + /// + double Price { get; } + + /// + /// Gets order trigger price value + /// + double TriggerPrice { get; } + + /// + /// Gets order trailing offset value + /// + double TrailOffset { get; } + + /// + /// Gets orders current status + /// + OrderStatus Status { get; } + + /// + /// Gets orders last update time + /// + DateTime LastUpdateTime { get; } + + /// + /// Gets Position Id. + /// + string PositionId { get; } + + /// + /// Gets StopLoss holder for given order + /// + SlTpHolder StopLoss { get; } + + /// + /// Gets TakeProfit holder for given order + /// + SlTpHolder TakeProfit { get; } + + SlTpHolder[] StopLossItems { get; } + + SlTpHolder[] TakeProfitItems { get; } + + string ConnectionId { get; } + + /// + /// Orders Type Id. It is used for the orders type comparing. + /// + string OrderTypeId { get; } + + /// + /// Gets order TIF(Time-In-Force) type + /// + TimeInForce TimeInForce { get; } + + /// + /// Gets orders expiration time + /// + DateTime ExpirationTime { get; } + + BusinessObjectState State { get; } + + /// + /// Remaining quantity of the order + /// + double RemainingQuantity { get; } + + /// + /// Filled quantity of the order + /// + double FilledQuantity { get; } + + /// + /// Gets open order original status + /// + string OriginalStatus { get; } + + double AverageFillPrice { get; } + + /// + /// Will be triggered on each invocation + /// + event Action Updated; + } + public interface ITradingObject + { + string Id { get; } + + Account Account { get; } + + Symbol Symbol { get; } + + Side Side { get; } + + string Comment { get; } + + AdditionalInfoCollection AdditionalInfo { get; } + } + public interface IUniqueID + { + string UniqueId { get; } + } + public interface IBuyerSellerData + { + string Seller { get; } + + string Buyer { get; } + } + public interface IVolumeTickData + { + VolumeTickDataType VolumeTickDataType { get; } + + long Time { get; } + + double Price { get; } + + double Volume { get; } + + TickDirection TickDirection { get; } + + AggressorFlag AggressorFlag { get; } + } + public enum VolumeTickDataType + { + Ticks, + Lasts + } + public sealed class DefaultSessionsContainer : ISessionsContainer, IMessageBuilder + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SessionsSet ?(CustomSession P_0) + { + return new SessionsSet + { + Days = P_0.Days, + CertainDates = new DateTime[0], + Sessions = new Session[1] + { + new Session(P_0.Name, P_0.OpenTime, P_0.CloseTime) + } + }; + } + } + + private static DefaultSessionsContainer ??; + + private readonly CustomSession[] ??; + + public static DefaultSessionsContainer Instance + { + get + { + lock (typeof(DefaultSessionsContainer)) + { + if (?? == null) + { + ?? = new DefaultSessionsContainer(); + } + } + return ??; + } + } + + public ISession[] ActiveSessions => ??; + + public TimeZoneInfo TimeZone => null; + + private DefaultSessionsContainer() + { + ?? = new CustomSession[1] + { + new CustomSession + { + Name = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + OpenOffset = TimeSpan.Zero, + CloseOffset = TimeSpan.FromTicks(863999999999L), + Days = Enum.GetValues(typeof(DayOfWeek)).Cast().ToArray(), + Type = SessionType.Main + } + }; + } + + public ISession[] GetSessionsForDate(DateTime dateTime) + { + return ??; + } + + public MessageSessionsContainer BuildMessage() + { + return new MessageSessionsContainer + { + Id = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + Name = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + Description = string.Empty, + Holidays = new HolidayInfo[0], + SessionsSets = ???.Select((CustomSession P_0) => new SessionsSet + { + Days = P_0.Days, + CertainDates = new DateTime[0], + Sessions = new Session[1] + { + new Session(P_0.Name, P_0.OpenTime, P_0.CloseTime) + } + }).ToArray() + }; + } + } + public interface ISession + { + string Name { get; } + + SessionType Type { get; } + + TimeSpan OpenTime { get; } + + TimeSpan CloseTime { get; } + + bool IsPrimary { get; } + } + public interface ISessionsContainer + { + ISession[] ActiveSessions { get; } + + TimeZoneInfo TimeZone { get; } + + ISession[] GetSessionsForDate(DateTime dateTime); + } + public enum SessionType + { + [Description("Main")] + Main, + [Description("Pre-market")] + PreMarket, + [Description("Post-market")] + PostMarket + } + [Published] + public interface IVolumeAnalysisCalculationProgress : IDisposable + { + VolumeAnalysisCalculationState State { get; } + + int ProgressPercent { get; } + + int ProgressBarIndex { get; } + + bool IsAborted { get; } + + VolumeAnalysisCalculationParameters CalculationParameters { get; } + + event EventHandler StateChanged; + + event EventHandler ProgressChanged; + + void AbortLoading(); + + void Wait(CancellationToken token = default(CancellationToken)); + } + [Published] + public interface IVolumeAnalysisCalculationTask : IDisposable + { + VolumeAnalysisData Result { get; } + + IVolumeAnalysisCalculationProgress Progress { get; } + } + /// + /// Defines 'Volume Analysis' calculation result item + /// + public interface IVolumeAnalysisItem + { + double GetValue(VolumeAnalysisField field); + } + /// + /// Contains all user's account information + /// + [Published] + public class Account : BusinessObject, ?, IMessageBuilder, IComparable, IComparable, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Asset ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private NettingType ??; + + [CompilerGenerated] + private AdditionalInfoCollection ??; + + private readonly ? ??; + + [CompilerGenerated] + private Action ??; + + /// + /// Gets account unique code. + /// + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Obtaining account name. + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets base currency of account. Account CCY is always equal to the server CCY in AlgoStudio + /// + public Asset AccountCurrency + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = asset; + } + } + + /// + /// Gets current balance of the account. + /// + public double Balance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public NettingType NettingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets additional account information + /// + [NotPublished] + public AdditionalInfoCollection AdditionalInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = additionalInfoCollection; + } + } + + int ?.PriorityIndex => 10; + + ? ?.Rules => ??; + + /// + /// Will be triggered on each account information updating + /// + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + [NotPublished] + protected internal Account(string connectionId) + : base(connectionId) + { + ?? = new ?(); + Core.Instance.RulesManager.Defaults.ForEach(delegate(Rule P_0) + { + ??.?(P_0.Name, P_0); + }); + } + + [NotPublished] + protected internal Account(BusinessObjectInfo accountInfo) + : base(accountInfo.ConnectionId) + { + Id = accountInfo.Id; + Name = accountInfo.Name; + State = BusinessObjectState.Fake; + } + + internal void ?(MessageAccount P_0) + { + Id = P_0.AccountId; + Name = P_0.AccountName; + if (P_0.AssetId != null && ConnectionCache != null && ConnectionCache.??.TryGetValue(P_0.AssetId, out var value)) + { + AccountCurrency = value; + } + Balance = P_0.Balance; + NettingType = P_0.NettingType; + if (P_0.AccountAdditionalInfo != null) + { + if (AdditionalInfo == null) + { + AdditionalInfoCollection additionalInfoCollection = (AdditionalInfo = new AdditionalInfoCollection()); + } + foreach (AdditionalInfoItem item in P_0.AccountAdditionalInfo) + { + AdditionalInfo.?(item); + } + } + ???.Invoke(this); + } + + private MessageAccount ?() + { + return new MessageAccount + { + AccountId = Id, + AccountName = Name, + AssetId = AccountCurrency.Id, + Balance = Balance, + AccountAdditionalInfo = AdditionalInfo?.Items.ToList() + }; + } + + MessageAccount IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + /// + /// Gets Account name + /// + /// + [NotPublished] + public override string ToString() + { + return Name; + } + + /// + /// Creates a business object info with an Account data which can be used for the restoring/serialization process. + /// + /// + [NotPublished] + public override BusinessObjectInfo CreateInfo() + { + return new ? + { + ConnectionId = base.ConnectionId, + Id = Id, + Name = Name, + IsCrypto = false + }; + } + + public int CompareTo(object obj) + { + return CompareTo(obj as Account); + } + + public int CompareTo(Account other) + { + if (this == other) + { + return 0; + } + if (other == null) + { + return 1; + } + return string.Compare(Id, other.Id, StringComparison.Ordinal); + } + + public bool Equals(Account other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Id == other.Id) + { + return base.ConnectionId == other.ConnectionId; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((Account)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Id, base.ConnectionId); + } + + [CompilerGenerated] + private void ?(Rule P_0) + { + ??.?(P_0.Name, P_0); + } + } + /// + /// The account operation. + /// + public class AccountOperation : BusinessObject, IComparable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IList ??; + + private AccountOperationUpdateHandler ??; + + private AccountOperationConfirmationHandler ??; + + private AccountOperationExecuteHandler ??; + + /// + /// Gets the name. + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets the button text. + /// + public string ButtonText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets the settings. + /// + public IList Settings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = list; + } + } + + internal AccountOperation(string P_0) + : base(P_0) + { + } + + /// + /// + /// + /// The settings. + public void Update(IList settings) + { + ???.Invoke(settings); + } + + /// + /// Builds the confirmation. + /// + /// The settings. + /// A string. + public string BuildConfirmation(IList settings) + { + return ???.Invoke(settings); + } + + /// + /// + /// + /// The settings. + public void Execute(IList settings) + { + ???.Invoke(settings); + } + + internal void ?(MessageAccountOperation P_0) + { + Name = P_0.Name; + ButtonText = P_0.ButtonText; + Settings = P_0.Settings.DeepCopy().ToList(); + ?? = P_0.UpdateHandler; + ?? = P_0.BuildConfirmationHandler; + ?? = P_0.ExecuteHandler; + } + + /// + /// Compare to. + /// + /// The obj. + /// An int. + public int CompareTo(object obj) + { + if (!(obj is AccountOperation accountOperation)) + { + return 0; + } + return string.Compare(Name, accountOperation.Name, StringComparison.Ordinal); + } + } + public delegate string AccountOperationConfirmationHandler(IList settings); + public delegate void AccountOperationExecuteHandler(IList settings); + public delegate void AccountOperationUpdateHandler(IList settings); + /// + /// The additional info collection. + /// + public class AdditionalInfoCollection : IEnumerable, IEnumerable, IEquatable + { + private readonly Dictionary ?; + + private readonly object ?; + + private static readonly ListEqualityComparer ?; + + /// + /// Gets the count. + /// + public int Count => ?.Count; + + public AdditionalInfoItem this[string key] + { + get + { + if (TryGetItem(key, out var item)) + { + return item; + } + throw new KeyNotFoundException(); + } + } + + /// + /// Gets the items. + /// + public IEnumerable Items + { + get + { + lock (?) + { + foreach (KeyValuePair item in ?) + { + yield return item.Value.Clone() as AdditionalInfoItem; + } + } + } + } + + static AdditionalInfoCollection() + { + ? = new ListEqualityComparer(EqualityComparer.Default); + } + + /// + /// Initializes a new instance of the class. + /// + public AdditionalInfoCollection() + { + ? = new Dictionary(); + ? = new object(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The items. + public AdditionalInfoCollection(params AdditionalInfoItem[] items) + : this() + { + foreach (AdditionalInfoItem additionalInfoItem in items) + { + ?(additionalInfoItem); + } + } + + /// + /// Try get item. + /// + /// The api key. + /// The item. + /// A bool. + public bool TryGetItem(string apiKey, out AdditionalInfoItem item) + { + item = null; + lock (?) + { + if (?.TryGetValue(apiKey, out var value)) + { + item = value.Clone() as AdditionalInfoItem; + return true; + } + } + return false; + } + + internal void ?(AdditionalInfoItem P_0) + { + lock (?) + { + if (!?.TryGetValue(P_0.Id, out var value)) + { + value = new AdditionalInfoItem(); + ?.Add(P_0.Id, value); + } + value.Update(P_0); + } + } + + internal void ?(IEnumerable P_0) + { + lock (?) + { + foreach (SettingItem item in P_0) + { + if (?.TryGetValue(item.Name, out var value)) + { + value.Value = item.Value; + } + } + } + } + + /// + /// Gets the enumerator. + /// + /// ]]> + public IEnumerator GetEnumerator() + { + return Items.GetEnumerator(); + } + + private IEnumerator ?() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + /// + /// Tos the string. + /// + /// A string. + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + using (IEnumerator enumerator = GetEnumerator()) + { + while (enumerator.MoveNext()) + { + AdditionalInfoItem current = enumerator.Current; + if (current.Hidden || !current.Visible) + { + continue; + } + string value = ((current.FormattingDescription == null) ? current.Value.ToString() : current.FormattingDescription.GetFormattedData()); + if (string.IsNullOrEmpty(current.NameKey) && string.IsNullOrEmpty(value)) + { + continue; + } + if (string.IsNullOrEmpty(current.NameKey)) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); + handler.AppendFormatted(value); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder3.Append(ref handler); + continue; + } + object value2 = current.Value; + if (value2 is bool) + { + if ((bool)value2) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); + handler.AppendFormatted(current.NameKey); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder4.Append(ref handler); + } + } + else + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder5 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(5, 2, stringBuilder2); + handler.AppendFormatted(current.NameKey); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + handler.AppendFormatted(value); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder5.Append(ref handler); + } + } + } + return stringBuilder.ToString().TrimEnd(' ', ';'); + } + + public bool Equals(AdditionalInfoCollection other) + { + List x = Items.ToList(); + List y = other.Items.ToList(); + return ?.Equals(x, y); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((AdditionalInfoCollection)obj); + } + + public override int GetHashCode() + { + return ?.GetHashCode(Items.ToList()); + } + } + /// + /// The comparing type. + /// + [DataContract(Name = "ComparingType", Namespace = "TradingPlatform")] + public enum ComparingType + { + [EnumMember] + String, + [EnumMember] + Int, + [EnumMember] + Double, + [EnumMember] + Long, + [EnumMember] + DateTime, + [EnumMember] + Boolean + } + /// + /// The additional info item formating type. + /// + public enum AdditionalInfoItemFormatingType + { + None, + AssetBalance, + CustomAsset, + Percent + } + /// + /// The additional info item. + /// + [ProtoContract] + public class AdditionalInfoItem : ICloneable, IXElementSerialization, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private ComparingType ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private AdditionalInfoItemFormatingType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private EditingInfo ??; + + [CompilerGenerated] + private IFormattingDescription ??; + + /// + /// ???? ??? ???, ??????????? ??? ?????????? ? ?????? ???? ?????????? + /// + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the group info. + /// + [ProtoMember(2)] + public string GroupInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the sort index. + /// + [ProtoMember(3)] + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the name key. + /// + [ProtoMember(4)] + public string NameKey + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the tool tip key. + /// + [ProtoMember(5)] + public string ToolTipKey + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the data type. + /// + [ProtoMember(6)] + public ComparingType DataType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the value. + /// + [ProtoIgnore] + public object Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether hidden. + /// + [ProtoMember(7)] + public bool Hidden + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the formating type. + /// + [ProtoMember(8)] + public AdditionalInfoItemFormatingType FormatingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// ???????????? ? ?????? ? AccountAdditionalInfoItemFormatingType.CustomAsset ??? ?????????????? ? ???????? ?????? + /// + [ProtoMember(9)] + public string CustomAssetID + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether visible. + /// + [ProtoMember(10)] + public bool Visible + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether is link. + /// + [ProtoMember(11)] + public bool IsLink + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(12, IsRequired = false)] + private string ProtoDynamicPropertySurrogateString + { + get + { + if (DataType != ComparingType.String) + { + return null; + } + return (string)Value; + } + set + { + if (DataType == ComparingType.String && text != null) + { + Value = text; + } + } + } + + [ProtoMember(13, IsRequired = false)] + private int? ProtoDynamicPropertySurrogateInt + { + get + { + if (DataType != ComparingType.Int) + { + return null; + } + return (int)Value; + } + set + { + if (DataType == ComparingType.Int && num.HasValue) + { + Value = num; + } + } + } + + [ProtoMember(14, IsRequired = false)] + private double? ProtoDynamicPropertySurrogateDouble + { + get + { + if (DataType != ComparingType.Double) + { + return null; + } + return (double)Value; + } + set + { + if (DataType == ComparingType.Double && num.HasValue) + { + Value = num; + } + } + } + + [ProtoMember(15, IsRequired = false)] + private long? ProtoDynamicPropertySurrogateLong + { + get + { + if (DataType != ComparingType.Long) + { + return null; + } + return (long)Value; + } + set + { + if (DataType == ComparingType.Long && num.HasValue) + { + Value = num; + } + } + } + + [ProtoMember(16, IsRequired = false)] + private DateTime? ProtoDynamicPropertySurrogateDateTime + { + get + { + if (DataType != ComparingType.DateTime) + { + return null; + } + return (DateTime)Value; + } + set + { + if (DataType == ComparingType.DateTime && dateTime.HasValue) + { + Value = dateTime; + } + } + } + + [ProtoMember(17, IsRequired = false)] + private bool? ProtoDynamicPropertySurrogateBoolean + { + get + { + if (DataType != ComparingType.Boolean) + { + return null; + } + return (bool)Value; + } + set + { + if (DataType == ComparingType.Boolean && flag.HasValue) + { + Value = flag; + } + } + } + + /// + /// Gets or Sets the editing info. + /// + public EditingInfo EditingInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the formatting description. + /// + public IFormattingDescription FormattingDescription + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + public AdditionalInfoItem() + { + Visible = true; + } + + /// + /// + /// + /// The item. + public virtual void Update(AdditionalInfoItem item) + { + GroupInfo = item.GroupInfo; + SortIndex = item.SortIndex; + NameKey = item.NameKey; + ToolTipKey = item.ToolTipKey; + DataType = item.DataType; + Value = item.Value; + Hidden = item.Hidden; + Visible = item.Visible; + IsLink = item.IsLink; + Id = item.Id; + FormatingType = item.FormatingType; + CustomAssetID = item.CustomAssetID; + EditingInfo = ((item.EditingInfo == null) ? null : new EditingInfo(item.EditingInfo)); + FormattingDescription = item.FormattingDescription; + } + + /// + /// + /// + /// An object. + public object Clone() + { + AdditionalInfoItem additionalInfoItem = new AdditionalInfoItem(); + additionalInfoItem.Update(this); + return additionalInfoItem; + } + + /// + /// To the XML element. + /// + /// A XElement. + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GroupInfo)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SortIndex)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), NameKey)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ToolTipKey)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)DataType)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Value)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Hidden)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)FormatingType)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CustomAssetID)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Visible)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsLink)); + return xElement; + } + + /// + /// From the XML element. + /// + /// The element. + /// The deserialization info. + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + GroupInfo = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + SortIndex = xElement3.ToInt(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + NameKey = xElement4.Value; + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + ToolTipKey = xElement5.Value; + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + DataType = (ComparingType)xElement6.ToInt(); + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + Value = DataType switch + { + ComparingType.Int => xElement7.ToInt(), + ComparingType.Double => xElement7.ToDouble(), + ComparingType.Long => xElement7.ToLong(), + ComparingType.DateTime => xElement7.ToDateTime(), + ComparingType.Boolean => xElement7.ToBool(), + _ => xElement7.Value, + }; + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + if (xElement8 != null) + { + Hidden = xElement8.ToBool(); + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + FormatingType = (AdditionalInfoItemFormatingType)xElement9.ToInt(); + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + CustomAssetID = xElement10.Value; + } + XElement xElement11 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + Visible = xElement11.ToBool(); + } + XElement xElement12 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + IsLink = xElement12.ToBool(); + } + } + + /// + /// To the string. + /// + /// A string. + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(38, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(GroupInfo); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Visible); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Hidden); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public bool Equals(AdditionalInfoItem other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (NameKey == other.NameKey) + { + return object.Equals(Value, other.Value); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((AdditionalInfoItem)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(NameKey, Value); + } + } + public class EditingInfo + { + [CompilerGenerated] + private SettingItem ?; + + [CompilerGenerated] + private Action ?; + + public SettingItem SettingItem + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public Action ValueChanged + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public EditingInfo() + { + } + + public EditingInfo(EditingInfo origin) + { + SettingItem = origin.SettingItem.GetCopy(); + ValueChanged = origin.ValueChanged; + } + } + /// + /// Defines asset entity + /// + [Published] + public class Asset : BusinessObject, IComparable, IMessageBuilder + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + /// + /// Asset id bearer + /// + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Asset name bearer + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Asset description + /// + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Defines a number precision of the change value + /// + public double MinimumChange + { + get + { + return ??; + } + set + { + if (?? != value) + { + ?? = value; + Precision = CoreMath.GetValuePrecision((decimal)??); + } + } + } + + /// + /// Gets precision value + /// + public int Precision + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets asset ISO 4217 code + /// + public string IsoCode + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Creates an Asset instance + /// + /// given connection Id + [NotPublished] + public Asset(string connectionId) + : base(connectionId) + { + } + + /// + /// Formats price into precision normalized string + /// + /// + /// + public string FormatPrice(double price) + { + if (!double.IsNaN(price)) + { + return price.Format(Precision); + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + + /// + /// Formats price into concatenated string which contains the precision normalized value and Asset's name + /// + /// + /// + public string FormatPriceWithCurrency(double price) + { + if (!double.IsNaN(price)) + { + return price.Format(Precision) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Name; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + + public string FormatWithCurrency(double value) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 2); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + internal void ?(MessageAsset P_0) + { + Id = P_0.Id; + Name = P_0.Name; + Description = P_0.Description; + MinimumChange = P_0.MinimumChange; + IsoCode = P_0.IsoCode; + } + + private MessageAsset ?() + { + return new MessageAsset + { + Id = Id, + Name = Name, + Description = Description, + MinimumChange = MinimumChange, + IsoCode = IsoCode + }; + } + + MessageAsset IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + /// + /// Gets Asset name + /// + /// + [NotPublished] + public override string ToString() + { + return Name; + } + + /// + /// Uses comparison by Assets names + /// + /// + /// + [NotPublished] + public int CompareTo(object obj) + { + if (!(obj is Asset asset)) + { + return 1; + } + return Name.CompareTo(asset.Name); + } + } + [DataContract] + [KnownType(typeof(Account))] + [KnownType(typeof(PnLItem))] + public abstract class BusinessObject : IConnectionBindedObject, IUniqueID + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private BusinessObjectState ??; + + private Connection ??; + + [CompilerGenerated] + private string ??; + + private static long ??; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public virtual BusinessObjectState State + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected internal set + { + ?? = value; + } + } + + public virtual Connection Connection => ?? ?? (?? = Core.Instance.Connections[ConnectionId]); + + internal virtual ? ConnectionCache => Connection?.??; + + /// + /// Unique ID during active session. Don't use for serialization + /// + public string UniqueId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal BusinessObject() + { + } + + internal BusinessObject(string P_0) + { + UniqueId = Interlocked.Increment(ref ??).ToString(); + ConnectionId = P_0; + State = BusinessObjectState.Normal; + } + + [NotPublished] + public virtual BusinessObjectInfo CreateInfo() + { + return new BusinessObjectInfo + { + ConnectionId = ConnectionId + }; + } + } + [DataContract(Name = "AccountStatus", Namespace = "TradingPlatform")] + public enum AccountStatus + { + [EnumMember] + Active, + [EnumMember] + Closed, + [EnumMember] + Halted + } + /// + /// ?????????? ???????????? ????????????? ????? ??? ???? ??????????? + /// + [DataContract(Name = "InstrumentType", Namespace = "TradingPlatform")] + public enum SymbolType + { + [EnumMember] + Unknown, + [EnumMember] + Forex, + [EnumMember] + Equities, + [EnumMember] + CFD, + [EnumMember] + Indexes, + [EnumMember] + Futures, + [EnumMember] + Options, + [EnumMember] + ETF, + [EnumMember] + Crypto, + [EnumMember] + Synthetic, + [EnumMember] + Spot, + [EnumMember] + Forward, + [EnumMember] + FixedIncome, + [EnumMember] + Warrants, + /// + /// ?????? ??? ????????? ?????????? + /// + [EnumMember] + Debentures, + [EnumMember] + Bond, + [EnumMember] + Swap + } + [DataContract(Name = "InstrumentQuotingType", Namespace = "TradingPlatform")] + public enum SymbolQuotingType + { + [EnumMember] + LotSize, + [EnumMember] + TickSizeTickCost, + [EnumMember] + Undefined + } + [DataContract(Name = "OptionCodingStyle", Namespace = "TradingPlatform")] + public enum OptionCodingStyle + { + [EnumMember] + Unspecified, + [EnumMember] + European, + [EnumMember] + American + } + public enum OrderStatus + { + [Description("Unspecified")] + Unspecified, + [Description("Opened")] + Opened, + [Description("Partially Filled")] + PartiallyFilled, + [Description("Filled")] + Filled, + [Description("Cancelled")] + Cancelled, + [Description("Refused")] + Refused, + [Description("Inactive")] + Inactive + } + public enum TimeInForce + { + [Description("Default")] + Default, + [Description("Day")] + Day, + [Description("Fill Or Kill")] + FOK, + [Description("Good Till Cancel")] + GTC, + [Description("Immediate Or Cancel")] + IOC, + [Description("Good Till Date")] + GTD, + [Description("Good Till Time")] + GTT, + [Description("Fill And Kill")] + FAK, + [Description("At The Open")] + ATO, + [Description("At The Close")] + ATC + } + public enum DealTicketType + { + [Description("Info")] + Info, + [Description("Refuse")] + Refuse, + [Description("Order opened")] + OrderOpened, + [Description("Order filled")] + OrderFilled, + [Description("Order partially filled")] + OrderPartiallyFilled, + [Description("Order cancelled")] + OrderCancelled, + [Description("Trading operation request")] + TradingOperationRequest, + [Description("Trading operation success")] + TradingOperationResultSuccess, + [Description("Trading operation refuse")] + TradingOperationResultRefuse, + [Description("Trading signal")] + TradingSignal, + [Description("Terminal update")] + TerminalUpdate, + [Description("License")] + License, + [Description("Connection success")] + ConnectionSuccess, + [Description("Connection lost")] + ConnectionLost + } + public enum DealTicketState + { + Received, + Seen + } + public enum PriceMeasurement + { + Absolute, + Offset + } + [DataContract(Name = "NettingType", Namespace = "TradingPlatform")] + public enum NettingType + { + [Description("Undefined")] + [EnumMember] + Undefined, + [Description("Multiple positions")] + [EnumMember] + MultiPosition, + [Description("Multiple positions per side")] + [EnumMember] + MultiPerSide, + [Description("One position")] + [EnumMember] + OnePosition, + [Description("One position per side")] + [EnumMember] + OnePositionPerSide + } + [DataContract(Name = "InstrumentVolumeType", Namespace = "TradingPlatform")] + public enum SymbolVolumeType + { + [EnumMember] + Volume, + [EnumMember] + Ticks, + [EnumMember] + Disable + } + public enum BusinessObjectState + { + Normal, + Fake + } + [DataContract(Name = "DeltaCalculationType", Namespace = "TradingPlatform")] + public enum DeltaCalculationType + { + [Description("Aggressor flag")] + [EnumMember(Value = "Aggressor flag")] + AggressorFlag, + [Description("Tick direction")] + [EnumMember(Value = "Tick direction")] + TickDirection + } + [DataContract(Name = "AvailableDerivatives", Namespace = "TradingPlatform")] + public enum AvailableDerivatives + { + None, + Unknown, + Present + } + [DataContract(Name = "FutureContractType", Namespace = "TradingPlatform")] + public enum FutureContractType + { + [EnumMember] + Contract, + [EnumMember] + Continuous, + [EnumMember] + Spread + } + public enum GroupOrderType + { + None, + OCO + } + public enum AccountBalanceEventReason + { + New, + Update + } + public enum OptionSerieType + { + Unknown, + Daily, + Week, + Month, + BinaryContracts + } + public class ClosedPosition : Position + { + [CompilerGenerated] + private double ??; + + public double LastTradedPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + internal ClosedPosition(string P_0) + : base(P_0) + { + } + + public override TradingOperationResult Close(double closeQuantity = -1.0) + { + return TradingOperationResult.CreateError(new ClosePositionRequestParameters().RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + internal override void ?(MessageOpenPosition P_0) + { + base.?(P_0); + if (P_0 is MessageClosedPosition messageClosedPosition) + { + LastTradedPrice = messageClosedPosition.LastTradedPrice; + } + } + } + /// + /// Represents information about corporate action. + /// + [Published] + public class CorporateAction : BusinessObject + { + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private CorporateActionType ??; + + [CompilerGenerated] + private Action ??; + + /// + /// Get the date and time when trade was executed + /// + public DateTime DateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + [DataMember(Name = "ID")] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + [DataMember(Name = "Instrument")] + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public string Details + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public CorporateActionType CorporateActionType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Will be triggered on corporate action updating + /// + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public CorporateAction(string connectionId) + : base(connectionId) + { + } + + internal void ?(MessageCorporateAction P_0) + { + Id = P_0.CorporateActionId; + if (!string.IsNullOrEmpty(P_0.SymbolId) && ConnectionCache != null && ConnectionCache.SymbolsCache.?(P_0.SymbolId, out var symbol)) + { + Symbol = symbol; + } + DateTime = P_0.DateTime; + Details = P_0.Details; + CorporateActionType = P_0.CorporateActionType; + ???.Invoke(); + } + } + [Published] + [DataContract(Name = "CryptoAccount", Namespace = "TradingPlatform")] + public class CryptoAccount : Account, IMessageBuilder + { + private readonly Dictionary ??; + + [CompilerGenerated] + private EventHandler ??; + + public CryptoAssetBalances[] Balances => ??.Values.ToArray(); + + public event EventHandler BalanceUpdated + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + internal CryptoAccount(string P_0) + : base(P_0) + { + ?? = new Dictionary(); + } + + internal CryptoAccount(BusinessObjectInfo P_0) + : base(P_0) + { + ?? = new Dictionary(); + } + + public bool TryGetAssetBalances(string assetId, out CryptoAssetBalances cryptoAssetBalances) + { + return ??.TryGetValue(assetId, out cryptoAssetBalances); + } + + internal void ?(MessageCryptoAssetBalances P_0) + { + AccountBalanceEventReason reason = AccountBalanceEventReason.Update; + if (!??.TryGetValue(P_0.AssetId, out var value)) + { + value = (??[P_0.AssetId] = new CryptoAssetBalances(base.ConnectionId)); + reason = AccountBalanceEventReason.New; + } + value.?(P_0); + ??.InvokeSafely(this, new CryptoAccountEventArgs(reason, value)); + } + + public override BusinessObjectInfo CreateInfo() + { + ? obj = base.CreateInfo() as ?; + obj.IsCrypto = true; + return obj; + } + + private MessageCryptoAccount ?() + { + return new MessageCryptoAccount + { + AccountId = base.Id, + AccountName = base.Name, + AssetId = base.AccountCurrency?.Id, + Balance = base.Balance, + AccountAdditionalInfo = base.AdditionalInfo?.Items.ToList() + }; + } + + MessageCryptoAccount IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } + [Published] + [DataContract(Name = "CryptoAssetBalances", Namespace = "TradingPlatform")] + public class CryptoAssetBalances : BusinessObject, IMessageBuilder + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Asset ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private GetAvailableBalanceHandler ??; + + private string ??; + + [DataMember(Name = "AssetId")] + public string AssetId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public Asset Asset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = asset; + } + } + + [DataMember(Name = "TotalBalance")] + public double TotalBalance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "AvailableBalance")] + public double AvailableBalance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "ReservedBalance")] + public double ReservedBalance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "TotalInUSD")] + public double TotalInUSD + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "TotalInBTC")] + public double TotalInBTC + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "Debt")] + public double Debt + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "Equity")] + public double Equity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + [DataMember(Name = "EquityInBTC")] + public double EquityInBTC + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = num; + } + } + + public DateTime LastUpdateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public GetAvailableBalanceHandler AvailableBalanceHandler + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double GetAvailableBalance(OrderRequestParameters requestParameters) + { + double availableBalance = 0.0; + GetAvailableBalanceHandler availableBalanceHandler = AvailableBalanceHandler; + if (availableBalanceHandler != null && availableBalanceHandler(AssetId, requestParameters, out availableBalance)) + { + return availableBalance; + } + return AvailableBalance; + } + + internal CryptoAssetBalances(string P_0) + : base(P_0) + { + } + + internal void ?(MessageCryptoAssetBalances P_0) + { + AssetId = P_0.AssetId; + TotalBalance = P_0.TotalBalance; + AvailableBalance = P_0.AvailableBalance; + ReservedBalance = P_0.ReservedBalance; + TotalInUSD = P_0.TotalInUSD; + TotalInBTC = P_0.TotalInBTC; + Debt = P_0.Debt; + Equity = P_0.Equity; + EquityInBTC = P_0.EquityInBTC; + AvailableBalanceHandler = P_0.AvailableBalanceHandler; + ?? = P_0.AccountId; + if (!string.IsNullOrEmpty(P_0.AssetId) && ConnectionCache.??.TryGetValue(P_0.AssetId, out var value)) + { + Asset = value; + } + LastUpdateTime = Core.Instance.TimeUtils.DateTimeUtcNow; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(18, 2); + defaultInterpolatedStringHandler.AppendFormatted(AssetId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TotalBalance); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public MessageCryptoAssetBalances BuildMessage() + { + return new MessageCryptoAssetBalances + { + AssetId = AssetId, + TotalBalance = TotalBalance, + AvailableBalance = AvailableBalance, + ReservedBalance = ReservedBalance, + TotalInUSD = TotalInUSD, + TotalInBTC = TotalInBTC, + Debt = Debt, + Equity = Equity, + EquityInBTC = EquityInBTC, + AvailableBalanceHandler = AvailableBalanceHandler, + AccountId = ?? + }; + } + } + /// + /// Base class for all Custom symbols: Synthetics, Custom Formulas, etc. + /// + public class CustomSymbol : Symbol, IDisposable + { + public CustomSymbol(string connectionID) + : base(connectionID) + { + base.Id = Guid.NewGuid().ToString(); + } + + public virtual void Dispose() + { + } + } +} +namespace ? +{ + internal sealed class ? : HistoricalData + { + [Serializable] + [CompilerGenerated] + private new sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func> ??; + + internal IEnumerable ?(HistoryInterval P_0) + { + return P_0.History; + } + } + + private readonly HistoryStorage ??; + + public ?(HistoryRequestParameters P_0, HistoryStorage P_1) + : base(P_0) + { + ?? = P_1; + } + + private protected override IList ?(HistoryRequestParameters P_0) + { + List list = new List(); + if (?? == null) + { + return list; + } + if (!(P_0.Symbol is HistoricalSymbol historicalSymbol)) + { + return list; + } + if (P_0.FromTime > P_0.ToTime) + { + return list; + } + HistoryAggregation aggregationToDirectDownload = P_0.Aggregation.GetAggregationToDirectDownload(P_0.Symbol.HistoryMetadata); + if (aggregationToDirectDownload == null) + { + return list; + } + HistoryRequestParameters historyRequestParameters = new HistoryRequestParameters(P_0) + { + ForceReload = false, + Aggregation = aggregationToDirectDownload + }; + HistoryStorageInfo info = historicalSymbol.GetInfo(historyRequestParameters.ToDescription(), HistoryStorageInfoScope.StoredIntervals); + if (info == null || !info.StoredIntervals.Any()) + { + return list; + } + DateTime dateTime = info.StoredIntervals.First().From; + if (historyRequestParameters.FromTime < dateTime) + { + historyRequestParameters.FromTime = dateTime; + } + Interval[] array = historyRequestParameters.Interval.Split(base.Symbol.GetHistoryDownloadingStep(historyRequestParameters.Aggregation)).ToArray(); + for (int i = 0; i < array.Length; i++) + { + try + { + if (P_0.CancellationToken.IsCancellationRequested) + { + break; + } + HistoryRequestParameters copy = historyRequestParameters.Copy; + copy.FromTime = array[i].From; + copy.ToTime = array[i].To; + List historyParametersForServerRequest; + List history = ??.Load(copy, out historyParametersForServerRequest).SelectMany((HistoryInterval historyInterval) => historyInterval.History).ToList(); + float num = (float)i / (float)array.Length; + IList collection = ??.AggregateHistory(new HistoryHolder(history, copy, (int)(num * 100f))); + list.AddRange(collection); + P_0.ProgressInfo?.Report(num); + continue; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + return list; + } + } + return list; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public sealed class HistoricalSymbol : CustomSymbol, IHistoryDataReceiver, IXElementSerialization, IHistoryStorage + { + public const string HISTORICAL_SYMBOL_CONNECTION_ID = "HISTORICAL_SYMBOL_CONNECTION_ID"; + + private string ??; + + private HistoryStorage ??; + + public HistoricalSymbol() + : base(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + base.Id = null; + ?(); + base.Exchange = new Exchange(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + base.Exchange.?(new MessageExchange + { + Id = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + ExchangeName = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = -1 + }); + } + + public void SetLocalStoragePath(string path) + { + if (!(?? == path)) + { + ???.Dispose(); + ?? = path; + ?? = HistoryStorage.Create(??); + ?(); + } + } + + private new void ?() + { + if (string.IsNullOrEmpty(??)) + { + historyMetadata = new HistoryMetadata(); + return; + } + HashSet hashSet = new HashSet(); + HashSet hashSet2 = new HashSet(); + HashSet hashSet3 = new HashSet(); + HashSet hashSet4 = new HashSet(); + HashSet hashSet5 = new HashSet(); + foreach (HistoryDescription allAvailableHistoryDescription in ??.GetAllAvailableHistoryDescriptions()) + { + HistoryStorageInfo info = ??.GetInfo(allAvailableHistoryDescription, HistoryStorageInfoScope.StoredIntervals); + if (info.StoredIntervals == null || !info.StoredIntervals.Any()) + { + continue; + } + hashSet.Add(allAvailableHistoryDescription.Aggregation.Name); + HistoryAggregation aggregation = allAvailableHistoryDescription.Aggregation; + if (!(aggregation is HistoryAggregationTime historyAggregationTime)) + { + if (!(aggregation is HistoryAggregationTick historyAggregationTick)) + { + if (!(aggregation is HistoryAggregationTimeStatistics historyAggregationTimeStatistics)) + { + if (aggregation is HistoryAggregationVolumeProfile historyAggregationVolumeProfile) + { + hashSet3.Add(historyAggregationVolumeProfile.Period); + } + } + else + { + hashSet3.Add(historyAggregationTimeStatistics.Period); + } + } + else + { + hashSet5.Add(historyAggregationTick.HistoryType); + } + } + else + { + hashSet2.Add(historyAggregationTime.Period); + hashSet4.Add(historyAggregationTime.HistoryType); + } + } + historyMetadata = new HistoryMetadata + { + AllowedAggregations = hashSet.ToArray(), + AllowedPeriodsHistoryAggregationTime = hashSet2.ToArray(), + AllowedHistoryTypesHistoryAggregationTime = hashSet4.ToArray(), + AllowedHistoryTypesHistoryAggregationTick = hashSet5.ToArray(), + AllowedPeriodsHistoryAggregationTimeStatistics = hashSet3.ToArray(), + DownloadingStep_Tick = TimeSpan.FromDays(1.0) + }; + } + + private protected override HistoricalData ?(HistoryRequestParameters P_0) + { + return new ?(P_0, ??); + } + + public override List GetAlowedOrderTypes(OrderTypeUsage? usage) + { + return new List(); + } + + public IList Load(HistoryRequestParameters requestParameters, out List historyParametersForServerRequest) + { + historyParametersForServerRequest = new List { requestParameters }; + return ???.Load(requestParameters, out historyParametersForServerRequest); + } + + public void Save(HistoryInterval historyInterval, bool wait = false) + { + if (?? != null) + { + ??.Save(historyInterval, wait); + ?(); + } + } + + public void Delete(HistoryDescription description, Interval interval, bool wait = false) + { + if (?? != null) + { + ??.Delete(description, interval, wait); + ??.?(); + ?(); + } + } + + public HistoryStorageInfo GetInfo(HistoryDescription description, HistoryStorageInfoScope scope) + { + return ???.GetInfo(description, scope); + } + + public List GetAllAvailableHistoryDescriptions() + { + return ??.GetAllAvailableHistoryDescriptions(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(GetType().Name); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ??)); + MessageSymbol messageSymbol = ((IMessageBuilder)this).BuildMessage(); + xElement.Add(messageSymbol.ToXElement()); + if (base.Product != null) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((IMessageBuilder)base.Product).BuildMessage().ToXElement())); + } + if (base.QuotingCurrency != null) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((IMessageBuilder)base.QuotingCurrency).BuildMessage().ToXElement())); + } + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + SetLocalStoragePath(xElement.Value); + } + string text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + XElement xElement2 = ((!(element.Name == text)) ? element.Element(text) : element); + if (xElement2 != null) + { + MessageSymbol messageSymbol = new MessageSymbol(base.Id); + messageSymbol.FromXElement(xElement2, deserializationInfo); + ?(messageSymbol); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + XElement xElement4 = xElement3.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + Asset asset = new Asset(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + MessageAsset messageAsset = new MessageAsset(); + messageAsset.FromXElement(xElement4, deserializationInfo); + asset.?(messageAsset); + base.Product = asset; + } + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + XElement xElement6 = xElement5.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + Asset asset2 = new Asset(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + MessageAsset messageAsset2 = new MessageAsset(); + messageAsset2.FromXElement(xElement6, deserializationInfo); + asset2.?(messageAsset2); + base.QuotingCurrency = asset2; + } + } + ?(); + } + + public void SaveHistory(HistoryHolder historyHolderFromProvider) + { + try + { + Save(new HistoryInterval + { + Description = new HistoryDescription(base.Id, historyHolderFromProvider.RequestParameters.Aggregation), + Interval = historyHolderFromProvider.RequestParameters.Interval, + History = historyHolderFromProvider.History + }, wait: true); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + public sealed class HistoryDataSymbolProvider : IHistoryDataProvider + { + [CompilerGenerated] + private Action ??; + + private readonly Symbol ??; + + private readonly HistoryRequestParameters ??; + + private readonly Interval[] ??; + + private int ??; + + public bool AllDataAlreadyProvided => ?? >= ??.Length; + + public string ProgressValue => ((float)?? / (float)??.Length).ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + + public event Action ProgressChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public HistoryDataSymbolProvider(Symbol realSymbolToImportHistory, HistoryRequestParameters historyRequestParameters) + { + ?? = realSymbolToImportHistory; + ?? = historyRequestParameters; + ?? = ??.Interval.Split(??.GetHistoryDownloadingStep(??.Aggregation)).ToArray(); + ?? = 0; + } + + public HistoryHolder GetHistory(CancellationToken cancellationToken) + { + Interval interval = ??[??]; + HistoryRequestParameters historyRequestParameters = new HistoryRequestParameters(??) + { + Interval = interval, + CancellationToken = cancellationToken + }; + if (?? == null) + { + return null; + } + HistoricalData history = ??.GetHistory(historyRequestParameters); + List list = new List(); + for (int i = 0; i < history.Count; i++) + { + list.Add(history[i, SeekOriginHistory.Begin]); + } + ??++; + ???.Invoke(ProgressValue); + return new HistoryHolder(list, historyRequestParameters); + } + } + public sealed class HistoryDataSymbolProviderRealtime : IHistoryDataProvider, IDisposable + { + private const int ?? = 10000; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private string ??; + + private DateTime ??; + + private DateTime ??; + + private readonly HistoricalData ??; + + private readonly HistoryRequestParameters ??; + + private readonly ManualResetEventSlim ??; + + public bool AllDataAlreadyProvided + { + get + { + if (!(?? >= ??.ToTime)) + { + return Core.Instance.TimeUtils.DateTimeUtcNow - ??.Symbol.QuoteDelay - TimeSpan.FromSeconds(10.0) > ??.ToTime; + } + return true; + } + } + + public string ProgressValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public event Action ProgressChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public HistoryDataSymbolProviderRealtime(HistoryRequestParameters historyRequestParameters) + { + ?? = historyRequestParameters; + HistoryRequestParameters historyRequestParameters2 = new HistoryRequestParameters(??) + { + ToTime = default(DateTime) + }; + ?? = new ManualResetEventSlim(); + ?? = ??.Symbol.GetHistory(historyRequestParameters2); + ??.NewHistoryItem += ?; + } + + public void Dispose() + { + ??.Dispose(); + ??.NewHistoryItem -= ?; + ??.Dispose(); + } + + public HistoryHolder GetHistory(CancellationToken cancellationToken) + { + if (??.Symbol == null) + { + return null; + } + if (??.Symbol.State == BusinessObjectState.Fake) + { + return null; + } + TimeSpan timeout = ??.ToTime - Core.Instance.TimeUtils.DateTimeUtcNow + ??.Symbol.QuoteDelay + TimeSpan.FromSeconds(10.0); + ??.Wait(timeout, cancellationToken); + ??.Reset(); + if (??.Count == 0) + { + return null; + } + List list = new List(); + HistoryRequestParameters historyRequestParameters = new HistoryRequestParameters(??); + int i; + for (i = 0; i < 10000 && i < ??.Count; i++) + { + IHistoryItem historyItem = ??[i, SeekOriginHistory.Begin]; + ?? = historyItem.TimeLeft; + if (historyItem.TimeLeft >= ??.ToTime) + { + break; + } + if (historyItem.TimeLeft >= ??.FromTime) + { + list.Add(historyItem); + } + } + if (!list.Any()) + { + return null; + } + historyRequestParameters.FromTime = list.First().TimeLeft; + historyRequestParameters.ToTime = new DateTime(list.Last().TicksRight + 1, DateTimeKind.Utc); + ??.CutItems(i); + return new HistoryHolder(list, historyRequestParameters); + } + + private void ?(object P_0, HistoryEventArgs P_1) + { + ?? = P_1.HistoryItem.TimeLeft; + if (?? < ??.FromTime) + { + if (??.Count > 10000) + { + ??.CutItems(10000); + } + ProgressValue = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + ???.Invoke(ProgressValue); + return; + } + if (??.Count >= 10000) + { + ??.Set(); + return; + } + if (?? >= ??.ToTime) + { + ??.Set(); + return; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(25, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.Count((IHistoryItem historyItem) => historyItem.TicksLeft > ??.FromTime.Ticks)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(10000); + ProgressValue = defaultInterpolatedStringHandler.ToStringAndClear(); + ???.Invoke(ProgressValue); + } + + [CompilerGenerated] + private bool ?(IHistoryItem P_0) + { + return P_0.TicksLeft > ??.FromTime.Ticks; + } + } + public interface IHistoryDataProvider + { + bool AllDataAlreadyProvided { get; } + + string ProgressValue { get; } + + event Action ProgressChanged; + + HistoryHolder GetHistory(CancellationToken changeToken); + } + public interface IHistoryDataReceiver + { + void SaveHistory(HistoryHolder historyFromProvider); + } + public sealed class ImportHistoryTask : IHistoryProcessingTask, IDisposable + { + [CompilerGenerated] + private sealed class ? + { + public CancellationToken ??; + + public ImportHistoryTask ??; + + internal void ?() + { + while (!??.??.AllDataAlreadyProvided) + { + try + { + if (??.IsCancellationRequested) + { + break; + } + HistoryHolder history = ??.??.GetHistory(??); + if (??.IsCancellationRequested || history == null) + { + break; + } + if (history.History.Any()) + { + ??.??.SaveHistory(history); + ??.?? += history.History.Count; + ??.???.Invoke(??.ProgressValue); + } + continue; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + ??.Stop(); + return; + } + } + ??.TaskState = HistoryTaskStateEnum.Completed; + ??.??.ProgressChanged -= ??.?; + (??.?? as IDisposable)?.Dispose(); + } + } + + [CompilerGenerated] + private Action ??; + + private HistoryTaskStateEnum ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Action ??; + + private int ??; + + private string ??; + + private readonly IHistoryDataProvider ??; + + private readonly IHistoryDataReceiver ??; + + private CancellationTokenSource ??; + + public HistoryTaskStateEnum TaskState + { + get + { + return ??; + } + private set + { + if (?? != HistoryTaskStateEnum.Completed) + { + ?? = historyTaskStateEnum; + switch (??) + { + case HistoryTaskStateEnum.Active: + ?(); + break; + case HistoryTaskStateEnum.Stopped: + ??.Cancel(); + break; + case HistoryTaskStateEnum.Completed: + ?? = string.Empty; + break; + } + ???.Invoke(??); + } + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ProgressValue + { + get + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + string text = defaultInterpolatedStringHandler.ToStringAndClear(); + if (string.IsNullOrEmpty(??)) + { + return text; + } + return text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ??; + } + } + + public event Action TaskStateChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ProgressChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public ImportHistoryTask(IHistoryDataProvider historyDataProvider, IHistoryDataReceiver historyDataReceiver) + { + ?? = historyDataProvider; + ?? = historyDataReceiver; + } + + public void Dispose() + { + if (?? != null) + { + ??.Cancel(); + ??.Dispose(); + ?? = null; + } + } + + public void Start() + { + TaskState = HistoryTaskStateEnum.Active; + } + + public void Stop() + { + TaskState = HistoryTaskStateEnum.Stopped; + } + + private void ?() + { + ?? = new CancellationTokenSource(); + CancellationToken ?? = ??.Token; + ??.ProgressChanged += ?; + ?? = 0; + ???.Invoke(ProgressValue); + Task.Factory.StartNew(delegate + { + while (!??.AllDataAlreadyProvided) + { + try + { + if (!??.IsCancellationRequested) + { + HistoryHolder history = ??.GetHistory(??); + if (!??.IsCancellationRequested && history != null) + { + if (history.History.Any()) + { + ??.SaveHistory(history); + ?? += history.History.Count; + ???.Invoke(ProgressValue); + } + continue; + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + Stop(); + return; + } + break; + } + TaskState = HistoryTaskStateEnum.Completed; + ??.ProgressChanged -= ?; + (?? as IDisposable)?.Dispose(); + }, ??); + } + + private void ?(string P_0) + { + ?? = P_0; + ???.Invoke(ProgressValue); + } + } + public interface IHistoryProcessingTask + { + HistoryTaskStateEnum TaskState { get; } + + string ProgressValue { get; } + + string Description { get; } + + event Action TaskStateChanged; + + event Action ProgressChanged; + + void Stop(); + } + public enum HistoryTaskStateEnum + { + [Description("Stopped")] + [EnumMember] + Stopped, + [Description("Active")] + [EnumMember] + Active, + [Description("Completed")] + [EnumMember] + Completed + } + public class BasicSyntheticPriceModifier : SyntheticPriceModifier + { + public override SyntheticPriceModifierType Type => SyntheticPriceModifierType.Basic; + + public override double CalculatePrice(double coefficient, double price) + { + return coefficient * price; + } + } + public class LnSyntheticPriceModifier : SyntheticPriceModifier + { + public override SyntheticPriceModifierType Type => SyntheticPriceModifierType.Ln; + + public override double CalculatePrice(double coefficient, double price) + { + return coefficient * Math.Log(price); + } + } + public abstract class SyntheticPriceModifier + { + public abstract SyntheticPriceModifierType Type { get; } + + public abstract double CalculatePrice(double coefficient, double price); + + public static SyntheticPriceModifier Create(SyntheticPriceModifierType type) + { + return type switch + { + SyntheticPriceModifierType.Undefined => new BasicSyntheticPriceModifier(), + SyntheticPriceModifierType.Basic => new BasicSyntheticPriceModifier(), + SyntheticPriceModifierType.Ln => new LnSyntheticPriceModifier(), + _ => throw new ArgumentOutOfRangeException(), + }; + } + } + public enum SyntheticPriceModifierType + { + Undefined, + [Description("Basic")] + Basic, + [Description("Ln")] + Ln + } +} +namespace ? +{ + internal sealed class ? : HistoricalData + { + private readonly Synthetic ??; + + public ?(HistoryRequestParameters P_0) + : base(P_0) + { + ?? = (Synthetic)P_0.Symbol; + } + + private protected override IList ?(HistoryRequestParameters P_0) + { + if (??.SyntheticState != SyntheticState.Initialized) + { + return new List(); + } + HistoryAggregation aggregationToDirectDownload = P_0.Aggregation.GetAggregationToDirectDownload(P_0.Symbol.HistoryMetadata); + HistoryRequestParameters historyRequestParameters = new HistoryRequestParameters(P_0) + { + Aggregation = aggregationToDirectDownload + }; + if (??.ForceUseTicksForHistory) + { + HistoryAggregation aggregation = historyRequestParameters.Aggregation; + if (!(aggregation is HistoryAggregationTickBars historyAggregationTickBars)) + { + if (aggregation is HistoryAggregationTime historyAggregationTime) + { + HistoryRequestParameters historyRequestParameters2 = historyRequestParameters; + historyRequestParameters2.Aggregation = new HistoryAggregationTick(historyAggregationTime.HistoryType switch + { + HistoryType.Ask => HistoryType.BidAsk, + HistoryType.Bid => HistoryType.BidAsk, + _ => historyAggregationTime.HistoryType, + }); + } + } + else + { + HistoryRequestParameters historyRequestParameters2 = historyRequestParameters; + historyRequestParameters2.Aggregation = new HistoryAggregationTick(historyAggregationTickBars.HistoryType switch + { + HistoryType.Ask => HistoryType.BidAsk, + HistoryType.Bid => HistoryType.BidAsk, + _ => historyAggregationTickBars.HistoryType, + }); + } + } + List list = new List(); + double[] array = new double[??.Items.Count]; + for (int i = 0; i < ??.Items.Count; i++) + { + array[i] = ??.Items[i].Coefficient; + HistoryRequestParameters historyRequestParameters3 = new HistoryRequestParameters(historyRequestParameters) + { + Symbol = ??.Items[i].Symbol + }; + if (??.Items[i].Coefficient < 0.0) + { + HistoryAggregation aggregation = historyRequestParameters3.Aggregation; + if (!(aggregation is HistoryAggregationTickBars { HistoryType: var historyType } historyAggregationTickBars2)) + { + if (aggregation is HistoryAggregationTime { HistoryType: var historyType2 } historyAggregationTime2) + { + HistoryType historyType3 = historyType2 switch + { + HistoryType.Ask => HistoryType.Bid, + HistoryType.Bid => HistoryType.Ask, + _ => historyAggregationTime2.HistoryType, + }; + historyRequestParameters.Aggregation = new HistoryAggregationTime(historyAggregationTime2.Period, historyType3); + } + } + else + { + HistoryType historyType4 = historyType switch + { + HistoryType.Ask => HistoryType.Bid, + HistoryType.Bid => HistoryType.Ask, + _ => historyAggregationTickBars2.HistoryType, + }; + historyRequestParameters.Aggregation = new HistoryAggregationTickBars(historyAggregationTickBars2.TicksCount, historyType4); + } + } + HistoricalData historicalData = new HistoricalData(historyRequestParameters3); + historicalData.Reload(); + if (historicalData.Count == 0) + { + return new List(); + } + list.Add(new ? + { + HistoricalData = historicalData, + SyntheticItem = ??.Items[i] + }); + } + List list2 = new List(); + ? ?2 = new ?(list, P_0.CancellationToken); + do + { + IHistoryItem[] array2 = new IHistoryItem[??.Items.Count]; + for (int j = 0; j < ?2.?.Count; j++) + { + array2[j] = ?2.?[j].HistoricalData[?2.?[j].Position, SeekOriginHistory.Begin]; + } + IHistoryItem historyItem = global::?.?.?(array, array2, ??.PriceModifier); + if (!(historyItem is HistoryItemBar historyItemBar)) + { + if (!(historyItem is HistoryItemTick historyItemTick)) + { + if (!(historyItem is HistoryItemLast historyItemLast)) + { + if (historyItem is HistoryItemMark historyItemMark) + { + historyItemMark.Price = base.Symbol.RoundPriceToTickSize(historyItemMark.Price); + } + } + else + { + historyItemLast.Price = base.Symbol.RoundPriceToTickSize(historyItemLast.Price); + } + } + else + { + historyItemTick.Bid = base.Symbol.RoundPriceToTickSize(historyItemTick.Bid); + historyItemTick.Ask = base.Symbol.RoundPriceToTickSize(historyItemTick.Ask); + } + } + else + { + historyItemBar.Open = base.Symbol.RoundPriceToTickSize(historyItemBar.Open); + historyItemBar.High = base.Symbol.RoundPriceToTickSize(historyItemBar.High); + historyItemBar.Low = base.Symbol.RoundPriceToTickSize(historyItemBar.Low); + historyItemBar.Close = base.Symbol.RoundPriceToTickSize(historyItemBar.Close); + } + list2.Add(historyItem); + } + while (?2.?(P_0.CancellationToken)); + list2.ProcessTickDirection(P_0.CancellationToken); + return ??.AggregateHistory(new HistoryHolder(list2, historyRequestParameters)); + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public sealed class Synthetic : CustomSymbol, ICustomizable + { + [Serializable] + [CompilerGenerated] + private new sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func, IEnumerable, IEnumerable> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func ??; + + public static Action ??; + + internal string ?(SyntheticItem P_0) + { + return P_0.Symbol.ConnectionId; + } + + internal bool ?(SyntheticItem P_0) + { + return P_0.Symbol == null; + } + + internal bool ?(SyntheticItem P_0) + { + return P_0.Symbol.State == BusinessObjectState.Fake; + } + + internal SyntheticItem ?(SyntheticItem P_0) + { + return new SyntheticItem(P_0); + } + + internal bool ?(SyntheticItem P_0) + { + return P_0.Symbol.GetAlowedOrderTypes(OrderTypeUsage.Order)?.FirstOrDefault((OrderType orderType) => orderType.Behavior == OrderTypeBehavior.Market) != null; + } + + internal bool ?(OrderType P_0) + { + return P_0.Behavior == OrderTypeBehavior.Market; + } + + internal TimeInForce[] ?(SyntheticItem P_0) + { + return P_0.Symbol.GetAlowedOrderTypes(OrderTypeUsage.Order).First((OrderType orderType) => orderType.Behavior == OrderTypeBehavior.Market).AllowedTifs; + } + + internal bool ?(OrderType P_0) + { + return P_0.Behavior == OrderTypeBehavior.Market; + } + + internal IEnumerable ?(IEnumerable P_0, IEnumerable P_1) + { + return P_0.Intersect(P_1); + } + + internal IEnumerable ?(SyntheticItem P_0) + { + return P_0.Symbol.HistoryMetadata.AllowedAggregations; + } + + internal IEnumerable ?(SyntheticItem P_0) + { + return P_0.Symbol.HistoryMetadata.AllowedPeriodsHistoryAggregationTime; + } + + internal IEnumerable ?(SyntheticItem P_0) + { + return P_0.Symbol.HistoryMetadata.AllowedHistoryTypesHistoryAggregationTime; + } + + internal IEnumerable ?(SyntheticItem P_0) + { + return P_0.Symbol.HistoryMetadata.AllowedHistoryTypesHistoryAggregationTick; + } + + internal Symbol ?(SyntheticItem P_0) + { + return P_0.Symbol; + } + + internal void ?(SyntheticItem P_0) + { + P_0.Symbol = Core.Instance.GetSymbol(P_0.Symbol.CreateInfo()); + } + } + + [CompilerGenerated] + private new sealed class ? + { + public PlaceOrderRequestParameters ??; + + public Func ??; + + internal double ?(SyntheticItem P_0) + { + return (double)((??.Side == Side.Buy) ? 1 : (-1)) * P_0.TradeRatio; + } + + internal bool ?(OrderType P_0) + { + return P_0.Behavior == ??.OrderType.Behavior; + } + } + + public const string SYNTHETIC_CONNECTION_ID = "CUSTOM_SYMBOL_CONNECTION"; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private ReadOnlyCollection ??; + + [CompilerGenerated] + private SyntheticState ??; + + [CompilerGenerated] + private SyntheticPriceModifier ??; + + [CompilerGenerated] + private bool ??; + + private List ??; + + private readonly object ??; + + private readonly ConnectionStateObserver ??; + + private bool ??; + + private bool ??; + + public override Connection Connection => Items?.FirstOrDefault()?.Symbol?.Connection; + + public override BusinessObjectState State + { + get + { + if (SyntheticState != SyntheticState.Initialized) + { + return BusinessObjectState.Fake; + } + return base.State; + } + protected internal set + { + base.State = value; + } + } + + public string[] LegsConnectionsIds => Items.Select((SyntheticItem P_0) => P_0.Symbol.ConnectionId).Distinct().ToArray(); + + public SyntheticPriceModifierType PriceModifierType + { + get + { + return PriceModifier?.Type ?? SyntheticPriceModifierType.Undefined; + } + set + { + SyntheticPriceModifier priceModifier = PriceModifier; + if (priceModifier == null || priceModifier.Type != value) + { + PriceModifier = SyntheticPriceModifier.Create(value); + } + } + } + + public ReadOnlyCollection Items + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = readOnlyCollection; + } + } + + public SyntheticState SyntheticState + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = syntheticState; + } + } + + public SyntheticPriceModifier PriceModifier + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = syntheticPriceModifier; + } + } + + public bool ForceUseTicksForHistory + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + List list = new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Name), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Id), + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)PriceModifierType), + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ForceUseTicksForHistory) + }; + if (base.Group != null) + { + list.Add(new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Group.GroupName), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Group.Id) + })); + } + for (int i = 0; i < Items.Count; i++) + { + list.Add(new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Items[i].Settings)); + } + return list; + } + set + { + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemString settingItemString) + { + base.Name = (string)settingItemString.Value; + } + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemString settingItemString2) + { + base.Id = (string)settingItemString2.Value; + } + PriceModifierType = (SyntheticPriceModifierType)value.GetValueOrDefault((int)PriceModifierType, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemBoolean settingItemBoolean) + { + ForceUseTicksForHistory = (bool)settingItemBoolean.Value; + } + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value is IEnumerable list) + { + string text = list.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value?.ToString(); + string text2 = list.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value?.ToString(); + if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2)) + { + base.Group = new SymbolGroup(base.ConnectionId); + base.Group.?(new MessageSymbolGroup + { + GroupName = text, + Id = text2 + }); + } + } + List list2 = new List(); + for (int i = 0; i < value.Count; i++) + { + if (!(value[i].Name != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + list2.Add(new SyntheticItem + { + Settings = (value[i].Value as List) + }); + } + } + Items = new ReadOnlyCollection(list2); + } + } + + public event Action Reinitialized + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public Synthetic(string name, SyntheticPriceModifierType priceModifierType) + : base(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ?? = new object(); + ?? = new List(); + ForceUseTicksForHistory = false; + PriceModifierType = priceModifierType; + Items = new ReadOnlyCollection(Array.Empty()); + SyntheticState = SyntheticState.NotInitialized; + base.Name = name; + Core.Instance.?(?); + ?? = new ConnectionStateObserver(this, ConnectionStateObserverPriority.High, ConnectionState.Connected, ConnectionState.Disconnected, ConnectionState.ConnectionLost); + } + + public Synthetic(string name, SyntheticPriceModifierType priceModifierType, IEnumerable items) + : this(name, priceModifierType) + { + Reinitialize(items); + } + + public Synthetic(string name, Synthetic origin) + : this(name, origin.PriceModifierType, origin.Items) + { + } + + public void Rename(string newName) + { + if (string.IsNullOrEmpty(newName)) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + base.Name = newName; + ???.Invoke(this); + base.?(); + } + + public void RenameGroup(string groupName) + { + if (string.IsNullOrEmpty(groupName)) + { + base.Group = null; + } + else + { + if (base.Group == null) + { + SymbolGroup symbolGroup = (base.Group = new SymbolGroup(base.ConnectionId)); + } + base.Group.?(new MessageSymbolGroup + { + GroupName = groupName, + Id = groupName, + SortIndex = 0 + }); + } + ???.Invoke(this); + base.?(); + } + + public void Reinitialize(IEnumerable newItems) + { + if (newItems == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + try + { + lock (??) + { + SyntheticState = SyntheticState.NotInitialized; + ?(); + base.?(); + MessageSymbol messageSymbol = new MessageSymbol(base.Id) + { + Name = base.Name, + SymbolType = SymbolType.Synthetic, + QuotingType = SymbolQuotingType.Undefined, + MinLot = 1.0, + LotStep = 1.0, + LotSize = 1.0, + VolumeType = SymbolVolumeType.Disable, + NettingType = NettingType.Undefined, + AllowCalculateRealtimeChange = true, + AllowCalculateRealtimeTicks = false, + AllowCalculateRealtimeTrades = false, + AllowCalculateRealtimeVolume = false + }; + ?(messageSymbol); + if (!newItems.Any() || newItems.Any((SyntheticItem P_0) => P_0.Symbol == null) || newItems.Any((SyntheticItem P_0) => P_0.Symbol.State == BusinessObjectState.Fake)) + { + return; + } + Items = new ReadOnlyCollection(newItems.Select((SyntheticItem P_0) => new SyntheticItem(P_0)).ToArray()); + StringBuilder stringBuilder = new StringBuilder(); + double num = double.MinValue; + double num2 = double.MaxValue; + bool flag = true; + bool flag2 = true; + TimeSpan timeSpan = TimeSpan.MaxValue; + double num3 = double.MaxValue; + foreach (SyntheticItem item in Items) + { + if (stringBuilder.Length < 100) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(5, 2, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(item.Symbol.FormatQuantity(item.Coefficient)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(item.Symbol.Name); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder2.Append(ref handler); + } + if (item.Symbol.MinLot > num) + { + num = item.Symbol.MinLot; + } + if (item.Symbol.MaxLot < num2) + { + num2 = item.Symbol.MaxLot; + } + if (item.Symbol.HistoryType != HistoryType.Last) + { + flag = false; + } + if (item.Symbol.HistoryType != HistoryType.Mark) + { + flag2 = false; + } + if (item.Symbol.TickSize < num3) + { + num3 = item.Symbol.TickSize; + } + if (item.Symbol.QuoteDelay < timeSpan) + { + timeSpan = item.Symbol.QuoteDelay; + } + } + if (PriceModifierType == SyntheticPriceModifierType.Ln) + { + num3 = 1E-05; + } + messageSymbol.Description = stringBuilder.ToString().TrimEnd('+', ' '); + messageSymbol.QuoteDelay = timeSpan; + messageSymbol.VariableTickList = new List + { + new VariableTick(num3) + }; + messageSymbol.MaxLot = Math.Floor(num2); + messageSymbol.HistoryType = (flag ? HistoryType.Last : (flag2 ? HistoryType.Mark : HistoryType.Bid)); + ?(messageSymbol); + bool flag3 = true; + flag3 = Items.All((SyntheticItem P_0) => P_0.Symbol.GetAlowedOrderTypes(OrderTypeUsage.Order)?.FirstOrDefault((OrderType orderType) => orderType.Behavior == OrderTypeBehavior.Market) != null); + if (((?)this).Rules[3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()] is ? ?) + { + ?.?(new MessageRule + { + Value = flag3 + }); + } + if (flag3) + { + TimeInForce[] source = Items.Select((SyntheticItem P_0) => P_0.Symbol.GetAlowedOrderTypes(OrderTypeUsage.Order).First((OrderType orderType) => orderType.Behavior == OrderTypeBehavior.Market).AllowedTifs).Cast>().Aggregate((IEnumerable P_0, IEnumerable P_1) => P_0.Intersect(P_1)) + .ToArray(); + if (!source.Any()) + { + source = new TimeInForce[1]; + } + ?? = new List + { + new MarketOrderType(source.ToArray()) + }; + } + else + { + ?? = new List + { + new MarketOrderType(default(TimeInForce)) + }; + } + historyMetadata = new HistoryMetadata + { + AllowedAggregations = Items.SelectMany((SyntheticItem P_0) => P_0.Symbol.HistoryMetadata.AllowedAggregations).Distinct().ToArray(), + AllowedPeriodsHistoryAggregationTime = Items.SelectMany((SyntheticItem P_0) => P_0.Symbol.HistoryMetadata.AllowedPeriodsHistoryAggregationTime).Distinct().ToArray(), + AllowedHistoryTypesHistoryAggregationTime = Items.SelectMany((SyntheticItem P_0) => P_0.Symbol.HistoryMetadata.AllowedHistoryTypesHistoryAggregationTime).Distinct().ToArray(), + AllowedHistoryTypesHistoryAggregationTick = Items.SelectMany((SyntheticItem P_0) => P_0.Symbol.HistoryMetadata.AllowedHistoryTypesHistoryAggregationTick).Distinct().ToArray() + }; + foreach (SyntheticItem item2 in Items) + { + item2.Symbol.NewQuote += ?; + item2.Symbol.NewLast += ?; + item2.Symbol.NewMark += ?; + item2.Symbol.NewLevel2 += ?; + item2.Symbol.NewDayBar += ?; + } + ?(); + SyntheticState = SyntheticState.Initialized; + ?? = true; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public override void Dispose() + { + ??.Dispose(); + ?(); + SyntheticState = SyntheticState.NotInitialized; + base.Dispose(); + } + + private new void ?() + { + try + { + foreach (SyntheticItem item in Items) + { + item.Symbol.NewQuote -= ?; + item.Symbol.NewLast -= ?; + item.Symbol.NewMark -= ?; + item.Symbol.NewLevel2 -= ?; + item.Symbol.NewDayBar -= ?; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + protected internal override void SubscribeAction(SubscribeQuoteType type) + { + } + + protected internal override void UnSubscribeAction(SubscribeQuoteType type) + { + } + + private new void ?() + { + try + { + ReadOnlyCollection items = Items; + if (items != null && items.Count == 0) + { + return; + } + int count = Items.Count; + double[] array = new double[count]; + Level2Item[][] array2 = new Level2Item[count][]; + Level2Item[][] array3 = new Level2Item[count][]; + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + for (int i = 0; i < Items.Count; i++) + { + SyntheticItem syntheticItem = Items[i]; + SessionsContainer currentSessionsInfo = syntheticItem.Symbol.CurrentSessionsInfo; + if (currentSessionsInfo != null && !currentSessionsInfo.ContainsDate(dateTimeUtcNow)) + { + return; + } + array[i] = syntheticItem.Coefficient; + DepthOfMarketAggregatedCollections depthOfMarketAggregatedCollections = syntheticItem.Symbol.DepthOfMarket.GetDepthOfMarketAggregatedCollections(); + if (syntheticItem.Coefficient > 0.0) + { + array3[i] = new Level2Item[depthOfMarketAggregatedCollections.Bids.Length]; + for (int j = 0; j < depthOfMarketAggregatedCollections.Bids.Length; j++) + { + array3[i][j] = depthOfMarketAggregatedCollections.Bids[j]; + } + } + else + { + array3[i] = new Level2Item[depthOfMarketAggregatedCollections.Asks.Length]; + for (int k = 0; k < depthOfMarketAggregatedCollections.Asks.Length; k++) + { + array3[i][k] = depthOfMarketAggregatedCollections.Asks[k]; + } + } + if (syntheticItem.Coefficient > 0.0) + { + array2[i] = new Level2Item[depthOfMarketAggregatedCollections.Asks.Length]; + for (int l = 0; l < depthOfMarketAggregatedCollections.Asks.Length; l++) + { + array2[i][l] = depthOfMarketAggregatedCollections.Asks[l]; + } + } + else + { + array2[i] = new Level2Item[depthOfMarketAggregatedCollections.Bids.Length]; + for (int m = 0; m < depthOfMarketAggregatedCollections.Bids.Length; m++) + { + array2[i][m] = depthOfMarketAggregatedCollections.Bids[m]; + } + } + } + (Level2Quote[], DateTime) tuple = global::?.?.?(array, QuotePriceType.Bid, base.Id, array3, PriceModifier); + (Level2Quote[], DateTime) tuple2 = global::?.?.?(array, QuotePriceType.Ask, base.Id, array2, PriceModifier); + DOMQuote dOMQuote = new DOMQuote(base.Id, dateTimeUtcNow); + Level2Quote[] item = tuple.Item1; + foreach (Level2Quote level2Quote in item) + { + dOMQuote.Bids.Add(new Level2Quote(level2Quote.PriceType, level2Quote.SymbolId, level2Quote.Id, RoundPriceToTickSize(level2Quote.Price), level2Quote.Size, level2Quote.Time)); + } + item = tuple2.Item1; + foreach (Level2Quote level2Quote2 in item) + { + dOMQuote.Asks.Add(new Level2Quote(level2Quote2.PriceType, level2Quote2.SymbolId, level2Quote2.Id, RoundPriceToTickSize(level2Quote2.Price), level2Quote2.Size, level2Quote2.Time)); + } + ?(dOMQuote); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + private void ?() + { + ReadOnlyCollection items = Items; + if (items == null || items.Count != 0) + { + int count = Items.Count; + double[] array = new double[count]; + double[] array2 = new double[count]; + double[] array3 = new double[count]; + double[] array4 = new double[count]; + double[] array5 = new double[count]; + DateTime[] array6 = new DateTime[count]; + for (int i = 0; i < Items.Count; i++) + { + SyntheticItem syntheticItem = Items[i]; + array[i] = syntheticItem.Coefficient; + array2[i] = syntheticItem.Symbol.Open; + array3[i] = syntheticItem.Symbol.High; + array4[i] = syntheticItem.Symbol.Low; + array5[i] = syntheticItem.Symbol.PrevClose; + array6[i] = syntheticItem.Symbol.QuoteDateTime; + } + (double, double, double, double, DateTime) tuple = global::?.?.?(array, array2, array3, array4, array5, array6, PriceModifier); + DayBar dayBar = new DayBar(base.Name, tuple.Item5) + { + Open = tuple.Item1, + High = tuple.Item2, + Low = tuple.Item3, + PreviousClose = tuple.Item4 + }; + ?(dayBar); + } + } + + private void ?() + { + ReadOnlyCollection items = Items; + if (items == null || items.Count != 0) + { + int count = Items.Count; + double[] array = new double[count]; + double[] array2 = new double[count]; + double[] array3 = new double[count]; + double[] array4 = new double[count]; + double[] array5 = new double[count]; + double[] array6 = new double[count]; + double[] array7 = new double[count]; + double[] array8 = new double[count]; + double[] array9 = new double[count]; + double[] array10 = new double[count]; + double[] array11 = new double[count]; + double[] array12 = new double[count]; + double[] array13 = new double[count]; + DateTime[] array14 = new DateTime[count]; + for (int i = 0; i < Items.Count; i++) + { + SyntheticItem syntheticItem = Items[i]; + array[i] = syntheticItem.Coefficient; + array2[i] = syntheticItem.Symbol.Ask; + array3[i] = syntheticItem.Symbol.Bid; + array4[i] = syntheticItem.Symbol.AskSize; + array5[i] = syntheticItem.Symbol.BidSize; + array6[i] = syntheticItem.Symbol.Last; + array7[i] = syntheticItem.Symbol.LastSize; + array8[i] = syntheticItem.Symbol.Mark; + array9[i] = syntheticItem.Symbol.MarkSize; + array10[i] = syntheticItem.Symbol.Open; + array11[i] = syntheticItem.Symbol.High; + array12[i] = syntheticItem.Symbol.Low; + array13[i] = syntheticItem.Symbol.PrevClose; + array14[i] = syntheticItem.Symbol.QuoteDateTime; + } + (double, double, double, double, DateTime) tuple = global::?.?.?(array, array2, array3, array4, array5, array14, PriceModifier); + (double, double, DateTime) tuple2 = global::?.?.?(array, array6, array7, array14, PriceModifier); + (double, double, DateTime) tuple3 = global::?.?.?(array, array8, array9, array14, PriceModifier); + (double, double, double, double, DateTime) tuple4 = global::?.?.?(array, array10, array11, array12, array13, array14, PriceModifier); + DayBar obj = new DayBar(base.Name, tuple.Item5) + { + Bid = tuple.Item2, + BidSize = tuple.Item4 + }; + (obj.Ask, _, obj.AskSize, _, _) = tuple; + (obj.Last, obj.LastSize, _) = tuple2; + (obj.Mark, obj.MarkSize, _) = tuple3; + (obj.Open, obj.High, obj.Low, obj.PreviousClose, _) = tuple4; + ?(obj); + } + } + + private void ?() + { + if (SyntheticState == SyntheticState.Initialized) + { + if (??) + { + ?? = false; + ?(); + } + if (??) + { + ?? = false; + ?(); + } + } + } + + private void ?(Symbol P_0, Last P_1) + { + if (SyntheticState == SyntheticState.NotInitialized) + { + return; + } + int count = Items.Count; + double[] array = new double[count]; + double[] array2 = new double[count]; + double[] array3 = new double[count]; + DateTime[] array4 = new DateTime[count]; + for (int i = 0; i < Items.Count; i++) + { + SyntheticItem syntheticItem = Items[i]; + array[i] = syntheticItem.Coefficient; + array2[i] = syntheticItem.Symbol.Last; + array3[i] = syntheticItem.Symbol.LastSize; + array4[i] = syntheticItem.Symbol.LastDateTime; + SessionsContainer currentSessionsInfo = syntheticItem.Symbol.CurrentSessionsInfo; + if (currentSessionsInfo != null && !currentSessionsInfo.ContainsDate(array4[i])) + { + return; + } + } + (double, double, DateTime) tuple = global::?.?.?(array, array2, array3, array4, PriceModifier); + if (!tuple.Item1.IsNanOrDefault()) + { + tuple.Item1 = RoundPriceToTickSize(tuple.Item1); + Last last = new Last(base.Name, tuple.Item1, tuple.Item2, tuple.Item3) + { + AggressorFlag = AggressorFlag.NotSet + }; + ?(last); + } + } + + private void ?(Symbol P_0, Mark P_1) + { + if (SyntheticState == SyntheticState.NotInitialized) + { + return; + } + int count = Items.Count; + double[] array = new double[count]; + double[] array2 = new double[count]; + double[] array3 = new double[count]; + DateTime[] array4 = new DateTime[count]; + for (int i = 0; i < Items.Count; i++) + { + SyntheticItem syntheticItem = Items[i]; + array[i] = syntheticItem.Coefficient; + array2[i] = syntheticItem.Symbol.Mark; + array3[i] = syntheticItem.Symbol.MarkSize; + array4[i] = syntheticItem.Symbol.LastDateTime; + SessionsContainer currentSessionsInfo = syntheticItem.Symbol.CurrentSessionsInfo; + if (currentSessionsInfo != null && !currentSessionsInfo.ContainsDate(array4[i])) + { + return; + } + } + (double, double, DateTime) tuple = global::?.?.?(array, array2, array3, array4, PriceModifier); + if (tuple.Item1 != 0.0) + { + tuple.Item1 = RoundPriceToTickSize(tuple.Item1); + Mark mark = new Mark(base.Name, tuple.Item3, tuple.Item1, tuple.Item2); + ?(mark); + } + } + + private void ?(Symbol P_0, Quote P_1) + { + if (SyntheticState == SyntheticState.NotInitialized) + { + return; + } + int count = Items.Count; + double[] array = new double[count]; + double[] array2 = new double[count]; + double[] array3 = new double[count]; + double[] array4 = new double[count]; + double[] array5 = new double[count]; + DateTime[] array6 = new DateTime[count]; + for (int i = 0; i < Items.Count; i++) + { + SyntheticItem syntheticItem = Items[i]; + array[i] = syntheticItem.Coefficient; + array2[i] = syntheticItem.Symbol.Ask; + array3[i] = syntheticItem.Symbol.Bid; + array4[i] = syntheticItem.Symbol.AskSize; + array5[i] = syntheticItem.Symbol.BidSize; + array6[i] = syntheticItem.Symbol.QuoteDateTime; + SessionsContainer currentSessionsInfo = syntheticItem.Symbol.CurrentSessionsInfo; + if (currentSessionsInfo != null && !currentSessionsInfo.ContainsDate(array6[i])) + { + return; + } + } + (double, double, double, double, DateTime) tuple = global::?.?.?(array, array2, array3, array4, array5, array6, PriceModifier); + if (!tuple.Item2.IsNanOrDefault() || !tuple.Item1.IsNanOrDefault()) + { + tuple.Item2 = RoundPriceToTickSize(tuple.Item2); + tuple.Item1 = RoundPriceToTickSize(tuple.Item1); + Quote quote = new Quote(base.Name, tuple.Item2, tuple.Item4, tuple.Item1, tuple.Item3, tuple.Item5); + ?(quote); + } + } + + private void ?(Symbol P_0, Level2Quote P_1, DOMQuote P_2) + { + ?? = true; + } + + private void ?(Symbol P_0, DayBar P_1) + { + ?? = true; + } + + private protected override HistoricalData ?(HistoryRequestParameters P_0) + { + return new ?(P_0); + } + + public override List GetAlowedOrderTypes(OrderTypeUsage? usage) + { + return ??; + } + + public override bool IsTradingAllowed(Account account) + { + foreach (Symbol item in Items.Select((SyntheticItem P_0) => P_0.Symbol)) + { + Account account2 = item.Connection?.BusinessObjects?.Accounts?.FirstOrDefault(); + if (account2 == null) + { + return false; + } + if (!item.IsTradingAllowed(account2)) + { + return false; + } + } + return true; + } + + internal override TradingOperationResult ?(PlaceOrderRequestParameters P_0) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.OrderTypeId != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return TradingOperationResult.CreateError(P_0.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + List list = Items.OrderByDescending((SyntheticItem syntheticItem2) => (double)((P_0.Side == Side.Buy) ? 1 : (-1)) * syntheticItem2.TradeRatio).ToList(); + for (int num = 0; num < list.Count; num++) + { + SyntheticItem syntheticItem = list[num]; + Symbol symbol = syntheticItem.Symbol; + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters(P_0) + { + Symbol = symbol, + Account = ((LegsConnectionsIds.Length > 1) ? symbol.Connection.BusinessObjects.Accounts[0] : P_0.Account) + }; + OrderType orderType = syntheticItem.Symbol.GetAlowedOrderTypes(OrderTypeUsage.Order).FirstOrDefault((OrderType orderType2) => orderType2.Behavior == P_0.OrderType.Behavior); + if (orderType == null) + { + return TradingOperationResult.CreateError(P_0.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + placeOrderRequestParameters.OrderTypeId = orderType.Id; + placeOrderRequestParameters.Quantity = (double)Math.Abs((decimal)placeOrderRequestParameters.Quantity * (decimal)syntheticItem.TradeRatio); + if ((P_0.Side == Side.Buy && syntheticItem.TradeRatio > 0.0) || (P_0.Side == Side.Sell && syntheticItem.TradeRatio < 0.0)) + { + placeOrderRequestParameters.Side = Side.Buy; + } + else + { + placeOrderRequestParameters.Side = Side.Sell; + } + if (!string.IsNullOrEmpty(syntheticItem.TradeComment)) + { + placeOrderRequestParameters.Comment = syntheticItem.TradeComment; + } + TradingOperationResult tradingOperationResult = syntheticItem.Symbol.?(placeOrderRequestParameters); + if (tradingOperationResult.Status == TradingOperationResultStatus.Failure) + { + return tradingOperationResult; + } + } + return TradingOperationResult.CreateSuccess(P_0.RequestId); + } + + public override Account GetDefaultAccount(Account currentValue = null) + { + if (LegsConnectionsIds.Length != 1) + { + return null; + } + if (currentValue?.ConnectionId == Items[0].Symbol.ConnectionId) + { + return currentValue; + } + return Core.Instance.Connections[Items[0].Symbol.ConnectionId]?.BusinessObjects?.Accounts?.FirstOrDefault(); + } + + public override string FormatQuantity(double quantity, bool inLots = true, bool abbreviate = false) + { + int valuePrecision = CoreMath.GetValuePrecision((decimal)quantity); + return quantity.Format(valuePrecision, abbreviate); + } + + public override ConnectionDependency GetConnectionStateDependency() + { + return new ConnectionDependency + { + Behavior = ConnectionDependencyBehavior.PartialDependency, + DependentConnectionsIds = LegsConnectionsIds + }; + } + + public override void OnConnectionStateChanged(Connection connection, ConnectionStateChangedEventArgs e) + { + List list = Items.ToList(); + list.ForEach(delegate(SyntheticItem P_0) + { + P_0.Symbol = Core.Instance.GetSymbol(P_0.Symbol.CreateInfo()); + }); + Reinitialize(list); + } + } + public enum SyntheticState + { + NotInitialized, + Initialized + } +} +namespace ? +{ + internal static class ? + { + internal class ? + { + private readonly List ??; + + private int ??; + + private double ??; + + private bool HasNextLevel => ?? < ??.Count - 1; + + public double PriceOnCurrentLevel + { + get + { + if (?? >= ??.Count) + { + return 0.0; + } + return ??[??].Price; + } + } + + public double SizeOnCurrentLevel + { + get + { + if (?? >= ??.Count) + { + return 0.0; + } + return ??[??].Size - ??; + } + } + + public ?(Level2Item[] P_0) + { + ?? = new List(P_0); + } + + public bool ?(double P_0) + { + double num = P_0; + do + { + if (SizeOnCurrentLevel > num) + { + ?? += num; + num = 0.0; + continue; + } + num -= SizeOnCurrentLevel; + if (HasNextLevel) + { + ??++; + ?? = 0.0; + continue; + } + return false; + } + while (num > 0.0); + return true; + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal double ?(? P_0) + { + return P_0.SizeOnCurrentLevel; + } + } + + public static (double ask, double bid, double askSize, double BidSize, DateTime QuoteDateTime) ?(double[] P_0, double[] P_1, double[] P_2, double[] P_3, double[] P_4, DateTime[] P_5, SyntheticPriceModifier P_6) + { + if (P_0 == null || P_0.Length == 0) + { + return (ask: double.NaN, bid: double.NaN, askSize: double.NaN, BidSize: double.NaN, QuoteDateTime: DateTime.MinValue); + } + double num = 0.0; + double num2 = 0.0; + double num3 = P_3[0]; + double num4 = P_4[0]; + DateTime dateTime = P_5[0]; + for (int i = 0; i < P_0.Length; i++) + { + if (P_1[i].IsNanOrDefault() && P_2[i].IsNanOrDefault()) + { + return (ask: double.NaN, bid: double.NaN, askSize: double.NaN, BidSize: double.NaN, QuoteDateTime: DateTime.MinValue); + } + num += P_6.CalculatePrice(P_0[i], (P_0[i] > 0.0) ? P_1[i] : P_2[i]); + num2 += P_6.CalculatePrice(P_0[i], (P_0[i] > 0.0) ? P_2[i] : P_1[i]); + if (P_0[i] > 0.0) + { + if (P_3[i] < num3) + { + num3 = P_3[i]; + } + if (P_4[i] < num4) + { + num4 = P_4[i]; + } + } + else + { + if (P_3[i] < num4) + { + num4 = P_3[i]; + } + if (P_4[i] < num3) + { + num3 = P_4[i]; + } + } + if (P_5[i] > dateTime) + { + dateTime = P_5[i]; + } + } + return (ask: num, bid: num2, askSize: num3, BidSize: num4, QuoteDateTime: dateTime); + } + + public static (double last, double lastSize, DateTime LastDateTime) ?(double[] P_0, double[] P_1, double[] P_2, DateTime[] P_3, SyntheticPriceModifier P_4) + { + if (P_0 == null || P_0.Length == 0) + { + return (last: double.NaN, lastSize: double.NaN, LastDateTime: DateTime.MinValue); + } + double num = 0.0; + double num2 = P_2[0]; + DateTime dateTime = P_3[0]; + for (int i = 0; i < P_0.Length; i++) + { + if (P_1[i].IsNanOrDefault()) + { + return (last: double.NaN, lastSize: double.NaN, LastDateTime: DateTime.MinValue); + } + num += P_4.CalculatePrice(P_0[i], P_1[i]); + if (P_2[i] < num2) + { + num2 = P_2[i]; + } + if (P_3[i] > dateTime) + { + dateTime = P_3[i]; + } + } + return (last: num, lastSize: num2, LastDateTime: dateTime); + } + + public static (double mark, double markSize, DateTime markDateTime) ?(double[] P_0, double[] P_1, double[] P_2, DateTime[] P_3, SyntheticPriceModifier P_4) + { + if (P_0 == null || P_0.Length == 0) + { + return (mark: double.NaN, markSize: double.NaN, markDateTime: DateTime.MinValue); + } + double num = 0.0; + double num2 = P_2[0]; + DateTime dateTime = P_3[0]; + for (int i = 0; i < P_0.Length; i++) + { + if (P_1[i].IsNanOrDefault()) + { + return (mark: double.NaN, markSize: double.NaN, markDateTime: DateTime.MinValue); + } + num += P_4.CalculatePrice(P_0[i], P_1[i]); + if (P_2[i] < num2) + { + num2 = P_2[i]; + } + if (P_3[i] > dateTime) + { + dateTime = P_3[i]; + } + } + return (mark: num, markSize: num2, markDateTime: dateTime); + } + + public static (Level2Quote[] quotes, DateTime Time) ?(double[] P_0, QuotePriceType P_1, string P_2, Level2Item[][] P_3, SyntheticPriceModifier P_4) + { + try + { + if (P_3 == null) + { + return (quotes: null, Time: DateTime.MinValue); + } + ?[] array = new ?[P_0.Length]; + for (int i = 0; i < array.Length; i++) + { + array[i] = new ?(P_3[i]); + } + List list = new List(); + bool flag = false; + do + { + double num = 0.0; + for (int j = 0; j < P_0.Length; j++) + { + num += P_4.CalculatePrice(P_0[j], array[j].PriceOnCurrentLevel); + } + double num2 = array.Min((? ?2) => ?2.SizeOnCurrentLevel); + list.Add(new Level2Quote(P_1, P_2, P_1.ToString() + list.Count, num, num2, Core.Instance.TimeUtils.DateTimeUtcNow)); + ?[] array2 = array; + for (int num3 = 0; num3 < array2.Length; num3++) + { + if (!array2[num3].?(num2)) + { + flag = true; + break; + } + } + } + while (!flag); + return (quotes: list.ToArray(), Time: DateTime.MinValue); + } + catch + { + return (quotes: null, Time: DateTime.MinValue); + } + } + + public static (double open, double high, double low, double close, DateTime QuoteDateTime) ?(double[] P_0, double[] P_1, double[] P_2, double[] P_3, double[] P_4, DateTime[] P_5, SyntheticPriceModifier P_6) + { + if (P_0 == null || P_0.Length == 0) + { + return (open: 0.0, high: 0.0, low: 0.0, close: 0.0, QuoteDateTime: DateTime.MinValue); + } + double num = 0.0; + double num2 = 0.0; + double num3 = 0.0; + double num4 = 0.0; + DateTime dateTime = P_5[0]; + for (int i = 0; i < P_0.Length; i++) + { + num += P_6.CalculatePrice(P_0[i], P_1[i]); + num2 += P_6.CalculatePrice(P_0[i], P_2[i]); + num3 += P_6.CalculatePrice(P_0[i], P_3[i]); + num4 += P_6.CalculatePrice(P_0[i], P_4[i]); + if (P_5[i] > dateTime) + { + dateTime = P_5[i]; + } + } + return (open: num, high: num2, low: num3, close: num4, QuoteDateTime: dateTime); + } + + public static IHistoryItem ?(double[] P_0, IHistoryItem[] P_1, SyntheticPriceModifier P_2) + { + if (P_1 == null) + { + return null; + } + if (P_1.Length == 0) + { + return null; + } + IHistoryItem historyItem = P_1[0]; + if (!(historyItem is HistoryItemBar)) + { + if (!(historyItem is HistoryItemTick)) + { + if (historyItem is HistoryItemLast) + { + double num = 0.0; + double volume = 0.0; + long num2 = long.MinValue; + for (int i = 0; i < P_0.Length; i++) + { + HistoryItemLast historyItemLast = (HistoryItemLast)P_1[i]; + num += P_2.CalculatePrice(P_0[i], historyItemLast.Price); + if (historyItemLast.TicksLeft > num2) + { + num2 = historyItemLast.TicksLeft; + } + } + return new HistoryItemLast + { + Price = num, + Volume = volume, + TicksLeft = num2 + }; + } + return null; + } + double num3 = 0.0; + double num4 = 0.0; + double bidSize = 0.0; + double askSize = 0.0; + long num5 = long.MinValue; + for (int j = 0; j < P_0.Length; j++) + { + HistoryItemTick historyItemTick = (HistoryItemTick)P_1[j]; + num3 += P_2.CalculatePrice(P_0[j], (P_0[j] > 0.0) ? historyItemTick.Bid : historyItemTick.Ask); + num4 += P_2.CalculatePrice(P_0[j], (P_0[j] > 0.0) ? historyItemTick.Ask : historyItemTick.Bid); + if (historyItemTick.TicksLeft > num5) + { + num5 = historyItemTick.TicksLeft; + } + } + return new HistoryItemTick + { + Bid = num3, + Ask = num4, + AskSize = askSize, + BidSize = bidSize, + TicksLeft = num5 + }; + } + double num6 = 0.0; + double num7 = 0.0; + double num8 = 0.0; + double num9 = 0.0; + double volume2 = 0.0; + int num10 = 0; + long num11 = long.MinValue; + long ticksRight = long.MinValue; + for (int k = 0; k < P_0.Length; k++) + { + HistoryItemBar historyItemBar = (HistoryItemBar)P_1[k]; + num6 += P_2.CalculatePrice(P_0[k], historyItemBar.Open); + num8 += P_2.CalculatePrice(P_0[k], historyItemBar.High); + num9 += P_2.CalculatePrice(P_0[k], historyItemBar.Low); + num7 += P_2.CalculatePrice(P_0[k], historyItemBar.Close); + if (historyItemBar.TicksLeft > num11) + { + num11 = historyItemBar.TicksLeft; + ticksRight = historyItemBar.TicksRight; + } + } + double[] source = new double[4] { num6, num8, num9, num7 }; + return new HistoryItemBar + { + Open = num6, + High = source.Max(), + Low = source.Min(), + Close = num7, + Volume = volume2, + Ticks = num10, + TicksLeft = num11, + TicksRight = ticksRight + }; + } + } + internal class ? + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Predicate ??; + + internal bool ?(ISyntheticSynhroniserItem P_0) + { + return P_0.Position == -1; + } + } + + public List ?; + + private bool ?; + + public ?(List P_0, CancellationToken P_1) + { + ? = P_0; + ? = P_0.Count > 0 && P_0[0].HistoricalData?.Aggregation is HistoryAggregationTime { Period: var period } && period.BasePeriod >= BasePeriod.Day; + while (?(P_1) && ?.Exists((ISyntheticSynhroniserItem syntheticSynhroniserItem) => syntheticSynhroniserItem.Position == -1)) + { + } + } + + public bool ?(CancellationToken P_0) + { + foreach (ISyntheticSynhroniserItem item in ?) + { + if (P_0.IsCancellationRequested) + { + return false; + } + long nextPositionTime = item.NextPositionTime; + if (nextPositionTime < 0) + { + continue; + } + foreach (ISyntheticSynhroniserItem item2 in ?) + { + if (P_0.IsCancellationRequested) + { + return false; + } + while (true) + { + nextPositionTime = item.NextPositionTime; + if (nextPositionTime < 0 || ? || (item2.SyntheticItem?.Symbol.CurrentSessionsInfo?.ContainsDate(nextPositionTime) ?? true)) + { + break; + } + if (P_0.IsCancellationRequested) + { + return false; + } + item.Move(); + } + } + } + long num = long.MaxValue; + for (int i = 0; i < ?.Count; i++) + { + if (P_0.IsCancellationRequested) + { + return false; + } + long nextPositionTime2 = ?[i].NextPositionTime; + if (nextPositionTime2 > 0 && nextPositionTime2 < num) + { + num = nextPositionTime2; + } + } + if (num == long.MaxValue) + { + return false; + } + bool result = false; + foreach (ISyntheticSynhroniserItem item3 in ?) + { + if (P_0.IsCancellationRequested) + { + return false; + } + if (item3.NextPositionTime == num) + { + item3.Move(); + result = true; + } + } + return result; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public interface ISyntheticSynhroniserItem + { + SyntheticItem SyntheticItem { get; set; } + + HistoricalData HistoricalData { get; set; } + + int Position { get; } + + long NextPositionTime { get; } + + void Move(); + } +} +namespace ? +{ + internal class ? : ISyntheticSynhroniserItem + { + [CompilerGenerated] + private SyntheticItem ??; + + [CompilerGenerated] + private HistoricalData ??; + + [CompilerGenerated] + private int ??; + + public SyntheticItem SyntheticItem + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoricalData HistoricalData + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Position + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public long NextPositionTime + { + get + { + if (Position < HistoricalData.Count - 1) + { + return HistoricalData[Position + 1, SeekOriginHistory.Begin].TicksLeft; + } + return -1L; + } + } + + public ?() + { + Position = -1; + } + + public void Move() + { + Position++; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public sealed class SyntheticItem : ICloneable, ICustomizable + { + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Coefficient + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TradeRatio + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string TradeComment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Symbol), + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Coefficient), + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TradeRatio) + }; + } + set + { + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemSymbol settingItemSymbol) + { + Symbol = settingItemSymbol.Value as Symbol; + } + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemDouble settingItemDouble) + { + Coefficient = (double)settingItemDouble.Value; + } + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemDouble settingItemDouble2) + { + TradeRatio = (double)settingItemDouble2.Value; + } + } + } + + public SyntheticItem() + { + Coefficient = 1.0; + TradeRatio = 1.0; + TradeComment = null; + } + + public SyntheticItem(SyntheticItem syntheticItem) + { + Symbol = syntheticItem.Symbol; + Coefficient = syntheticItem.Coefficient; + TradeRatio = syntheticItem.TradeRatio; + TradeComment = syntheticItem.TradeComment; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 2); + defaultInterpolatedStringHandler.AppendFormatted(Coefficient); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Symbol?.Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public object Clone() + { + return new SyntheticItem(this); + } + } + public sealed class DeliveredAsset : TradingObject, IMessageBuilder + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private Action ??; + + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public string Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public DateTime CreationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Will be triggered on each invocation + /// + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + internal DeliveredAsset(string P_0) + : base(P_0) + { + } + + internal void ?(MessageOpenDeliveredAsset P_0) + { + base.Id = P_0.Id; + if (ConnectionCache != null && ConnectionCache.SymbolsCache.?(P_0.SymbolId, out var symbol)) + { + base.Symbol = symbol; + } + if (ConnectionCache != null && ConnectionCache.AccountsCache.?(P_0.AccountId, out var account)) + { + base.Account = account; + } + Quantity = P_0.Quantity; + Status = P_0.Status; + CreationTime = P_0.CreationTime; + ProcessAdditionalItems(P_0.AdditionalInfoItems); + ???.Invoke(this); + } + + public MessageOpenDeliveredAsset BuildMessage() + { + return new MessageOpenDeliveredAsset + { + Id = base.Id, + AccountId = base.Account?.Id, + SymbolId = base.Symbol?.Id, + Quantity = Quantity, + Status = Status, + CreationTime = CreationTime + }; + } + } + /// + /// Contains all information which belong to the given exchange + /// + [Published] + public sealed class Exchange : BusinessObject, IComparable, IMessageBuilder + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + private string ??; + + /// + /// Gets Exchange Id + /// + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets Exchange name + /// + public string ExchangeName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Used for the Exchanges comparing + /// + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + internal SessionsContainer CurrentSessionsInfo + { + get + { + if (string.IsNullOrEmpty(??)) + { + return null; + } + ConnectionCache.TradingSessions.TryGetValue(??, out var value); + return value; + } + } + + public ExchangeComplexIdentifier ComplexId => new ExchangeComplexIdentifier(base.ConnectionId, Id); + + internal Exchange(string P_0) + : base(P_0) + { + } + + internal void ?(MessageExchange P_0) + { + Id = P_0.Id; + ExchangeName = P_0.ExchangeName; + SortIndex = P_0.SortIndex; + ?? = P_0.SessionsContainerId; + } + + private MessageExchange ?() + { + return new MessageExchange + { + Id = Id, + ExchangeName = ExchangeName, + SortIndex = SortIndex, + SessionsContainerId = ?? + }; + } + + MessageExchange IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + /// + /// Compares Exchnges in order by next - SortIndex, Exchange name, Connection Id, Exchange Id. + /// + /// + /// + [NotPublished] + public int CompareTo(object obj) + { + if (!(obj is Exchange exchange)) + { + return 1; + } + int num = SortIndex.CompareTo(exchange.SortIndex); + if (num != 0) + { + return num; + } + num = ExchangeName.CompareTo(exchange.ExchangeName); + if (num != 0) + { + return num; + } + num = base.ConnectionId.CompareTo(exchange.ConnectionId); + if (num != 0) + { + return num; + } + return Id.CompareTo(exchange.Id); + } + + public override string ToString() + { + return ExchangeName ?? Id.ToString() ?? base.ToString(); + } + } + /// + /// Provides possibility to group and sort symbols for each connection + /// + [Published] + [DataContract(Name = "InstrumentGroup", Namespace = "TradingPlatform")] + public class SymbolGroup : BusinessObject + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + /// + /// Gets group Id + /// + [DataMember(Name = "GroupId")] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets group name + /// + [DataMember(Name = "GroupName")] + public string GroupName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets sort index for comparing process + /// + [DataMember(Name = "SortIndex")] + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + internal SymbolGroup(string P_0) + : base(P_0) + { + } + + internal void ?(MessageSymbolGroup P_0) + { + Id = P_0.Id; + GroupName = P_0.GroupName; + SortIndex = P_0.SortIndex; + } + } + public sealed class NewsArticle : BusinessObject + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal bool ?(Symbol P_0) + { + return P_0 != null; + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IEnumerable ??; + + private string[] ??; + + private bool ??; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public DateTime CreationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public string Title + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string SourceLink + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Category + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public IEnumerable Symbols + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + public bool NeedToLoadSymbols + { + get + { + if (?? != null) + { + return ??.Any(); + } + return false; + } + } + + internal NewsArticle(string P_0) + : base(P_0) + { + Symbols = new Symbol[0]; + ?? = new string[0]; + } + + internal void ?(MessageNewsHeadline P_0) + { + Id = P_0.Id; + CreationDate = P_0.CreationDate; + Title = P_0.Title; + SourceLink = P_0.SourceLink; + Category = P_0.Category; + if (P_0.SymbolsIds != null && P_0.SymbolsIds.Any()) + { + ?? = P_0.SymbolsIds.ToArray(); + } + } + + public void LoadSymbols() + { + if (??) + { + return; + } + ?? = true; + if (!NeedToLoadSymbols) + { + return; + } + try + { + Symbols = (from P_0 in ?? + select Connection.?(new GetSymbolRequestParameters + { + SymbolId = P_0 + }) into P_0 + where P_0 != null + select P_0).ToArray(); + ?? = null; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?? = false; + } + } + + [CompilerGenerated] + private Symbol ?(string P_0) + { + return Connection.?(new GetSymbolRequestParameters + { + SymbolId = P_0 + }); + } + } + /// + /// Represents trading information about pending order + /// + [DataContract(Name = "Order", Namespace = "TradingPlatform")] + [Published] + public class Order : TradingObject, IMessageBuilder, IOrder, ITradingObject, IUniqueID, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private OrderStatus ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private TimeInForce ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private SlTpHolder[] ??; + + [CompilerGenerated] + private SlTpHolder[] ??; + + [CompilerGenerated] + private Action ??; + + /// + /// The ID of the order group. This group created when trades done by the MAM account. + /// + [DataMember(Name = "GroupId")] + public string GroupId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets Position Id. + /// + [DataMember(Name = "PositionId")] + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Total quantity of the order + /// + [DataMember(Name = "TotalQuantity")] + public double TotalQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Filled quantity of the order + /// + [DataMember(Name = "FilledQuantity")] + public double FilledQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Remaining quantity of the order + /// + public double RemainingQuantity => TotalQuantity - FilledQuantity; + + /// + /// Orders Type Id. It is used for the orders type comparing. + /// + [DataMember(Name = "OrderTypeId")] + public string OrderTypeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets OrderType + /// + public OrderType OrderType => ConnectionCache.OrderTypes.FirstOrDefault((OrderType P_0) => P_0.Id == OrderTypeId); + + /// + /// Gets order price value + /// + [DataMember(Name = "Price")] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets order trigger price value + /// + [DataMember(Name = "TriggerPrice")] + public double TriggerPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets order trailing offset value + /// + [DataMember(Name = "TrailOffset")] + public double TrailOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets orders current status + /// + [DataMember(Name = "Status")] + public OrderStatus Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = orderStatus; + } + } + + /// + /// Gets open order original status + /// + [DataMember(Name = "OriginalStatus")] + public string OriginalStatus + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets order TIF(Time-In-Force) type + /// + [DataMember(Name = "Tif")] + public TimeInForce TimeInForce + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeInForce; + } + } + + /// + /// Gets orders expiration time + /// + [DataMember(Name = "ExpirationTime")] + public DateTime ExpirationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets orders last update time + /// + public DateTime LastUpdateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public double AverageFillPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets StopLoss holder for given order + /// + public SlTpHolder StopLoss => StopLossItems.FirstOrDefault(); + + /// + /// Gets TakeProfit holder for given order + /// + public SlTpHolder TakeProfit => TakeProfitItems.FirstOrDefault(); + + public SlTpHolder[] StopLossItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + public SlTpHolder[] TakeProfitItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + /// + /// Will be triggered on each invocation + /// + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Creates Order instance + /// + /// + internal Order(string P_0) + : base(P_0) + { + StopLossItems = new SlTpHolder[0]; + TakeProfitItems = new SlTpHolder[0]; + } + + internal void ?(MessageOpenOrder P_0) + { + base.Id = P_0.OrderId; + GroupId = P_0.GroupId; + PositionId = P_0.PositionId; + LastUpdateTime = P_0.LastUpdateTime; + if (ConnectionCache != null && ConnectionCache.SymbolsCache.?(P_0.SymbolId, out var symbol)) + { + base.Symbol = symbol; + } + else if (!string.IsNullOrEmpty(P_0.SymbolId)) + { + base.Symbol = new Symbol(new BusinessObjectInfo + { + Id = P_0.SymbolId, + Name = P_0.SymbolId + }); + } + if (!string.IsNullOrEmpty(P_0.AccountId) && ConnectionCache != null && ConnectionCache.AccountsCache.?(P_0.AccountId, out var account)) + { + base.Account = account; + } + TotalQuantity = P_0.TotalQuantity; + FilledQuantity = P_0.FilledQuantity; + base.Side = P_0.Side; + OrderTypeId = P_0.OrderTypeId; + Price = P_0.Price; + TriggerPrice = P_0.TriggerPrice; + TrailOffset = P_0.TrailOffset; + TimeInForce = P_0.TimeInForce; + ExpirationTime = P_0.ExpirationTime; + Status = P_0.Status; + OriginalStatus = P_0.OriginalStatus; + AverageFillPrice = P_0.AverageFillPrice; + StopLossItems = P_0.StopLossItems.ToArray(); + TakeProfitItems = P_0.TakeProfitItems.ToArray(); + base.Comment = P_0.Comment; + ProcessAdditionalItems(P_0.AdditionalInfoItems); + ???.Invoke(this); + } + + public MessageOpenOrder BuildMessage() + { + MessageOpenOrder messageOpenOrder = new MessageOpenOrder(base.Symbol?.Id); + messageOpenOrder.OrderId = base.Id; + messageOpenOrder.GroupId = GroupId; + messageOpenOrder.PositionId = PositionId; + messageOpenOrder.LastUpdateTime = LastUpdateTime; + messageOpenOrder.AccountId = base.Account?.Id; + messageOpenOrder.TotalQuantity = TotalQuantity; + messageOpenOrder.FilledQuantity = FilledQuantity; + messageOpenOrder.Side = base.Side; + messageOpenOrder.OrderTypeId = OrderTypeId; + messageOpenOrder.Price = Price; + messageOpenOrder.TriggerPrice = TriggerPrice; + messageOpenOrder.TrailOffset = TrailOffset; + messageOpenOrder.TimeInForce = TimeInForce; + messageOpenOrder.ExpirationTime = ExpirationTime; + messageOpenOrder.Status = Status; + messageOpenOrder.OriginalStatus = OriginalStatus; + messageOpenOrder.Comment = base.Comment; + messageOpenOrder.AdditionalInfoItems = base.AdditionalInfo?.ToList(); + messageOpenOrder.StopLossItems.AddRange(StopLossItems); + messageOpenOrder.TakeProfitItems.AddRange(TakeProfitItems); + return messageOpenOrder; + } + + /// + /// Cancels pending order + /// + /// + public TradingOperationResult Cancel(string sendingSource = null) + { + return Core.Instance.CancelOrder(new CancelOrderRequestParameters + { + Order = this, + SendingSource = sendingSource + }); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(46, 12); + defaultInterpolatedStringHandler.AppendFormatted(base.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType?.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(FilledQuantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TotalQuantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(?()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Status); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PositionId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(GroupId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Comment); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private string ?() + { + StringBuilder stringBuilder = new StringBuilder(); + if (!double.IsNaN(Price)) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(5, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.Symbol?.FormatPrice(Price) ?? Price.FormatPriceWithMaxPrecision()); + stringBuilder3.Append(ref handler); + } + if (!double.IsNaN(TriggerPrice)) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.Symbol?.FormatPrice(TriggerPrice) ?? TriggerPrice.FormatPriceWithMaxPrecision()); + stringBuilder4.Append(ref handler); + } + if (!double.IsNaN(TrailOffset)) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder5 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.Symbol?.FormatOffset(TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? TrailOffset.FormatPriceWithMaxPrecision()); + stringBuilder5.Append(ref handler); + } + return stringBuilder.ToString(); + } + + public bool Equals(Order other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (base.ConnectionId == other.ConnectionId) + { + return base.Id == other.Id; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((Order)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(base.ConnectionId, base.Id); + } + + [CompilerGenerated] + private bool ?(OrderType P_0) + { + return P_0.Id == OrderTypeId; + } + } + /// + /// Represents an wrapper + /// + public class OrderHistory : Order, IMessageBuilder, IEquatable + { + public OrderHistory(string connectionId) + : base(connectionId) + { + } + + private MessageOrderHistory ?() + { + return new MessageOrderHistory(BuildMessage()); + } + + MessageOrderHistory IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + public bool Equals(OrderHistory other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (base.ConnectionId == other.ConnectionId && base.Id == other.Id && base.UniqueId == other.UniqueId && object.Equals(base.Symbol, other.Symbol) && object.Equals(base.Account, other.Account) && object.Equals(base.OrderType, other.OrderType) && object.Equals(base.StopLoss, other.StopLoss) && object.Equals(base.TakeProfit, other.TakeProfit) && object.Equals(base.StopLossItems, other.StopLossItems) && object.Equals(base.TakeProfitItems, other.TakeProfitItems) && object.Equals(base.AdditionalInfo, other.AdditionalInfo) && base.Comment == other.Comment && base.Price == other.Price && base.TriggerPrice == other.TriggerPrice && base.TrailOffset == other.TrailOffset && base.AverageFillPrice == other.AverageFillPrice && base.TotalQuantity == other.TotalQuantity && base.FilledQuantity == other.FilledQuantity && base.RemainingQuantity == other.RemainingQuantity && base.Side == other.Side && State == other.State && base.Status == other.Status && base.ExpirationTime == other.ExpirationTime && base.GroupId == other.GroupId && base.OriginalStatus == other.OriginalStatus && base.PositionId == other.PositionId && base.LastUpdateTime == other.LastUpdateTime && base.OrderTypeId == other.OrderTypeId) + { + return base.TimeInForce == other.TimeInForce; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((OrderHistory)obj); + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(base.ConnectionId); + hashCode.Add(base.Id); + hashCode.Add(base.UniqueId); + hashCode.Add(base.Symbol); + hashCode.Add(base.Account); + hashCode.Add(base.OrderType); + hashCode.Add(base.StopLoss); + hashCode.Add(base.TakeProfit); + hashCode.Add(base.StopLossItems); + hashCode.Add(base.TakeProfitItems); + hashCode.Add(base.AdditionalInfo); + hashCode.Add(base.Comment); + hashCode.Add(base.Price); + hashCode.Add(base.TriggerPrice); + hashCode.Add(base.TrailOffset); + hashCode.Add(base.AverageFillPrice); + hashCode.Add(base.TotalQuantity); + hashCode.Add(base.FilledQuantity); + hashCode.Add(base.RemainingQuantity); + hashCode.Add(base.Side); + hashCode.Add(State); + hashCode.Add(base.Status); + hashCode.Add(base.ExpirationTime); + hashCode.Add(base.GroupId); + hashCode.Add(base.OriginalStatus); + hashCode.Add(base.PositionId); + hashCode.Add(base.LastUpdateTime); + hashCode.Add(base.OrderTypeId); + hashCode.Add(base.TimeInForce); + return hashCode.ToHashCode(); + } + } + public class BasicBalanceCalculator : IBalanceCalculator, IDisposable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(SlTpHolder P_0) + { + return !double.IsNaN(P_0.QuantityPercentage); + } + + internal double ?(SlTpHolder P_0) + { + return P_0.Quantity; + } + } + + [CompilerGenerated] + private sealed class ? + { + public BasicBalanceCalculator ??; + + public SettingItem[] ??; + + public OrderRequestParameters ??; + + internal void ?() + { + ??.PopulateAction(??, ??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public BasicBalanceCalculator ??; + + public OrderRequestParameters ??; + + public string ??; + + internal void ?() + { + try + { + ??.RequestParameters = ??; + ??.?? = ??; + ??.OnOrderSettingChanged(??); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ??.?? = null; + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public BasicBalanceCalculator ??; + + public Symbol ??; + + public double ??; + + internal double ?(SlTpHolder P_0) + { + return ??.?(??, P_0, P_0.QuantityPercentage / 100.0, ??); + } + + internal double ?(SlTpHolder P_0) + { + return ??.?(??, P_0, P_0.Quantity, ??); + } + } + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private double? ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private readonly bool ??; + + [CompilerGenerated] + private bool ??; + + protected OrderRequestParameters RequestParameters; + + private string ??; + + private Task ??; + + private Task ??; + + protected SettingItem QuantityItem; + + private SettingItem ??; + + private SettingItem ??; + + public bool DisplayQuantityInLots + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double? CurrentFillPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string QuantityDefiningSettingName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AsyncBehavior + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + protected bool SkipChanges + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public BasicBalanceCalculator() + { + AsyncBehavior = false; + } + + public void Populate(SettingItem[] orderSettings, OrderRequestParameters requestParameters) + { + if (AsyncBehavior) + { + ?? = Task.Run(delegate + { + PopulateAction(orderSettings, requestParameters); + }); + } + else + { + PopulateAction(orderSettings, requestParameters); + } + } + + protected virtual void PopulateAction(SettingItem[] orderSettings, OrderRequestParameters requestParameters) + { + RequestParameters = requestParameters; + QuantityItem = orderSettings?.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?? = orderSettings?.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?? = orderSettings?.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?(); + Recalculate(); + } + + public void OnOrderSettingChanged(string settingName, OrderRequestParameters requestParameters) + { + ? CS$<>8__locals11 = new ?(); + CS$<>8__locals11.?? = this; + CS$<>8__locals11.?? = requestParameters; + CS$<>8__locals11.?? = settingName; + if (SkipChanges || ?? != null) + { + return; + } + if (AsyncBehavior) + { + ?? = Task.Run(delegate + { + try + { + CS$<>8__locals11.??.RequestParameters = CS$<>8__locals11.??; + CS$<>8__locals11.??.?? = CS$<>8__locals11.??; + CS$<>8__locals11.??.OnOrderSettingChanged(CS$<>8__locals11.??); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + CS$<>8__locals11.??.?? = null; + } + }); + } + else + { + CS$<>8__locals11.?(); + } + } + + protected virtual void OnOrderSettingChanged(string settingName) + { + if (!(settingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(settingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (settingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + QuantityDefiningSettingName = settingName; + OnRiskPercentChanged(); + } + else + { + Recalculate(); + } + } + else + { + QuantityDefiningSettingName = settingName; + OnRiskChanged(); + } + } + else + { + QuantityDefiningSettingName = settingName; + OnQuantityChanged(); + } + } + + public void OnTimerTick() + { + OrderRequestParameters requestParameters = RequestParameters; + if (requestParameters != null && requestParameters.OrderType?.Behavior == OrderTypeBehavior.Market && ?? == null) + { + Recalculate(); + } + } + + protected void Recalculate() + { + string text = ??; + try + { + ?? = QuantityDefiningSettingName ?? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + ?(); + RecalculateAction(??); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?? = text; + } + } + + protected virtual void RecalculateAction(string processingSettingName) + { + if (!(processingSettingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(processingSettingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (processingSettingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + OnRiskPercentChanged(); + } + } + else + { + OnRiskChanged(); + } + } + else + { + OnQuantityChanged(); + } + } + + public void Dispose() + { + if (AsyncBehavior) + { + Task.WhenAll(?? ?? Task.CompletedTask, ?? ?? Task.CompletedTask).ContinueWith(delegate + { + DisposeAction(); + }); + } + else + { + DisposeAction(); + } + } + + protected virtual void DisposeAction() + { + QuantityItem = null; + } + + protected virtual void OnQuantityChanged() + { + if (QuantityItem != null) + { + UpdateRisk(GetQuantity()); + UpdateRiskPercent(GetRisk()); + } + } + + protected virtual void OnRiskChanged() + { + if (?? != null) + { + double? risk = GetRisk(); + ?(risk); + UpdateRiskPercent(risk); + } + } + + protected virtual void OnRiskPercentChanged() + { + double? num = ?(); + double? availableBalance = GetAvailableBalance(); + if (num.HasValue && availableBalance.HasValue) + { + double value = availableBalance.Value * num.Value / 100.0; + ?(value, SettingItemValueChangingReason.Programmatically); + ?(value); + } + } + + protected void UpdateQuantity(double? quantity, SettingItemValueChangingReason reason) + { + if (quantity.HasValue) + { + QuantityItem.SetValueWithReason(CoreMath.FloorToIncrement(quantity.Value, RequestParameters.Symbol.LotStep), reason); + } + } + + private void ?(double? P_0) + { + Symbol ?? = RequestParameters?.Symbol; + List list = RequestParameters?.StopLossItems; + if (!P_0.HasValue || QuantityItem == null || !CurrentFillPrice.HasValue || list == null || list.Count == 0 || ?? == null) + { + return; + } + double ?? = CurrentFillPrice.Value; + double value; + if (list.Count == 1) + { + SlTpHolder slTpHolder = list[0]; + value = CoreMath.RoundToIncrement(P_0.Value / ?(??, slTpHolder, 1.0, ??), ??.LotStep); + } + else if (list.All((SlTpHolder slTpHolder3) => !double.IsNaN(slTpHolder3.QuantityPercentage))) + { + double num = list.Sum((SlTpHolder slTpHolder3) => ?(??, slTpHolder3, slTpHolder3.QuantityPercentage / 100.0, ??)); + value = CoreMath.RoundToIncrement(P_0.Value / num, ??.LotStep); + } + else + { + SlTpHolder[] array = list.Take(list.Count - 1).ToArray(); + SlTpHolder slTpHolder2 = list.Last(); + if (array.Length < 1) + { + return; + } + double num2 = array.Sum((SlTpHolder slTpHolder3) => ?(??, slTpHolder3, slTpHolder3.Quantity, ??)); + double num3 = P_0.Value - num2; + if (num3 <= 0.0) + { + value = ??.MinLot; + } + else + { + double num4 = CoreMath.RoundToIncrement(num3 / ?(??, slTpHolder2, 1.0, ??), ??.LotStep); + value = array.Sum((SlTpHolder slTpHolder3) => slTpHolder3.Quantity) + num4; + } + } + UpdateQuantity(value, SettingItemValueChangingReason.Programmatically); + } + + private void ?(double? P_0, SettingItemValueChangingReason P_1) + { + if (P_0.HasValue) + { + ??.SetValueWithReason(P_0.Value, P_1); + } + } + + protected void UpdateRisk(double? quantity) + { + Symbol symbol = RequestParameters?.Symbol; + List list = RequestParameters?.StopLossItems; + if (!quantity.HasValue || ?? == null || !CurrentFillPrice.HasValue || list == null || list.Count == 0 || symbol == null || !RequestParameters.TryCorrectBracketsQuantity(out var _)) + { + return; + } + double value = CurrentFillPrice.Value; + double num = 0.0; + foreach (SlTpHolder item in list) + { + double num2 = item.Quantity; + if (double.IsNaN(num2)) + { + num2 = quantity.Value; + } + num += ?(symbol, item, num2, value); + } + ??.SetValueWithReason(num, SettingItemValueChangingReason.Programmatically); + } + + protected void UpdateRiskPercent(double? risk) + { + double? availableBalance = GetAvailableBalance(); + if (risk.HasValue && ?? != null && availableBalance.HasValue && availableBalance != 0.0) + { + double num = risk.Value / availableBalance.Value * 100.0; + ??.SetValueWithReason(num, SettingItemValueChangingReason.Programmatically); + } + } + + protected virtual double? GetAvailableBalance() + { + return RequestParameters?.Account?.Balance; + } + + protected double? GetQuantity() + { + double? result = QuantityItem?.GetValue(); + if (!result.HasValue) + { + return null; + } + if (!DisplayQuantityInLots && RequestParameters?.Symbol != null) + { + return result.Value / RequestParameters.Symbol.LotSize; + } + return result; + } + + protected double? GetRisk() + { + return ???.GetValue(); + } + + private double? ?() + { + return ???.GetValue(); + } + + private void ?() + { + CurrentFillPrice = RequestParameters.OrderType?.GetFillPrice(RequestParameters); + } + + private double ?(Symbol P_0, SlTpHolder P_1, double P_2, double P_3) + { + double num = P_1.Price; + if (P_1.PriceMeasurement == PriceMeasurement.Offset) + { + num = RequestParameters.Symbol.CalculatePrice(P_3, (double)((RequestParameters.Side != Side.Buy) ? 1 : (-1)) * num); + } + double num2 = Math.Abs(P_0.CalculateValue(RequestParameters.Side, P_3, P_2)); + double num3 = Math.Abs(P_0.CalculateValue(RequestParameters.Side, num, P_2)); + return Math.Abs(num2 - num3); + } + + [CompilerGenerated] + private void ?(Task P_0) + { + DisposeAction(); + } + } + public abstract class CryptoBalanceCalculator : BasicBalanceCalculator + { + private SettingItemDoubleWithLink ??; + + private SettingItemSlider ??; + + protected override void PopulateAction(SettingItem[] orderSettings, OrderRequestParameters requestParameters) + { + RequestParameters = requestParameters; + if (?? != null) + { + ??.LinkAction = null; + } + ?? = orderSettings?.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as SettingItemDoubleWithLink; + ?? = orderSettings?.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as SettingItemSlider; + if (?? != null) + { + ??.LinkAction = OnLinkAction; + PopulateTotal(); + } + base.PopulateAction(orderSettings, requestParameters); + } + + protected override void OnOrderSettingChanged(string settingName) + { + if (!(settingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(settingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (settingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + base.QuantityDefiningSettingName = settingName; + OnPercentChanged(); + } + } + else + { + base.QuantityDefiningSettingName = settingName; + OnTotalChanged(); + } + } + else + { + OnSideChanged(); + } + base.OnOrderSettingChanged(settingName); + } + + protected override void RecalculateAction(string processingSettingName) + { + if (!(processingSettingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (processingSettingName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + OnPercentChanged(); + } + else + { + base.RecalculateAction(processingSettingName); + } + } + else + { + OnTotalChanged(); + } + } + + protected override void DisposeAction() + { + ?? = null; + ?? = null; + base.DisposeAction(); + } + + protected virtual double CalculateQuantity(double total, double fillPrice) + { + return (double)((decimal)total / (decimal)fillPrice); + } + + protected virtual double CalculateTotal(double quantity, double fillPrice) + { + return (double)((decimal)fillPrice * (decimal)quantity); + } + + protected virtual string GetTotalLinkText() + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + + protected virtual ulong CalculateSliderStep() + { + return 0uL; + } + + protected override void OnQuantityChanged() + { + base.OnQuantityChanged(); + if (QuantityItem != null) + { + UpdateTotal(GetQuantity()); + UpdateSlider(); + } + } + + protected override void OnRiskChanged() + { + base.OnRiskChanged(); + if (QuantityItem != null) + { + UpdateTotal(GetQuantity()); + UpdateSlider(); + } + } + + protected override void OnRiskPercentChanged() + { + base.OnRiskPercentChanged(); + if (QuantityItem != null) + { + UpdateTotal(GetQuantity()); + UpdateSlider(); + } + } + + protected virtual void OnSideChanged() + { + } + + protected virtual void OnTotalChanged() + { + if (?? != null) + { + UpdateQuantity(GetTotal()); + UpdateSlider(); + UpdateRisk(GetQuantity()); + UpdateRiskPercent(GetRisk()); + } + } + + protected abstract void OnLinkAction(object obj); + + protected abstract void OnPercentChanged(); + + protected void UpdateQuantity(double? total) + { + if (total.HasValue && QuantityItem != null && base.CurrentFillPrice.HasValue) + { + double value = base.CurrentFillPrice.Value; + if (!value.IsNanOrDefault()) + { + double value2 = CalculateQuantity(total.Value, value); + UpdateQuantity(value2, SettingItemValueChangingReason.Programmatically); + } + } + } + + protected void UpdateTotal(double? quantity) + { + if (quantity.HasValue && ?? != null && base.CurrentFillPrice.HasValue) + { + double value = base.CurrentFillPrice.Value; + if (!double.IsNaN(value)) + { + UpdateTotal(CalculateTotal(quantity.Value, value), SettingItemValueChangingReason.Programmatically); + } + } + } + + protected void UpdateTotal(double? total, SettingItemValueChangingReason reason) + { + if (total.HasValue) + { + ??.SetValueWithReason(total, reason); + } + } + + protected void UpdateTotalLink() + { + if (?? != null) + { + ??.LinkText = GetTotalLinkText(); + } + } + + protected void UpdateSlider() + { + if (?? != null) + { + ulong num = CalculateSliderStep(); + ??.SetValueWithReason(num, SettingItemValueChangingReason.Programmatically); + } + } + + protected void PopulateTotal() + { + if (?? != null) + { + double num = 1.0; + int decimalPlaces = 0; + string dimension = string.Empty; + Asset totalAsset = GetTotalAsset(); + if (totalAsset != null) + { + num = totalAsset.MinimumChange; + decimalPlaces = totalAsset.Precision; + dimension = totalAsset.Name; + } + ??.Minimum = num; + ??.Maximum = double.MaxValue; + ??.Increment = num; + ??.DecimalPlaces = decimalPlaces; + ??.Dimension = dimension; + } + } + + protected double? GetTotal() + { + return ???.GetValue(); + } + + protected double? GetSliderPercent() + { + return (double?)???.GetValue() / 100.0; + } + + protected virtual Asset GetTotalAsset() + { + return RequestParameters?.Symbol?.QuotingCurrency; + } + } + public interface IBalanceCalculator : IDisposable + { + bool DisplayQuantityInLots { get; set; } + + double? CurrentFillPrice { get; set; } + + string QuantityDefiningSettingName { get; set; } + + void Populate(SettingItem[] orderSettings, OrderRequestParameters requestParameters); + + void OnOrderSettingChanged(string settingName, OrderRequestParameters requestParameters); + + void OnTimerTick(); + } + public abstract class MarginBasedBalanceCalculator : CryptoBalanceCalculator + { + private Symbol ??; + + private Account ??; + + private Asset ??; + + protected Symbol CurrentSymbol + { + get + { + return ??; + } + set + { + if (?? == value) + { + return; + } + ?? = null; + if (?? != null) + { + ??.Updated -= ?; + } + ?? = value; + if (?? != null) + { + ??.Updated += ?; + ?? = CurrentSymbol.Connection?.BusinessObjects.Assets.FirstOrDefault((Asset P_0) => P_0.Id == BalanceCurrency); + } + } + } + + protected Account CurrentAccount + { + get + { + return ??; + } + set + { + if (?? != value) + { + if (?? != null) + { + ??.Updated -= ?; + } + ?? = value; + if (?? != null) + { + ??.Updated += ?; + } + } + } + } + + protected virtual string BalanceCurrency => CurrentSymbol?.QuotingCurrency?.Id; + + protected override void PopulateAction(SettingItem[] orderSettings, OrderRequestParameters requestParameters) + { + base.PopulateAction(orderSettings, requestParameters); + CurrentSymbol = requestParameters.Symbol; + CurrentAccount = requestParameters.Account; + PopulateTotal(); + UpdateTotalLink(); + Recalculate(); + } + + protected override void DisposeAction() + { + base.DisposeAction(); + CurrentAccount = null; + } + + protected override string GetTotalLinkText() + { + double? availableBalance = GetAvailableBalance(); + if (!availableBalance.HasValue) + { + return base.GetTotalLinkText(); + } + return ???.FormatPriceWithCurrency(availableBalance.Value); + } + + protected override ulong CalculateSliderStep() + { + double? total = GetTotal(); + if (!total.HasValue) + { + return base.CalculateSliderStep(); + } + double? num = GetAvailableBalance(); + if (!num.HasValue) + { + return base.CalculateSliderStep(); + } + if (num == 0.0) + { + num = 1.0; + } + return (ulong)(total.Value * 100.0 * 100.0 / num).Value; + } + + protected override Asset GetTotalAsset() + { + return ??; + } + + protected abstract double? GetAvailableForOrder(); + + protected abstract int? GetLeverage(); + + protected override void OnLinkAction(object obj) + { + UpdateTotal(GetAvailableBalance(), SettingItemValueChangingReason.Manually); + } + + protected override void OnPercentChanged() + { + double? sliderPercent = GetSliderPercent(); + if (sliderPercent.HasValue) + { + double? availableBalance = GetAvailableBalance(); + if (availableBalance.HasValue) + { + double value = availableBalance.Value * sliderPercent.Value / 100.0; + UpdateQuantity(value); + UpdateTotal(GetQuantity()); + UpdateRisk(GetQuantity()); + UpdateRiskPercent(GetRisk()); + } + } + } + + private void ?(Symbol P_0) + { + try + { + base.SkipChanges = true; + UpdateTotalLink(); + Recalculate(); + } + finally + { + base.SkipChanges = false; + } + } + + private void ?(Account P_0) + { + try + { + base.SkipChanges = true; + UpdateTotalLink(); + Recalculate(); + } + finally + { + base.SkipChanges = false; + } + } + + protected override double? GetAvailableBalance() + { + double? availableForOrder = GetAvailableForOrder(); + if (!availableForOrder.HasValue) + { + return null; + } + int? leverage = GetLeverage(); + if (!leverage.HasValue) + { + return null; + } + return availableForOrder * (double?)leverage; + } + + [CompilerGenerated] + private bool ?(Asset P_0) + { + return P_0.Id == BalanceCurrency; + } + } + public class MultiAssetBalanceCalculator : CryptoBalanceCalculator + { + private CryptoAssetBalances ??; + + private CryptoAccount ??; + + protected CryptoAssetBalances CurrentBalance + { + get + { + return ??; + } + set + { + if (?? != value) + { + ?? = value; + UpdateTotalLink(); + Recalculate(); + } + } + } + + private CryptoAccount CurrentAccount + { + get + { + return ??; + } + set + { + if (?? == cryptoAccount) + { + ?(); + return; + } + if (?? != null) + { + ??.BalanceUpdated -= ?; + } + ?? = cryptoAccount; + if (?? != null) + { + ??.BalanceUpdated += ?; + } + ?(); + } + } + + protected override void PopulateAction(SettingItem[] orderSettings, OrderRequestParameters requestParameters) + { + base.PopulateAction(orderSettings, requestParameters); + CurrentAccount = requestParameters.Account as CryptoAccount; + } + + protected override void DisposeAction() + { + base.DisposeAction(); + CurrentAccount = null; + CurrentBalance = null; + } + + protected override string GetTotalLinkText() + { + if (CurrentBalance == null) + { + return base.GetTotalLinkText(); + } + return CurrentBalance.Asset.FormatPriceWithCurrency(GetAvailableBalance().GetValueOrDefault()); + } + + protected override ulong CalculateSliderStep() + { + if (RequestParameters == null || CurrentBalance == null) + { + return base.CalculateSliderStep(); + } + double? num = ((RequestParameters.Side != Side.Buy) ? GetQuantity() : GetTotal()); + if (!num.HasValue) + { + return base.CalculateSliderStep(); + } + double? num2 = GetAvailableBalance(); + if ((!num2.HasValue || num2.GetValueOrDefault() == 0.0) ? true : false) + { + num2 = 1.0; + } + return (ulong)(num.Value * 100.0 * 100.0 / num2).Value; + } + + protected override double? GetAvailableBalance() + { + return CurrentBalance?.AvailableBalance ?? 0.0; + } + + protected override void OnSideChanged() + { + ?(); + UpdateSlider(); + } + + protected override void OnLinkAction(object obj) + { + if (CurrentBalance != null && RequestParameters != null) + { + double valueOrDefault = GetAvailableBalance().GetValueOrDefault(); + if (RequestParameters.Side == Side.Buy) + { + UpdateTotal(valueOrDefault, SettingItemValueChangingReason.Manually); + } + else + { + UpdateQuantity(valueOrDefault, SettingItemValueChangingReason.Manually); + } + } + } + + protected override void OnPercentChanged() + { + double? sliderPercent = GetSliderPercent(); + if (sliderPercent.HasValue && CurrentBalance != null && RequestParameters != null) + { + double valueOrDefault = GetAvailableBalance().GetValueOrDefault(); + if (RequestParameters.Side == Side.Buy) + { + double value = valueOrDefault * sliderPercent.Value / 100.0; + UpdateQuantity(value); + UpdateTotal(value, SettingItemValueChangingReason.Programmatically); + UpdateRisk(GetQuantity()); + UpdateRiskPercent(GetRisk()); + } + else + { + double value2 = valueOrDefault * sliderPercent.Value / 100.0; + UpdateTotal(value2); + UpdateQuantity(value2, SettingItemValueChangingReason.Programmatically); + UpdateRisk(GetQuantity()); + UpdateRiskPercent(GetRisk()); + } + } + } + + private void ?(object P_0, CryptoAccountEventArgs P_1) + { + if (CurrentBalance != null && !(P_1.Balances.AssetId != CurrentBalance.AssetId)) + { + UpdateTotalLink(); + Recalculate(); + } + } + + private void ?() + { + try + { + CurrentBalance = ?(); + } + finally + { + UpdateTotalLink(); + Recalculate(); + } + } + + [CompilerGenerated] + private CryptoAssetBalances ?() + { + CryptoAccount currentAccount = CurrentAccount; + if (currentAccount == null || currentAccount.State != BusinessObjectState.Normal) + { + return null; + } + string text = ((RequestParameters.Side != Side.Buy) ? RequestParameters.Symbol?.Product?.Id : RequestParameters.Symbol?.QuotingCurrency?.Id); + if (string.IsNullOrEmpty(text)) + { + return null; + } + if (!CurrentAccount.TryGetAssetBalances(text, out var cryptoAssetBalances)) + { + return null; + } + return cryptoAssetBalances; + } + } + public class CustomOrderType : OrderType + { + private readonly string ??; + + private readonly OrderTypeBehavior ??; + + private readonly OrderType ??; + + public override string Id + { + get + { + if (!string.IsNullOrEmpty(??)) + { + return ??; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + + public override string Name + { + get + { + if (!string.IsNullOrEmpty(??)) + { + return ??; + } + return ???.Name ?? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + + public override string Abbreviation => ???.Abbreviation ?? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => ???.Behavior ?? ??; + + public override string PriceItemId => ???.PriceItemId ?? base.PriceItemId; + + public CustomOrderType(string name, OrderTypeBehavior behavior, params TimeInForce[] allowedTifs) + : this(name, behavior, null, allowedTifs) + { + } + + public CustomOrderType(string name, OrderType baseOrderType) + : this(name, baseOrderType?.Behavior, baseOrderType, baseOrderType?.AllowedTifs ?? new TimeInForce[1]) + { + } + + public CustomOrderType(OrderType baseOrderType) + : this(baseOrderType?.Name, baseOrderType?.Behavior, baseOrderType, baseOrderType?.AllowedTifs ?? new TimeInForce[1]) + { + } + + private CustomOrderType(string P_0, OrderTypeBehavior? P_1, OrderType P_2, params TimeInForce[] allowedTifs) + : base(allowedTifs) + { + ?? = P_0; + ?? = P_1.GetValueOrDefault(); + ?? = P_2; + } + + public override IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + return ???.GetOrderSettings(parameters, formatSettings) ?? base.GetOrderSettings(parameters, formatSettings); + } + + public override IList GetDealTicketItems(OrderRequestParameters request) + { + return ???.GetDealTicketItems(request) ?? base.GetDealTicketItems(request); + } + + public override void SetDefaultPrices(SettingItem[] settings, OrderRequestParameters parameters) + { + if (?? != null) + { + ??.SetDefaultPrices(settings, parameters); + } + else + { + base.SetDefaultPrices(settings, parameters); + } + } + + public override double GetFillPrice(OrderRequestParameters parameters) + { + return ???.GetFillPrice(parameters) ?? double.NaN; + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + return ???.GetConfirmMessage(placeRequest, formatSettings); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + return ???.GetConfirmMessage(modifyRequest, formatSettings); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + return ???.GetCancelConfirmMessage(cancelRequest, formatSettings); + } + + public override ValidateResult ValidateOrderRequestParameters(OrderRequestParameters parameters) + { + return ???.ValidateOrderRequestParameters(parameters) ?? base.ValidateOrderRequestParameters(parameters); + } + } + public enum OrderTypeBehavior + { + Unspecified, + Market, + Limit, + Stop, + TrailingStop, + StopLimit + } + [Flags] + public enum OrderTypeUsage + { + Order = 1, + CloseOrder = 2, + All = 3 + } + public class LimitIfTouchedOrderType : LimitOrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => OrderTypeBehavior.StopLimit; + + public LimitIfTouchedOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + } + + public override IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + IList orderSettings = base.GetOrderSettings(parameters, formatSettings); + double num = 0.0; + double num2 = 1E-05; + int decimalPlaces = 5; + Symbol symbol = parameters.Symbol; + bool enabled = true; + if (symbol != null) + { + if (parameters.Type == RequestType.PlaceOrder) + { + num = ((parameters.Side == Side.Buy) ? symbol.Ask : symbol.Bid); + num = CoreMath.ProcessNaN(num); + } + else if (parameters.Type == RequestType.ModifyOrder) + { + num = parameters.TriggerPrice; + enabled = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), parameters.Account, parameters.Symbol, this).Status == TradingOperationStatus.Allowed; + } + VariableTick variableTick = symbol.FindVariableTick(num); + if (variableTick != null) + { + num2 = variableTick.TickSize; + decimalPlaces = variableTick.Precision; + } + } + SettingItemDouble item = new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SortIndex = 0, + Minimum = num2, + Maximum = 2147483647.0, + Increment = num2, + DecimalPlaces = decimalPlaces, + Enabled = enabled + }; + orderSettings.Add(item); + return orderSettings; + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + string value = placeRequest.TimeInForce.Format(placeRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(38, 9); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatQuantity(placeRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatPrice(placeRequest.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatPrice(placeRequest.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(placeRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + string value = modifyRequest.TimeInForce.Format(modifyRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 10); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatQuantity(modifyRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatPrice(modifyRequest.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatPrice(modifyRequest.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(modifyRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + IOrder order = cancelRequest?.Order; + if (order == null) + { + return string.Empty; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 9); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Format(order.PositionId, order.GroupId)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.TimeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatQuantity(order.TotalQuantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Account.GetCurrentName()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override ValidateResult ValidateOrderRequestParameters(OrderRequestParameters parameters) + { + return base.ValidateOrderRequestParameters(parameters); + } + + public override IList GetDealTicketItems(OrderRequestParameters request) + { + IList dealTicketItems = base.GetDealTicketItems(request); + dealTicketItems.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.FormatPrice(request.TriggerPrice), 5550)); + return dealTicketItems; + } + } + public class LimitOrderType : OrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => OrderTypeBehavior.Limit; + + protected virtual string PriceText => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string PriceItemId => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public LimitOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + base.Usage = OrderTypeUsage.All; + } + + public override IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + IList orderSettings = base.GetOrderSettings(parameters, formatSettings); + double num = 0.0; + double num2 = 1E-05; + int decimalPlaces = 5; + Symbol symbol = parameters.Symbol; + bool enabled = true; + if (symbol != null) + { + if (parameters.Type == RequestType.PlaceOrder) + { + num = ((parameters.Side == Side.Buy) ? symbol.Ask : symbol.Bid); + num = CoreMath.ProcessNaN(num); + } + else if (parameters.Type == RequestType.ModifyOrder) + { + num = parameters.Price; + if (double.IsNaN(num)) + { + num = parameters.TriggerPrice; + } + enabled = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), parameters.Account, parameters.Symbol, this).Status == TradingOperationStatus.Allowed; + } + VariableTick variableTick = symbol.FindVariableTick(num); + if (variableTick != null) + { + num2 = variableTick.TickSize; + decimalPlaces = variableTick.Precision; + } + } + SettingItemDouble item = new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num) + { + Text = loc._(PriceText, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SortIndex = 0, + Minimum = num2, + Maximum = 2147483647.0, + Increment = num2, + DecimalPlaces = decimalPlaces, + Enabled = enabled + }; + orderSettings.Add(item); + return orderSettings; + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + string value = placeRequest.TimeInForce.Format(placeRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(16, 8); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatQuantity(placeRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatPrice(placeRequest.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(placeRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + string value = modifyRequest.TimeInForce.Format(modifyRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(32, 9); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatQuantity(modifyRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatPrice(modifyRequest.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(modifyRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + IOrder order = cancelRequest?.Order; + if (order == null) + { + return string.Empty; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(31, 8); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(order.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Format(order.PositionId, order.GroupId)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.TimeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatQuantity(order.TotalQuantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Account.GetCurrentName()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override ValidateResult ValidateOrderRequestParameters(OrderRequestParameters parameters) + { + ValidateResult result = base.ValidateOrderRequestParameters(parameters); + if (result.State == ValidateState.NotValid) + { + return result; + } + double price = parameters.Price; + if (parameters.Side == Side.Buy) + { + SlTpHolder stopLoss = parameters.StopLoss; + if (stopLoss != null && stopLoss.PriceMeasurement == PriceMeasurement.Absolute && stopLoss.Price >= price) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + SlTpHolder takeProfit = parameters.TakeProfit; + if (takeProfit != null && takeProfit.PriceMeasurement == PriceMeasurement.Absolute && takeProfit.Price <= price) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + } + if (parameters.Side == Side.Sell) + { + SlTpHolder stopLoss2 = parameters.StopLoss; + if (stopLoss2 != null && stopLoss2.PriceMeasurement == PriceMeasurement.Absolute && stopLoss2.Price <= price) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + SlTpHolder takeProfit2 = parameters.TakeProfit; + if (takeProfit2 != null && takeProfit2.PriceMeasurement == PriceMeasurement.Absolute && takeProfit2.Price >= price) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + } + return ValidateResult.Valid; + } + + public override IList GetDealTicketItems(OrderRequestParameters request) + { + IList dealTicketItems = base.GetDealTicketItems(request); + dealTicketItems.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.FormatPrice(request.Price), 5500)); + return dealTicketItems; + } + + public override double GetFillPrice(OrderRequestParameters parameters) + { + SettingItem itemByPath = parameters.AdditionalParameters.GetItemByPath(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByPath != null) + { + return (double)itemByPath.Value; + } + return parameters.Price; + } + + public override void SetDefaultPrices(SettingItem[] settings, OrderRequestParameters parameters) + { + if (parameters.Symbol != null) + { + double num = ((parameters.Side == Side.Buy) ? parameters.Symbol.Ask : parameters.Symbol.Bid); + if (!double.IsNaN(num)) + { + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num); + } + } + } + } + public class MarketIfTouchedOrderType : StopOrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public MarketIfTouchedOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + base.Usage = OrderTypeUsage.All; + } + } + public class MarketOrderType : OrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => OrderTypeBehavior.Market; + + public MarketOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + string value = placeRequest.TimeInForce.Format(placeRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 6); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatQuantity(placeRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(placeRequest)); + return defaultInterpolatedStringHandler.ToStringAndClear() + ((placeRequest.Account != null) ? (3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + placeRequest.Account.GetCurrentName()) : string.Empty); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + string value = modifyRequest.TimeInForce.Format(modifyRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(27, 8); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatQuantity(modifyRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(modifyRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + IOrder order = cancelRequest?.Order; + if (order == null) + { + return string.Empty; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(27, 7); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(order.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Format(order.PositionId, order.GroupId)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.TimeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatQuantity(order.TotalQuantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Account.GetCurrentName()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override ValidateResult ValidateOrderRequestParameters(OrderRequestParameters parameters) + { + ValidateResult result = base.ValidateOrderRequestParameters(parameters); + if (result.State == ValidateState.NotValid) + { + return result; + } + if (parameters.Side == Side.Buy) + { + double ask = parameters.Symbol.Ask; + SlTpHolder stopLoss = parameters.StopLoss; + if (stopLoss != null && stopLoss.PriceMeasurement == PriceMeasurement.Absolute && stopLoss.Price >= ask) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + SlTpHolder takeProfit = parameters.TakeProfit; + if (takeProfit != null && takeProfit.PriceMeasurement == PriceMeasurement.Absolute && takeProfit.Price <= ask) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + } + if (parameters.Side == Side.Sell) + { + double bid = parameters.Symbol.Bid; + SlTpHolder stopLoss2 = parameters.StopLoss; + if (stopLoss2 != null && stopLoss2.PriceMeasurement == PriceMeasurement.Absolute && stopLoss2.Price <= bid) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + SlTpHolder takeProfit2 = parameters.TakeProfit; + if (takeProfit2 != null && takeProfit2.PriceMeasurement == PriceMeasurement.Absolute && takeProfit2.Price >= bid) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + } + return ValidateResult.Valid; + } + + public override double GetFillPrice(OrderRequestParameters parameters) + { + double result = double.NaN; + if (parameters.Symbol != null) + { + result = ((parameters.Side != Side.Buy) ? parameters.Symbol.Bid : parameters.Symbol.Ask); + } + return result; + } + } + public abstract class OrderType : BusinessObject, IComparable, ?, IEquatable + { + [CompilerGenerated] + private static class ? + { + public static Func ??; + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func> ??; + + internal IEnumerable ?(OrderType P_0) + { + return P_0.AllowedTifs; + } + } + + [CompilerGenerated] + private sealed class ? + { + public TimeInForce? ??; + + internal bool ?(SelectItem P_0) + { + if (??.HasValue) + { + return P_0.Value.Equals((int)??.Value); + } + return true; + } + } + + [CompilerGenerated] + private sealed class ? + { + public OrderRequestParameters ??; + + internal bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)??.Side; + } + } + + public const string Market = "Market"; + + public const string Limit = "Limit"; + + public const string Stop = "Stop"; + + public const string TrailingStop = "Tr.stop"; + + public const string StopLimit = "StopLimit"; + + public const string MarketIfTouched = "MarketIfTouched"; + + public const string LimitIfTouched = "LimitIfTouched"; + + public const string Custom = "Custom"; + + public const string TIME_IF_FORCE = "Time in force"; + + public const string EXPIRATION = "Expiration"; + + public const string SIDE = "Side"; + + public const string QUANTITY = "Quantity"; + + public const string PRICE = "Price"; + + public const string TRIGGER_PRICE = "TriggerPrice"; + + public const string TRAIL_OFFSET = "TrailOffset"; + + public const string COMMENT = "Comment"; + + public const string TOTAL = "Total"; + + public const string BALANCE_PERCENT = "Balance percent"; + + public const string RISK = "Risk"; + + public const string RISK_PERCENT = "Risk percent"; + + public const string REDUCE_ONLY = "Reduce-Only"; + + public const string POST_ONLY = "Post-Only"; + + public const string PARENT_ORDER_ID = "Parent Order ID"; + + public const int BALANCE_PERCENT_STEPS_COUNT_MULTIPLIER = 100; + + [CompilerGenerated] + private readonly OrderTypeUsage ??; + + [CompilerGenerated] + private readonly TimeInForce[] ??; + + [CompilerGenerated] + private readonly PriceMeasurement ??; + + [CompilerGenerated] + private readonly BalanceCalculatorFactory ??; + + private readonly ? ??; + + public abstract string Id { get; } + + public virtual string Name => Id; + + public abstract string Abbreviation { get; } + + public virtual OrderTypeBehavior Behavior => OrderTypeBehavior.Unspecified; + + public OrderTypeUsage Usage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public TimeInForce[] AllowedTifs + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public PriceMeasurement SLTPPriceMeasurement + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public BalanceCalculatorFactory BalanceCalculatorFactory + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public virtual string PriceItemId => null; + + int ?.PriorityIndex => 30; + + ? ?.Rules => ??; + + protected OrderType(params TimeInForce[] allowedTimeInForce) + : base(string.Empty) + { + if (allowedTimeInForce.Length == 0) + { + allowedTimeInForce = Enum.GetValues(typeof(TimeInForce)).Cast().ToArray(); + } + AllowedTifs = allowedTimeInForce; + Usage = OrderTypeUsage.Order; + SLTPPriceMeasurement = PriceMeasurement.Absolute; + ?? = new ?(); + Core.Instance.RulesManager.Defaults.ForEach(delegate(Rule P_0) + { + ??.?(P_0.Name, P_0); + }); + } + + public virtual IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + List list = new List(); + ?(list, parameters, -100, (parameters.Type == RequestType.ModifyOrder) ? new TimeInForce?(parameters.TimeInForce) : ((TimeInForce?)null)); + ?((ICollection)list, parameters, -90, (DateTime?)null); + ?(list, parameters, -80, (parameters.Type == RequestType.ModifyOrder) ? VisibilityMode.Hidden : VisibilityMode.Visible); + ?(list, parameters, formatSettings.DisplayQuantityInLots, -70, (parameters.Type == RequestType.ModifyOrder) ? new double?(parameters.Quantity) : ((double?)null)); + if (BalanceCalculatorFactory != null) + { + if (BalanceCalculatorFactory(parameters.Symbol, parameters.Account) is CryptoBalanceCalculator) + { + ?(list, -60); + ?(list, -50); + } + ?(list, parameters.Symbol?.QuotingCurrency, -40); + ?(list, -30); + } + return list; + } + + public abstract double GetFillPrice(OrderRequestParameters parameters); + + public virtual void SetDefaultPrices(SettingItem[] settings, OrderRequestParameters parameters) + { + } + + public virtual string GetConfirmMessage(OrderRequestParameters parameters, FormatSettings formatSettings) + { + string text = string.Empty; + if (!(parameters is PlaceOrderRequestParameters placeRequest)) + { + if (parameters is ModifyOrderRequestParameters modifyRequest) + { + text = GetModifyConfirmMessage(modifyRequest, formatSettings); + } + } + else + { + text = GetPlaceConfirmMessage(placeRequest, formatSettings); + } + string additionalPartConfirmMessage = GetAdditionalPartConfirmMessage(parameters, formatSettings); + if (string.IsNullOrEmpty(additionalPartConfirmMessage)) + { + return text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + additionalPartConfirmMessage + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + + protected abstract string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings); + + protected abstract string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings); + + protected virtual string GetAdditionalPartConfirmMessage(OrderRequestParameters parameters, FormatSettings formatSettings) + { + return null; + } + + public abstract string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings); + + public virtual ValidateResult ValidateOrderRequestParameters(OrderRequestParameters parameters) + { + if (!AllowedTifs.Contains(parameters.TimeInForce)) + { + return ValidateResult.NotValid(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (parameters.StopLossItems != null) + { + foreach (SlTpHolder stopLossItem in parameters.StopLossItems) + { + if (stopLossItem.PriceMeasurement != PriceMeasurement.Absolute && stopLossItem.PriceMeasurement != SLTPPriceMeasurement) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(120, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SLTPPriceMeasurement); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(stopLossItem.PriceMeasurement); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return ValidateResult.NotValid(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + } + if (parameters.TakeProfitItems != null) + { + foreach (SlTpHolder takeProfitItem in parameters.TakeProfitItems) + { + if (takeProfitItem.PriceMeasurement != PriceMeasurement.Absolute && takeProfitItem.PriceMeasurement != SLTPPriceMeasurement) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(120, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SLTPPriceMeasurement); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(takeProfitItem.PriceMeasurement); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return ValidateResult.NotValid(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + } + return ValidateResult.Valid; + } + + public virtual IList GetDealTicketItems(OrderRequestParameters request) + { + List list = new List(); + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.Connection?.Name)); + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.Name, 1000)); + string text = Core.Instance.CustomAccountPropertiesProvider.GetProperty(request.Account, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as string; + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), string.IsNullOrEmpty(text) ? request.Account.Name : (request.Account.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()), 2000)); + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.FormatQuantity(request.Quantity), 3000)); + if (request.Type == RequestType.ModifyOrder && request is ModifyOrderRequestParameters modifyOrderRequestParameters) + { + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), modifyOrderRequestParameters.OrderId, 3500)); + } + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Side.ToString(), 4000)); + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Format(request.PositionId, request.GroupId), 5000)); + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.TimeInForce.Format(request.ExpirationTime), 6000)); + if (request.StopLossItems != null && request.StopLossItems.Count > 1) + { + for (int i = 0; i < request.StopLossItems.Count; i++) + { + string key; + if (!request.StopLoss.IsTrailing) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(12, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(i + 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + key = defaultInterpolatedStringHandler.ToStringAndClear(); + } + else + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(16, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(i + 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + key = defaultInterpolatedStringHandler.ToStringAndClear(); + } + list.Add(new DealTicketItem(key, request.StopLossItems[i].Format(request.Symbol), 6500 + i)); + } + } + else if (request.StopLoss != null) + { + list.Add(new DealTicketItem(request.StopLoss.IsTrailing ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.StopLoss.Format(request.Symbol), 6500)); + } + if (request.TakeProfitItems != null && request.TakeProfitItems.Count > 1) + { + for (int j = 0; j < request.TakeProfitItems.Count; j++) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(j + 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + list.Add(new DealTicketItem(defaultInterpolatedStringHandler.ToStringAndClear(), request.TakeProfitItems[j].Format(request.Symbol), 6510 + j)); + } + } + else if (request.TakeProfit != null) + { + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.TakeProfit.Format(request.Symbol), 6510)); + } + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Core.Instance.TimeUtils.DateTimeUtcNow.ToString(), 7000)); + if (!string.IsNullOrEmpty(request.Comment)) + { + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Comment, 8000)); + } + if (!string.IsNullOrEmpty(request.SendingSource)) + { + list.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.SendingSource, 9000)); + } + return list; + } + + private void ?(ICollection P_0, OrderRequestParameters P_1, int P_2, TimeInForce? P_3 = null) + { + List obj = P_1?.OrderType?.AllowedTifs?.ToList() ?? P_1?.Symbol?.GetAlowedOrderTypes(OrderTypeUsage.Order)?.SelectMany((OrderType orderType) => orderType.AllowedTifs).Distinct().ToList(); + obj?.Sort(new TimeInForceComparer()); + List list = obj?.Select(?).ToList(); + if (list != null && list.Any()) + { + SelectItem value = list.FirstOrDefault((SelectItem selectItem) => !P_3.HasValue || selectItem.Value.Equals((int)P_3.Value)); + P_0.Add(new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value, list, P_2) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }); + } + } + + private void ?(ICollection P_0, OrderRequestParameters P_1, int P_2, DateTime? P_3 = null) + { + TimeInForce[] array = P_1?.OrderType?.AllowedTifs; + if (array != null && (array.Contains(TimeInForce.GTD) || array.Contains(TimeInForce.GTT))) + { + DateTime minDate = Core.Instance.TimeUtils.DateTimeUtcNow.ToSelectedTimeZone(); + DateTime value = P_3 ?? minDate.AddDays(1.0); + P_0.Add(new SettingItemDateTime(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value, P_2) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + MinDate = minDate, + MaxDate = (P_1.Symbol?.ExpirationDate ?? DateTime.MaxValue), + Relation = new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ?(TimeInForce.GTD), ?(TimeInForce.GTT)) + }); + } + } + + private void ?(ICollection P_0, OrderRequestParameters P_1, int P_2, VisibilityMode P_3 = VisibilityMode.Visible) + { + List list = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1) + }; + SelectItem value = list.First(); + if (P_1 != null && P_1.Type == RequestType.ModifyOrder) + { + value = list.FirstOrDefault((SelectItem selectItem) => (int)(object)selectItem.Value == (int)P_1.Side); + } + P_0.Add(new SettingItemRadioLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value, list, P_2) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + VisibilityMode = P_3 + }); + } + + private void ?(ICollection P_0, OrderRequestParameters P_1, bool P_2, int P_3, double? P_4 = null) + { + double num = 0.0; + double maximum = 0.0; + double num2 = 1.0; + int decimalPlaces = 1; + double value = 1.0; + string dimension = null; + if (P_1 != null && P_1.Symbol?.State == BusinessObjectState.Normal) + { + double num3 = (P_2 ? 1.0 : P_1.Symbol.LotSize); + num = P_1.Symbol.MinLot * num3; + maximum = P_1.Symbol.MaxLot * num3; + num2 = (P_2 ? P_1.Symbol.LotStep : P_1.Symbol.NotionalValueStep); + decimalPlaces = CoreMath.GetValuePrecision((decimal)num2); + value = (P_4 * num3) ?? num; + dimension = P_1.Symbol.Product?.Name; + } + if (P_2) + { + dimension = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + P_0.Add(new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value, P_3) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = num, + Maximum = maximum, + Increment = num2, + DecimalPlaces = decimalPlaces, + UseTradingNumeric = true, + Dimension = dimension + }); + } + + private void ?(ICollection P_0, int P_1) + { + double num = 1.0; + int decimalPlaces = 0; + double maximum = double.MaxValue; + string empty = string.Empty; + P_0.Add(new SettingItemDoubleWithLink(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num, null, P_1) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = num, + Maximum = maximum, + Increment = num, + DecimalPlaces = decimalPlaces, + UseTradingNumeric = true, + Dimension = empty + }); + } + + private void ?(ICollection P_0, int P_1) + { + P_0.Add(new SettingItemSlider(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0uL, P_1) + { + StepsCount = 10000uL + }); + } + + private void ?(ICollection P_0, Asset P_1, int P_2) + { + P_0.Add(new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0.01, P_2) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 0.01, + Maximum = double.MaxValue, + Increment = 0.01, + DecimalPlaces = 2, + UseTradingNumeric = true, + Dimension = P_1?.Name + }); + } + + private void ?(ICollection P_0, int P_1) + { + P_0.Add(new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0.1, P_1) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 0.1, + Maximum = double.MaxValue, + Increment = 0.1, + DecimalPlaces = 1, + UseTradingNumeric = true, + Dimension = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + } + + private static SelectItem ?(TimeInForce P_0) + { + return new SelectItem(P_0.GetDescription(), (int)P_0); + } + + public int CompareTo(object obj) + { + return Id.CompareTo((obj as OrderType).Id); + } + + public static string GetSLTPComfirmMessage(OrderRequestParameters requestParameters) + { + string text = string.Empty; + try + { + bool flag = requestParameters.StopLossItems.Count > 1 || requestParameters.TakeProfitItems.Count > 1; + if (requestParameters.StopLoss != null) + { + for (int i = 0; i < requestParameters.StopLossItems.Count; i++) + { + SlTpHolder slTpHolder = requestParameters.StopLossItems[i]; + string text2 = slTpHolder.Format(requestParameters.Symbol); + string value = (flag ? (i + 1).ToString() : string.Empty); + string value2 = (flag ? (3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + requestParameters.Symbol.FormatQuantity(slTpHolder.Quantity)) : string.Empty); + if (slTpHolder.IsTrailing) + { + text = text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + text2; + } + else + { + string text3 = text; + string text4; + if (slTpHolder.PriceMeasurement != PriceMeasurement.Absolute) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(12, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(text2); + defaultInterpolatedStringHandler.AppendFormatted(value2); + text4 = defaultInterpolatedStringHandler.ToStringAndClear(); + } + else + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(text2); + defaultInterpolatedStringHandler.AppendFormatted(value2); + text4 = defaultInterpolatedStringHandler.ToStringAndClear(); + } + text = text3 + text4; + } + if (i != requestParameters.StopLossItems.Count - 1) + { + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + } + if (requestParameters.TakeProfit != null) + { + if (!string.IsNullOrEmpty(text)) + { + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + for (int j = 0; j < requestParameters.TakeProfitItems.Count; j++) + { + SlTpHolder slTpHolder2 = requestParameters.TakeProfitItems[j]; + string value3 = slTpHolder2.Format(requestParameters.Symbol); + string value4 = (flag ? (j + 1).ToString() : string.Empty); + string value5 = (flag ? (3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + requestParameters.Symbol.FormatQuantity(slTpHolder2.Quantity)) : string.Empty); + string text5 = text; + string text6 = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + string text7; + if (slTpHolder2.PriceMeasurement != PriceMeasurement.Absolute) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value3); + defaultInterpolatedStringHandler.AppendFormatted(value5); + text7 = defaultInterpolatedStringHandler.ToStringAndClear(); + } + else + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value3); + defaultInterpolatedStringHandler.AppendFormatted(value5); + text7 = defaultInterpolatedStringHandler.ToStringAndClear(); + } + text = text5 + text6 + text7; + if (j != requestParameters.TakeProfitItems.Count - 1) + { + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return text; + } + + public string Format(string positionId = null, string groupId = null) + { + if (!string.IsNullOrEmpty(positionId)) + { + string value = Behavior switch + { + OrderTypeBehavior.Limit => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + OrderTypeBehavior.Stop => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + OrderTypeBehavior.TrailingStop => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + _ => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), + }; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(positionId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + if (!string.IsNullOrEmpty(groupId)) + { + return Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return Name; + } + + public static string Format(IOrder order) + { + if (order is LocalOrder) + { + return order.OrderType.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return Format(order.OrderTypeId, order.ConnectionId, order.PositionId, order.GroupId); + } + + public static string Format(string orderTypeId, string connectionId = null, string positionId = null, string groupId = null) + { + return Core.Instance.GetOrderType(orderTypeId, connectionId)?.Format(positionId, groupId) ?? orderTypeId; + } + + public bool Equals(OrderType other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Id == other.Id) + { + return base.ConnectionId == other.ConnectionId; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((OrderType)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Id, base.ConnectionId); + } + + [CompilerGenerated] + private void ?(Rule P_0) + { + ??.?(P_0.Name, P_0); + } + } + public delegate IBalanceCalculator BalanceCalculatorFactory(Symbol symbol, Account account); +} +namespace ? +{ + internal class ? : SettingItemRelation + { + [CompilerGenerated] + private new static class ? + { + public static SettingItemRelationDelegate ??; + } + + public ?(string P_0, params object[] relationValues) + : base(new Dictionary> { + { + P_0, + new List(relationValues) + } }, ?) + { + } + + private static bool ?(SettingItemRelationParameters P_0) + { + SettingItemRelation.CheckVisibilityRelation(P_0); + if (!SettingItemRelation.CheckValues(P_0.RelationValuesByParentItem, P_0.MultipleRelationCondition) || !(P_0.DependentItem is SettingItemDateTime settingItemDateTime)) + { + return false; + } + TimeInForce value = P_0.ChangedItem.GetValue(); + settingItemDateTime.Format = ((value != TimeInForce.GTD) ? DatePickerFormat.DateTime : DatePickerFormat.Date); + return true; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public class StopLimitOrderType : LimitOrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => OrderTypeBehavior.StopLimit; + + public StopLimitOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + } + + public override IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + IList orderSettings = base.GetOrderSettings(parameters, formatSettings); + double price = 0.0; + double num = 0.0; + double minimum = 1E-05; + double increment = 1E-05; + int decimalPlaces = 5; + Symbol symbol = parameters.Symbol; + bool enabled = true; + if (symbol != null) + { + if (parameters.Type == RequestType.PlaceOrder) + { + num = ((parameters.Side == Side.Buy) ? symbol.Ask : symbol.Bid); + num = CoreMath.ProcessNaN(num); + price = symbol.CalculatePrice(num, (parameters.Side != Side.Buy) ? 1 : (-1)); + } + else if (parameters.Type == RequestType.ModifyOrder) + { + price = parameters.Price; + num = parameters.TriggerPrice; + enabled = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), parameters.Account, parameters.Symbol, this).Status == TradingOperationStatus.Allowed; + } + VariableTick variableTick = symbol.FindVariableTick(price); + if (variableTick != null) + { + minimum = variableTick.TickSize; + } + variableTick = symbol.FindVariableTick(num); + if (variableTick != null) + { + increment = variableTick.TickSize; + decimalPlaces = variableTick.Precision; + } + } + SettingItemDouble item = new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SortIndex = 0, + Minimum = minimum, + Maximum = 2147483647.0, + Increment = increment, + DecimalPlaces = decimalPlaces, + Enabled = enabled + }; + orderSettings.Add(item); + return orderSettings; + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + string value = placeRequest.TimeInForce.Format(placeRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(38, 9); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatQuantity(placeRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatPrice(placeRequest.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatPrice(placeRequest.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(placeRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + string value = modifyRequest.TimeInForce.Format(modifyRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 10); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatQuantity(modifyRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatPrice(modifyRequest.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatPrice(modifyRequest.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(modifyRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + IOrder order = cancelRequest?.Order; + if (order == null) + { + return string.Empty; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 9); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Format(order.PositionId, order.GroupId)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.TimeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatQuantity(order.TotalQuantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.Price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(cancelRequest.Order.Account.GetCurrentName()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override IList GetDealTicketItems(OrderRequestParameters request) + { + IList dealTicketItems = base.GetDealTicketItems(request); + dealTicketItems.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.FormatPrice(request.TriggerPrice), 5550)); + return dealTicketItems; + } + + public override void SetDefaultPrices(SettingItem[] settings, OrderRequestParameters parameters) + { + if (parameters.Symbol != null) + { + double num = ((parameters.Side == Side.Buy) ? parameters.Symbol.Ask : parameters.Symbol.Bid); + if (!double.IsNaN(num)) + { + double num2 = parameters.Symbol.CalculatePrice(num, (parameters.Side != Side.Buy) ? 1 : (-1)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num2); + } + } + } + } + public class StopOrderType : OrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => OrderTypeBehavior.Stop; + + public override string PriceItemId => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public StopOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + base.Usage = OrderTypeUsage.All; + } + + public override IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + IList orderSettings = base.GetOrderSettings(parameters, formatSettings); + double num = 0.0; + double num2 = 1E-05; + int decimalPlaces = 5; + Symbol symbol = parameters.Symbol; + bool enabled = true; + if (symbol != null) + { + if (parameters.Type == RequestType.PlaceOrder) + { + num = ((parameters.Side == Side.Buy) ? symbol.Bid : symbol.Ask); + num = CoreMath.ProcessNaN(num); + } + else if (parameters.Type == RequestType.ModifyOrder) + { + num = parameters.TriggerPrice; + if (double.IsNaN(num)) + { + num = parameters.Price; + } + enabled = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), parameters.Account, parameters.Symbol, this).Status == TradingOperationStatus.Allowed; + } + VariableTick obj = symbol.FindVariableTick(num) ?? symbol.VariableTickList.FirstOrDefault(); + num2 = obj.TickSize; + decimalPlaces = obj.Precision; + } + SettingItemDouble item = new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SortIndex = 0, + Minimum = num2, + Maximum = 2147483647.0, + Increment = num2, + DecimalPlaces = decimalPlaces, + Enabled = enabled + }; + orderSettings.Add(item); + return orderSettings; + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + string value = placeRequest.TimeInForce.Format(placeRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 8); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatQuantity(placeRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatPrice(placeRequest.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(placeRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + string value = modifyRequest.TimeInForce.Format(modifyRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(31, 9); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatQuantity(modifyRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatPrice(modifyRequest.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(modifyRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + IOrder order = cancelRequest?.Order; + if (order == null) + { + return string.Empty; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(31, 8); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(order.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Format(order.PositionId, order.GroupId)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.TimeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatQuantity(order.TotalQuantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(cancelRequest.Order.Account.GetCurrentName()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override ValidateResult ValidateOrderRequestParameters(OrderRequestParameters parameters) + { + ValidateResult result = base.ValidateOrderRequestParameters(parameters); + if (result.State == ValidateState.NotValid) + { + return result; + } + double triggerPrice = parameters.TriggerPrice; + if (parameters.Side == Side.Buy) + { + SlTpHolder stopLoss = parameters.StopLoss; + if (stopLoss != null && stopLoss.PriceMeasurement == PriceMeasurement.Absolute && stopLoss.Price >= triggerPrice) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + SlTpHolder takeProfit = parameters.TakeProfit; + if (takeProfit != null && takeProfit.PriceMeasurement == PriceMeasurement.Absolute && takeProfit.Price <= triggerPrice) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + } + if (parameters.Side == Side.Sell) + { + SlTpHolder stopLoss2 = parameters.StopLoss; + if (stopLoss2 != null && stopLoss2.PriceMeasurement == PriceMeasurement.Absolute && stopLoss2.Price <= triggerPrice) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + SlTpHolder takeProfit2 = parameters.TakeProfit; + if (takeProfit2 != null && takeProfit2.PriceMeasurement == PriceMeasurement.Absolute && takeProfit2.Price >= triggerPrice) + { + return ValidateResult.NotValid(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + } + return ValidateResult.Valid; + } + + public override IList GetDealTicketItems(OrderRequestParameters request) + { + IList dealTicketItems = base.GetDealTicketItems(request); + dealTicketItems.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.FormatPrice(request.TriggerPrice), 5500)); + return dealTicketItems; + } + + public override double GetFillPrice(OrderRequestParameters parameters) + { + SettingItem itemByPath = parameters.AdditionalParameters.GetItemByPath(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByPath != null) + { + return (double)itemByPath.Value; + } + return parameters.TriggerPrice; + } + + public override void SetDefaultPrices(SettingItem[] settings, OrderRequestParameters parameters) + { + if (parameters.Symbol != null) + { + double num = ((parameters.Side == Side.Buy) ? parameters.Symbol.Bid : parameters.Symbol.Ask); + if (!double.IsNaN(num)) + { + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num); + } + } + } + } + public class TrailingStopOrderType : OrderType + { + public override string Id => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Name => loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public override string Abbreviation => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override OrderTypeBehavior Behavior => OrderTypeBehavior.TrailingStop; + + public TrailingStopOrderType(params TimeInForce[] allowedTimeInForce) + : base(allowedTimeInForce) + { + base.Usage = OrderTypeUsage.All; + base.SLTPPriceMeasurement = PriceMeasurement.Offset; + } + + public override IList GetOrderSettings(OrderRequestParameters parameters, FormatSettings formatSettings) + { + IList orderSettings = base.GetOrderSettings(parameters, formatSettings); + int value = 1; + if (parameters.Type == RequestType.ModifyOrder) + { + value = (int)parameters.TrailOffset; + } + orderSettings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 1 + }); + return orderSettings; + } + + protected override string GetPlaceConfirmMessage(PlaceOrderRequestParameters placeRequest, FormatSettings formatSettings) + { + string value = placeRequest.TimeInForce.Format(placeRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 8); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatQuantity(placeRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Symbol.FormatOffset(placeRequest.TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(placeRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(placeRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override string GetModifyConfirmMessage(ModifyOrderRequestParameters modifyRequest, FormatSettings formatSettings) + { + string value = modifyRequest.TimeInForce.Format(modifyRequest.ExpirationTime); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(31, 9); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatQuantity(modifyRequest.Quantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Symbol.FormatOffset(modifyRequest.TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.GetSLTPComfirmMessage(modifyRequest)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(modifyRequest.Account.GetCurrentName()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override string GetCancelConfirmMessage(CancelOrderRequestParameters cancelRequest, FormatSettings formatSettings) + { + IOrder order = cancelRequest?.Order; + if (order == null) + { + return string.Empty; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(33, 9); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(order.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Format(order.PositionId, order.GroupId)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.TimeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatQuantity(order.TotalQuantity, formatSettings.DisplayQuantityInLots)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatPrice(order.TriggerPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Symbol.FormatOffset(order.TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(order.Account.GetCurrentName()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override IList GetDealTicketItems(OrderRequestParameters request) + { + IList dealTicketItems = base.GetDealTicketItems(request); + dealTicketItems.Add(new DealTicketItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), request.Symbol.FormatOffset(request.TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), 5500)); + return dealTicketItems; + } + + public override double GetFillPrice(OrderRequestParameters parameters) + { + double result = double.NaN; + SettingItem itemByPath = parameters.AdditionalParameters.GetItemByPath(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + int num = ((itemByPath == null) ? ((int)parameters.TrailOffset) : ((int)itemByPath.Value)); + if (parameters.Symbol != null) + { + result = ((parameters.Side != Side.Buy) ? parameters.Symbol.CalculatePrice(parameters.Symbol.Bid, -num) : parameters.Symbol.CalculatePrice(parameters.Symbol.Ask, num)); + } + return result; + } + } + /// + /// Represents trading information about related position + /// + [DataContract(Name = "Position", Namespace = "TradingPlatform")] + [Published] + public class Position : TradingObject, IMessageBuilder + { + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + private PnLItem ??; + + private PnLItem ??; + + private PnLItem ??; + + private PnLItem ??; + + [CompilerGenerated] + private double ??; + + /// + /// Gets position quantity value + /// + [DataMember(Name = "Quantity")] + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets position open order price + /// + [DataMember(Name = "OpenPrice")] + public double OpenPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets position openning time + /// + [DataMember(Name = "OpenTime")] + public DateTime OpenTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets Profit/loss (without swaps or commissions) all calculated based on the current broker's price. For open position it shows the profit/loss you would make if you close the position at the current price. If position closed, this parameter show profit/loss what trader have after closing this position. + /// + public PnLItem GrossPnL + { + get + { + return ??; + } + internal set + { + ?? = pnLItem; + } + } + + /// + /// Gets Profit/loss calculated based on the current broker's price. For open position it shows the profit/loss you would make if you close the position at the current price. If position closed, this parameter show profit/loss what trader have after closing this position. + /// + public PnLItem NetPnL + { + get + { + return ??; + } + internal set + { + ?? = pnLItem; + } + } + + /// + /// Gets fee amount for the position. + /// + public PnLItem Fee + { + get + { + return ??; + } + internal set + { + ?? = pnLItem; + } + } + + /// + /// Gets PnL swaps + /// + public PnLItem Swaps + { + get + { + return ??; + } + internal set + { + ?? = pnLItem; + } + } + + /// + /// The market price obtainable from your broker. + /// + public double CurrentPrice => ((base.Side != Side.Buy) ? base.Symbol?.Ask : base.Symbol?.Bid) ?? double.NaN; + + public double LiquidationPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets StopLoss order which belongs to the position + /// + public Order StopLoss => ConnectionCache.Orders.FirstOrDefault((Order P_0) => P_0.PositionId == base.Id && (P_0.OrderType.Behavior == OrderTypeBehavior.Stop || P_0.OrderType.Behavior == OrderTypeBehavior.TrailingStop) && P_0.OrderType.Usage.HasFlag(OrderTypeUsage.CloseOrder)); + + /// + /// Gets TakeProfit order which belongs to the position + /// + public Order TakeProfit => ConnectionCache.Orders.FirstOrDefault((Order P_0) => P_0.PositionId == base.Id && P_0.OrderType.Behavior == OrderTypeBehavior.Limit && P_0.OrderType.Usage.HasFlag(OrderTypeUsage.CloseOrder)); + + /// + /// Returns ticks amount between open and current price. + /// + public double GrossPnLTicks + { + get + { + if (base.Symbol == null || OpenPrice.IsNanOrDefault() || CurrentPrice.IsNanOrDefault()) + { + return 0.0; + } + if (base.Side == Side.Buy) + { + return base.Symbol.CalculateTicks(OpenPrice, CurrentPrice); + } + return base.Symbol.CalculateTicks(CurrentPrice, OpenPrice); + } + } + + /// + /// Will be triggered on each and invocation + /// + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + internal Position(string P_0) + : base(P_0) + { + LiquidationPrice = double.NaN; + } + + /// + /// Closes position if quantity is not specified else - uses partial closing operation. + /// + /// + /// + public virtual TradingOperationResult Close(double closeQuantity = -1.0) + { + return Core.Instance.ClosePosition(new ClosePositionRequestParameters + { + Position = this, + CloseQuantity = ((closeQuantity != -1.0) ? closeQuantity : Quantity) + }); + } + + public void ForceRecalculatePnl() + { + PnL pnL = Connection.?(new PnLRequestParameters + { + Symbol = base.Symbol, + Account = base.Account, + OpenPrice = OpenPrice, + ClosePrice = CurrentPrice, + Side = base.Side, + Quantity = Quantity, + PositionId = base.Id + }); + if (pnL != null) + { + ?(pnL); + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(18, 6); + defaultInterpolatedStringHandler.AppendFormatted(base.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Quantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Symbol.FormatPrice(OpenPrice)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Id); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + internal virtual void ?(MessageOpenPosition P_0) + { + base.Id = P_0.PositionId; + if (ConnectionCache != null && ConnectionCache.SymbolsCache.?(P_0.SymbolId, out var symbol)) + { + base.Symbol = symbol; + } + if (ConnectionCache != null && ConnectionCache.AccountsCache.?(P_0.AccountId, out var account)) + { + base.Account = account; + } + OpenPrice = P_0.OpenPrice; + OpenTime = P_0.OpenTime; + Quantity = P_0.Quantity; + base.Side = P_0.Side; + base.Comment = P_0.Comment; + LiquidationPrice = P_0.LiquidationPrice; + ProcessAdditionalItems(P_0.AdditionalInfoItems); + ???.Invoke(this); + } + + public MessageOpenPosition BuildMessage() + { + return new MessageOpenPosition(base.Symbol?.Id) + { + PositionId = base.Id, + AccountId = base.Account?.Id, + OpenPrice = OpenPrice, + OpenTime = OpenTime, + Quantity = Quantity, + Side = base.Side, + Comment = base.Comment, + LiquidationPrice = LiquidationPrice, + AdditionalInfoItems = base.AdditionalInfo?.ToList() + }; + } + + internal void ?(PnL P_0) + { + if ((0u | (?(ref ??, P_0.GrossPnL) ? 1u : 0u) | (?(ref ??, P_0.NetPnL) ? 1u : 0u) | (?(ref ??, P_0.Fee) ? 1u : 0u) | (?(ref ??, P_0.Swaps) ? 1u : 0u)) != 0) + { + ???.Invoke(this); + } + } + + private bool ?(ref PnLItem P_0, PnLItem P_1) + { + if (P_1 != null) + { + PnLItem obj = P_0; + if (obj == null || !obj.Equals(P_1)) + { + P_0 = P_1; + P_0.ConnectionId = base.ConnectionId; + return true; + } + } + return false; + } + + [CompilerGenerated] + private bool ?(Order P_0) + { + if (P_0.PositionId == base.Id && (P_0.OrderType.Behavior == OrderTypeBehavior.Stop || P_0.OrderType.Behavior == OrderTypeBehavior.TrailingStop)) + { + return P_0.OrderType.Usage.HasFlag(OrderTypeUsage.CloseOrder); + } + return false; + } + + [CompilerGenerated] + private bool ?(Order P_0) + { + if (P_0.PositionId == base.Id && P_0.OrderType.Behavior == OrderTypeBehavior.Limit) + { + return P_0.OrderType.Usage.HasFlag(OrderTypeUsage.CloseOrder); + } + return false; + } + } + /// + /// Represents a report grid which can hold system reports based on s and s content. + /// + public class Report + { + /// + /// Columns collection + /// + public List Columns; + + /// + /// Rows collection + /// + public List Rows; + + internal string ?; + + /// + /// Initializes report grid + /// + public Report() + { + Columns = new List(); + Rows = new List(); + } + + /// + /// Adds coloring column to the report + /// + public void AddColumn(string header, ComparingType valueType, ColouringModes coloringModes) + { + Columns.Add(new ReportColumn(header, valueType, coloringModes)); + } + + /// + /// Adds default(non-colored) column to the report + /// + public void AddColumn(string header, ComparingType valueType) + { + AddColumn(header, valueType, ColouringModes.None); + } + } + /// + /// Exposes report cell decoration + /// + public class ReportCell + { + /// + /// Cell label + /// + public string Label; + + /// + /// Cell value + /// + public object Value; + + public IFormattingDescription formattingDescription; + + internal ReportCell(string P_0, object P_1, IFormattingDescription P_2 = null) + { + Label = P_0; + Value = P_1; + formattingDescription = P_2; + } + } + /// + /// Exposes report column decoration + /// + public class ReportColumn + { + [CompilerGenerated] + private Color ?; + + [CompilerGenerated] + private Color ?; + + /// + /// Header of the column + /// + public string Header; + + public ColouringModes ColoringModes; + + /// + /// Column value type + /// + public ComparingType ValueType; + + public Color UpForeColor + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = color; + } + } + + public Color DownForeColor + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = color; + } + } + + internal ReportColumn(string P_0, ComparingType P_1, ColouringModes P_2) + { + Header = P_0; + ValueType = P_1; + ColoringModes = P_2; + if (P_2 == ColouringModes.Signed) + { + UpForeColor = Color.FromArgb(55, 219, 186); + DownForeColor = Color.FromArgb(235, 96, 47); + } + } + } + /// + /// Exposes report row decoration + /// + public class ReportRow + { + /// + /// A collection of cells + /// + public List Cells; + + /// + /// Initializes cells in the row + /// + public ReportRow() + { + Cells = new List(); + } + + /// + /// Adds cells to the row by label and value + /// + public void AddCell(string label, object value, IFormattingDescription formattingDescription = null) + { + Cells.Add(new ReportCell(label, value, formattingDescription)); + } + + /// + /// Adds cells to the row by value only + /// + public void AddCell(object value, IFormattingDescription formattingDescription = null) + { + if (value == null) + { + AddCell(string.Empty, string.Empty, formattingDescription); + return; + } + string label = ((!(value is double d)) ? value.ToString() : (double.IsNaN(d) ? string.Empty : d.ToString())); + AddCell(label, value, formattingDescription); + } + } + /// + /// Defines report request parameters from which can be used in + /// + public class ReportType : BusinessObject, IComparable, ICustomizable + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + private IList ??; + + /// + /// Gets report Id + /// + public int Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets report Name + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// report settings + /// + public IList Settings + { + get + { + return ??; + } + set + { + ?? = new List(); + foreach (SettingItem item in value) + { + ??.Add(item.GetCopy()); + } + } + } + + internal ReportType(string P_0) + : base(P_0) + { + ?? = new List(); + } + + internal void ?(MessageReportType P_0) + { + Id = P_0.Id; + Name = P_0.Name; + if (?? == null) + { + ?? = new List(); + } + foreach (SettingItem parameter in P_0.Parameters) + { + ??.Add(parameter); + } + } + + internal ReportType ?() + { + return new ReportType(base.ConnectionId) + { + Id = Id, + Name = Name, + Settings = Settings + }; + } + + public int CompareTo(object obj) + { + return 0; + } + } +} +namespace ? +{ + internal interface ? + { + int PriorityIndex { get; } + + ? Rules { get; } + } +} +namespace TradingPlatform.BusinessLayer +{ + public abstract class Rule + { + public const string ALLOW_TRADING = "Allow trading"; + + public const string ALLOW_SCREENER = "Allow screener"; + + public const string ALLOW_CONTAINS_SCREENER_CONDITIONS = "Allow 'contains' screener conditions"; + + public const string ALLOW_NEWS = "Allow news"; + + public const string ALLOW_SL = "Allow SL"; + + public const string ALLOW_TP = "Allow TP"; + + public const string ALLOW_SL_TRAILING = "Allow SL Trailing"; + + public const string ALLOW_TP_TRAILING = "Allow TP Trailing"; + + public const string ALLOW_MULTI_SL_TP = "ALLOW_MULTI_SL_TP"; + + public const string ALLOW_MODIFY_ORDER = "Allow modify order"; + + public const string ALLOW_MODIFY_ORDER_TYPE = "Allow modify order type"; + + public const string ALLOW_MODIFY_AMOUNT = "Allow modify amount"; + + public const string ALLOW_MODIFY_PRICE = "Allow modify price"; + + public const string ALLOW_MODIFY_TIF = "Allow modify tif"; + + public const string ALLOW_CHANGE_TO_MARKET = "Allow change to market"; + + public const string ALLOW_REVERSE_POSITION = "Allow reverse position"; + + public const string ALLOW_REDUCE_ONLY = "Allow reduce-only"; + + public const string ALLOW_EXPORT = "Allow export"; + + public const string ALLOW_LINK_OCO = "Allow Link OCO"; + + public const string ALLOW_NEW_OCO = "Allow New OCO"; + + public const string ALLOW_GROUP_ORDERS = "Allow group orders"; + + public const string ALLOW_PARTIAL_CLOSE_POSITION = "Allow partial close position"; + + public const string DEFAULT_SHOW_STRIKES_COUNT = "DEFAULT_SHOW_STRIKES_COUNT"; + + public const string LEVEL2_IS_AGGREGATED = "LEVEL2_IS_AGGREGATED"; + + public const string LEVEL2_HAS_IMPLIED_SIZE = "LEVEL2_HAS_IMPLIED_SIZE"; + + public const string PLACE_ORDER_TRADING_OPERATION_HAS_ORDER_ID = "PLACE_ORDER_TRADING_OPERATION_HAS_ORDER_ID"; + + public const string ALLOW_VOLUME_ANALYSIS_FROM_TICK_HISTORY = "ALLOW_VOLUME_ANALYSIS_FROM_TICK_HISTORY"; + + [CompilerGenerated] + private string ?; + + internal string Name + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = text; + } + } + + protected Rule(string name) + { + Name = name; + } + + internal virtual void ?(MessageRule P_0) + { + Name = P_0.Name; + } + + internal static Rule ?(MessageRule P_0) + { + object value = P_0.Value; + if (!(value is string text)) + { + if (!(value is int num)) + { + if (value is bool flag) + { + return new ?(P_0.Name, flag); + } + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + return new ?(P_0.Name, num); + } + return new ?(P_0.Name, text); + } + } +} +namespace ? +{ + internal sealed class ? : Rule + { + [CompilerGenerated] + private ? ??; + + internal ? Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = val; + } + } + + internal ?(string P_0, ? P_1) + : base(P_0) + { + Value = P_1; + } + + internal override void ?(MessageRule P_0) + { + if (!(P_0.Value is ? value)) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + typeof(?).Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + base.?(P_0); + Value = value; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// Represents a permisions checking tool which use next priority order , , and + /// + public sealed class RulesManager + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal bool ?(FieldInfo P_0) + { + if (P_0.IsLiteral) + { + return !P_0.IsInitOnly; + } + return false; + } + + internal bool ?(FieldInfo P_0) + { + return P_0.FieldType == typeof(string); + } + + internal string ?(FieldInfo P_0) + { + return P_0.GetValue(null) as string; + } + + internal Symbol ?(SyntheticItem P_0) + { + return P_0.Symbol; + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? where ? : Rule + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(? P_0) + { + return P_0 != null; + } + + internal int ?(? P_0) + { + return P_0.PriorityIndex; + } + } + + internal static HashSet ?; + + internal const int ? = 0; + + internal const int ? = 10; + + internal const int ? = 20; + + internal const int ? = 30; + + internal List Defaults => new List + { + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), true) + }; + + static RulesManager() + { + ? = new HashSet(from P_0 in typeof(CoreLicenceKeys).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy) + where P_0.IsLiteral && !P_0.IsInitOnly + where P_0.FieldType == typeof(string) + select P_0.GetValue(null) as string); + } + + public AllowedResult IsAllowed(string ruleName, string connectionId) + { + ?(ruleName); + return ?(ruleName, ?(connectionId)); + } + + public AllowedResult IsAllowed(string ruleName, Account account) + { + ?(ruleName, account); + return ?(ruleName, ?(account.ConnectionId), account); + } + + public AllowedResult IsAllowed(string ruleName, Symbol symbol) + { + ?(ruleName, symbol); + if (ruleName != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() || !(symbol is Synthetic synthetic)) + { + return ?(ruleName, ?(symbol.ConnectionId), symbol); + } + ?[] rulesContainers = synthetic.LegsConnectionsIds.Select(?).Cast().Concat(synthetic.Items.Select((SyntheticItem P_0) => P_0.Symbol)) + .ToArray(); + return ?(ruleName, rulesContainers); + } + + public AllowedResult IsAllowed(string ruleName, Account account, Symbol symbol) + { + ?(ruleName, account, symbol); + return ?(ruleName, ?(account.ConnectionId), account, symbol); + } + + public AllowedResult IsAllowed(string ruleName, Account account, Symbol symbol, OrderType orderType) + { + ?(ruleName, account, symbol, orderType); + return ?(ruleName, ?(account.ConnectionId), account, symbol, orderType); + } + + public int GetIntValue(string ruleName, string connectionId) + { + ?(ruleName); + return ?(ruleName, ?(connectionId)); + } + + public int GetIntValue(string ruleName, Account account) + { + ?(ruleName, account); + return ?(ruleName, ?(account.ConnectionId), account); + } + + public int GetIntValue(string ruleName, Account account, Symbol symbol) + { + ?(ruleName, account, symbol); + return ?(ruleName, ?(account.ConnectionId), account, symbol); + } + + public int GetIntValue(string ruleName, Account account, Symbol symbol, OrderType orderType) + { + ?(ruleName, account, symbol, orderType); + return ?(ruleName, ?(account.ConnectionId), account, symbol, orderType); + } + + public string GetStringValue(string ruleName, string connectionId) + { + ?(ruleName); + return ?(ruleName, ?(connectionId)); + } + + public string GetStringValue(string ruleName, Account account) + { + ?(ruleName, account); + return ?(ruleName, ?(account.ConnectionId), account); + } + + public string GetStringValue(string ruleName, Account account, Symbol symbol) + { + ?(ruleName, account, symbol); + return ?(ruleName, ?(account.ConnectionId), account, symbol); + } + + public string GetStringValue(string ruleName, Account account, Symbol symbol, OrderType orderType) + { + ?(ruleName, account, symbol, orderType); + return ?(ruleName, ?(account.ConnectionId), account, symbol, orderType); + } + + private AllowedResult ?(string P_0, params ?[] rulesContainers) + { + IEnumerable> enumerable = ?>(P_0, rulesContainers); + if (enumerable.Count() == 0) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + foreach (? item in enumerable) + { + if (!item.Value) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + } + return AllowedResult.GetAllowedResult(); + } + + private int ?(string P_0, params ?[] rulesContainers) + { + return ?>(P_0, rulesContainers).LastOrDefault()?.Value ?? (-1); + } + + private string ?(string P_0, params ?[] rulesContainers) + { + return ?>(P_0, rulesContainers).LastOrDefault()?.Value ?? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + + private IEnumerable ?(string P_0, params ?[] rulesContainers) where ? : Rule + { + IOrderedEnumerable orderedEnumerable = from ? in rulesContainers + where ? != null + orderby ?.PriorityIndex + select ?; + foreach (? item in orderedEnumerable) + { + if (item.Rules != null && item.Rules.?(P_0, out var rule) && rule is ? val) + { + yield return val; + } + } + } + + private ? ?(string P_0) + { + return Core.Instance.Connections[P_0]?.??; + } + + private void ?(string P_0) + { + if (string.IsNullOrEmpty(P_0)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + } + + private void ?(string P_0, Account P_1) + { + ?(P_0); + if (P_1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + } + + private void ?(string P_0, Symbol P_1) + { + ?(P_0); + if (P_1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + } + + private void ?(string P_0, Account P_1, Symbol P_2) + { + ?(P_0, P_1); + if (P_2 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (P_2.SymbolType == SymbolType.Synthetic || !(P_1.ConnectionId != P_2.ConnectionId)) + { + return; + } + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + + private void ?(string P_0, Account P_1, Symbol P_2, OrderType P_3) + { + ?(P_0, P_1, P_2); + if (P_3 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (P_2.SymbolType == SymbolType.Synthetic || !(P_1.ConnectionId != P_3.ConnectionId)) + { + return; + } + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + } + [ProtoContract] + public class HolidayInfo : IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [ProtoMember(1)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public DateTime Date + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HolidayInfo() + { + } + + internal HolidayInfo(HolidayInfo P_0) + { + Name = P_0.Name; + Date = P_0.Date; + } + + public override string ToString() + { + return Core.Instance.TimeUtils.GetFormatedDate(Core.Instance.TimeUtils.ConvertFromSelectedTimeZoneToUTC(Date)) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Name; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Date)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Name = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Date = xElement2.ToDateTime(toUTC: true); + } + } + } + [ProtoContract] + public class Session : ISession, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private SessionType ??; + + [CompilerGenerated] + private bool ??; + + [ProtoMember(1)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + [ProtoMember(2)] + public TimeSpan OpenTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + [ProtoMember(3)] + public TimeSpan CloseTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + [ProtoMember(4)] + public SessionType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = sessionType; + } + } + + [ProtoMember(5)] + public bool IsPrimary + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Session(string name, TimeSpan openTime, TimeSpan closeTime, SessionType type = SessionType.Main, bool isPrimary = false) + : this() + { + Name = name; + OpenTime = openTime; + CloseTime = closeTime; + Type = type; + IsPrimary = isPrimary; + } + + public Session(Session session) + : this(session.Name, session.OpenTime, session.CloseTime, session.Type, session.IsPrimary) + { + } + + internal Session() + { + Type = SessionType.Main; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OpenTime)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OpenTime)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Type)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsPrimary)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Name = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + OpenTime = xElement2.ToTimeSpan(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + CloseTime = xElement3.ToTimeSpan(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + Type = (SessionType)xElement4.ToInt(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + IsPrimary = xElement5.ToBool(); + } + } + } + public class SessionsContainer : BusinessObject, ISessionsContainer, IMessageBuilder + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal IEnumerable ?(SessionsSet P_0) + { + return P_0.Sessions; + } + + internal HolidayInfo ?(HolidayInfo P_0) + { + return new HolidayInfo(P_0); + } + + internal SessionsSet ?(SessionsSet P_0) + { + return new SessionsSet(P_0); + } + + internal HolidayInfo ?(HolidayInfo P_0) + { + return new HolidayInfo(P_0); + } + + internal SessionsSet ?(SessionsSet P_0) + { + return new SessionsSet(P_0); + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + public DayOfWeek ??; + + public Func ??; + + public Func ??; + + internal bool ?(HolidayInfo P_0) + { + return P_0.Date.Date == ??.Date; + } + + internal bool ?(SessionsSet P_0) + { + return P_0.CertainDates?.Any((DateTime dateTime) => dateTime.Date == ??.Date) ?? false; + } + + internal bool ?(DateTime P_0) + { + return P_0.Date == ??.Date; + } + + internal bool ?(SessionsSet P_0) + { + return P_0.Days?.Any((DayOfWeek dayOfWeek) => dayOfWeek == ??) ?? false; + } + + internal bool ?(DayOfWeek P_0) + { + return P_0 == ??; + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private HolidayInfo[] ??; + + [CompilerGenerated] + private SessionsSet[] ??; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public HolidayInfo[] Holidays + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + public SessionsSet[] SessionsSets + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + public ISession[] ActiveSessions => SessionsSets?.SelectMany((SessionsSet P_0) => P_0.Sessions).Cast().ToArray(); + + public TimeZoneInfo TimeZone => null; + + internal SessionsContainer(string P_0) + : base(P_0) + { + } + + public void UpdateByMessage(MessageSessionsContainer message) + { + Id = message.Id; + Name = message.Name; + Description = message.Description; + Holidays = message.Holidays?.Select((HolidayInfo P_0) => new HolidayInfo(P_0)).ToArray(); + SessionsSets = message.SessionsSets?.Select((SessionsSet P_0) => new SessionsSet(P_0)).ToArray(); + } + + public ISession[] GetSessionsForDate(DateTime dateTime) + { + if (Holidays?.FirstOrDefault((HolidayInfo P_0) => P_0.Date.Date == dateTime.Date) != null) + { + return Array.Empty(); + } + DayOfWeek ?? = dateTime.DayOfWeek; + return (SessionsSets.FirstOrDefault((SessionsSet P_0) => P_0.CertainDates?.Any((DateTime dateTime2) => dateTime2.Date == dateTime.Date) ?? false) ?? SessionsSets.FirstOrDefault((SessionsSet P_0) => P_0.Days?.Any((DayOfWeek dayOfWeek) => dayOfWeek == ??) ?? false))?.Sessions.Cast().ToArray() ?? Array.Empty(); + } + + public MessageSessionsContainer BuildMessage() + { + return new MessageSessionsContainer + { + Id = Id, + Name = Name, + Description = Description, + Holidays = Holidays?.Select((HolidayInfo P_0) => new HolidayInfo(P_0)).ToArray(), + SessionsSets = SessionsSets?.Select((SessionsSet P_0) => new SessionsSet(P_0)).ToArray() + }; + } + } + [ProtoContract] + public class SessionsSet : IXElementSerialization + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal Session ?(Session P_0) + { + return new Session(P_0); + } + + internal DayOfWeek ?(XElement P_0) + { + return (DayOfWeek)P_0.ToInt(); + } + + internal DateTime ?(XElement P_0) + { + return P_0.ToDateTime(toUTC: true); + } + } + + [CompilerGenerated] + private Session[] ??; + + [CompilerGenerated] + private DayOfWeek[] ??; + + [CompilerGenerated] + private DateTime[] ??; + + [ProtoMember(1)] + public Session[] Sessions + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public DayOfWeek[] Days + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public DateTime[] CertainDates + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SessionsSet() + { + } + + internal SessionsSet(SessionsSet P_0) + { + Sessions = P_0.Sessions.Select((Session session) => new Session(session)).ToArray(); + Days = P_0.Days?.Clone() as DayOfWeek[]; + CertainDates = P_0.CertainDates?.ToArray(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Session[] sessions = Sessions; + foreach (Session session in sessions) + { + xElement2.Add(session.ToXElement()); + } + xElement.Add(xElement2); + XElement xElement3 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DayOfWeek[] days = Days; + foreach (DayOfWeek dayOfWeek in days) + { + xElement3.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)dayOfWeek)); + } + xElement.Add(xElement3); + if (CertainDates != null) + { + XElement xElement4 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DateTime[] certainDates = CertainDates; + foreach (DateTime dateTime in certainDates) + { + xElement4.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), dateTime)); + } + xElement.Add(xElement4); + } + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + List list = new List(); + foreach (XElement item in xElement.Elements()) + { + Session session = new Session(); + session.FromXElement(item, deserializationInfo); + list.Add(session); + } + Sessions = list.ToArray(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Days = (from P_0 in xElement2.Elements() + select (DayOfWeek)P_0.ToInt()).ToArray(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + CertainDates = (from P_0 in xElement3.Elements() + select P_0.ToDateTime(toUTC: true)).ToArray(); + } + } + } + /// + /// Represent access to symbol information and properties. + /// + [Published] + public class Symbol : BusinessObject, IComparable, ?, IMessageBuilder, IMessageBuilder, IEquatable, IConnectionStateDependent + { + [CompilerGenerated] + private static class ? + { + public static Func ??; + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal double ?(double P_0, double P_1) + { + return P_0; + } + + internal long ?(long P_0, long P_1) + { + return P_0; + } + + internal DateTime ?(DateTime P_0, DateTime P_1) + { + return P_0; + } + + internal long ?(long P_0, long P_1) + { + if (P_0 < 0) + { + return P_1; + } + return P_0; + } + + internal DateTime ?(DateTime P_0, DateTime P_1) + { + if (!(P_0 != default(DateTime))) + { + return P_1; + } + return P_0; + } + + internal string ?(Exchange P_0) + { + return P_0.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public MessageSymbolInfo ??; + + internal bool ?(OptionSerie P_0) + { + return P_0.Id == ??.OptionSerieId; + } + } + + [CompilerGenerated] + private sealed class ? + { + public OrderTypeUsage? ??; + + internal bool ?(OrderType P_0) + { + return P_0.Usage.HasFlag(??); + } + } + + public const string SPOT_SYMBOL_ID = "spotSymbolId"; + + public const string TRADING_SYMBOL_ID = "TradingSymbol"; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private SymbolType ??; + + [CompilerGenerated] + private Asset ??; + + [CompilerGenerated] + private Asset ??; + + private Exchange ??; + + private string ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private AdditionalInfoCollection ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private NettingType ??; + + [CompilerGenerated] + private SymbolGroup ??; + + [CompilerGenerated] + private SymbolQuotingType ??; + + [CompilerGenerated] + private double ??; + + private List ??; + + private double? ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private OptionCodingStyle ??; + + [CompilerGenerated] + private OptionType ??; + + [CompilerGenerated] + private OptionSerie ??; + + [CompilerGenerated] + private string ??; + + private Symbol ??; + + private string ??; + + [CompilerGenerated] + private AvailableDerivatives ??; + + [CompilerGenerated] + private AvailableDerivatives ??; + + private List ??; + + [CompilerGenerated] + private FutureContractType? ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private DepthOfMarket ??; + + private double ??; + + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + private readonly object ??; + + private TickDirection ??; + + private TickDirection ??; + + private TickDirection ??; + + [CompilerGenerated] + private HistoryType ??; + + protected HistoryMetadata historyMetadata; + + [CompilerGenerated] + private SymbolVolumeType ??; + + protected VolumeAnalysisMetadata volumeAnalysisMetadata; + + private QuoteHandler ??; + + private Level2Handler ??; + + private LastHandler ??; + + private MarkHandler ??; + + [CompilerGenerated] + private DayBarHandler ??; + + [CompilerGenerated] + private SymbolUpdateHandler ??; + + private readonly ? ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private DeltaCalculationType ??; + + [CompilerGenerated] + private double ??; + + private string ??; + + private const double ?? = 1.0 / 32.0; + + private const double ?? = 1.0 / 64.0; + + private const double ?? = 1.0 / 128.0; + + private const double ?? = 1.0 / 256.0; + + /// + /// Gets symbol Id + /// + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public SymbolComplexIdentifier ComplexId => new SymbolComplexIdentifier(base.ConnectionId, ExchangeId, Id); + + /// + /// Gets symbol name + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + /// + /// Gets symbol description + /// + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets symbol type + /// + public SymbolType SymbolType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbolType; + } + } + + /// + /// Gets symbol base Asset + /// + public Asset Product + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + /// + /// Gets symbol counter Asset + /// + public Asset QuotingCurrency + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + /// + /// Gets Exchange of current symbol + /// + public Exchange Exchange + { + get + { + return ??; + } + protected set + { + ?? = value; + ExchangeId = Exchange?.Id; + } + } + + /// + /// Gets Exchange id of current symbol + /// + public string ExchangeId + { + get + { + return Exchange?.Id ?? ??; + } + private set + { + ?? = text; + } + } + + /// + /// Returns delay with which quote come in platform. + /// + public TimeSpan QuoteDelay + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + /// + /// Gets symbol additional info + /// + [NotPublished] + public AdditionalInfoCollection AdditionalInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = additionalInfoCollection; + } + } + + /// + /// The highest trade allowed + /// + public double MaxLot + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// The lowest trade allowed + /// + public double MinLot + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets symbol NettingType + /// + public NettingType NettingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = nettingType; + } + } + + /// + /// Gets SymbolGroup + /// + public SymbolGroup Group + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + /// + /// Gets current SymbolQuotingType + /// + public SymbolQuotingType QuotingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbolQuotingType; + } + } + + /// + /// Amount of base asset for one lot. + /// + public double LotSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Stores list of symbol ticksizes + /// + public List VariableTickList + { + get + { + return ??; + } + private set + { + ?? = list; + List list2 = ??; + if (list2 != null && list2.Count == 1) + { + ?? = ??[0].TickSize; + } + else + { + ?? = null; + } + } + } + + /// + /// Step of the lot changes + /// + public double LotStep + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Step of the notional value changes + /// + public double NotionalValueStep + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets derivative expiration date + /// + public DateTime ExpirationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets derivative last trading date + /// + public DateTime LastTradingDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets derivative maturity date + /// + public DateTime MaturityDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets derivative strike price + /// + [NotPublished] + public double StrikePrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets derivative option style + /// + [NotPublished] + public OptionCodingStyle OptionStyle + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = optionCodingStyle; + } + } + + /// + /// Gets derivative option type + /// + [NotPublished] + public OptionType OptionType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = optionType; + } + } + + /// + /// Gets derivative option serie + /// + [NotPublished] + public OptionSerie OptionSerie + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = optionSerie; + } + } + + /// + /// Gets derivative underlier name + /// + public string Root + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets derivative underlier symbol + /// + public Symbol Underlier + { + get + { + return ??; + } + private set + { + ?? = symbol; + UnderlierId = Underlier?.Id; + } + } + + /// + /// Gets derivative underlier symbol id + /// + public string UnderlierId + { + get + { + return Underlier?.Id ?? ??; + } + private set + { + ?? = text; + } + } + + public AvailableDerivatives AvailableFutures + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = availableDerivatives; + } + } + + public AvailableDerivatives AvailableOptions + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = availableDerivatives; + } + } + + public Exchange[] AvailableOptionsExchanges => ??.ToArray(); + + public FutureContractType? FutureContractType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = futureContractType; + } + } + + /// + /// Gets Ask price + /// + public double Ask + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets Ask size + /// + public double AskSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets Bid price + /// + public double Bid + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets Bid size + /// + public double BidSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets quote time + /// + public DateTime QuoteDateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets last price + /// + public double Last + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets last size + /// + public double LastSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets last time + /// + public DateTime LastDateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Gets mark price + /// + public double Mark + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets mark size + /// + public double MarkSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets open price + /// + public double Open + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets previous close price + /// + public double PrevClose + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets high price + /// + public double High + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets low price + /// + public double Low + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets volume value + /// + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets quote asset volume value + /// + public double QuoteAssetVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets PrevSettlement value + /// + [NotPublished] + public double PrevSettlement + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets ticks amount + /// + public long Ticks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets trades amount + /// + public long Trades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets Level2 data + /// + public DepthOfMarket DepthOfMarket + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = depthOfMarket; + } + } + + /// + /// Gets spread value between Bid and Ask + /// + public double Spread + { + get + { + if (double.IsNaN(Bid) || double.IsNaN(Ask)) + { + return double.NaN; + } + return CalculateTicks(Bid, Ask); + } + } + + /// + /// Gets percentage value + /// + public double SpreadPercentage + { + get + { + if (double.IsNaN(Bid) || double.IsNaN(Ask)) + { + return double.NaN; + } + decimal num = (decimal)Ask; + decimal num2 = (decimal)Bid; + decimal num3 = (num + num2) / 2m; + if (num3 == 0m) + { + return double.NaN; + } + return (double)((num - num2) / num3 * 100m); + } + } + + /// + /// Gets change value between Bid/Last and Close price + /// + public double Change + { + get + { + if (AllowCalculateRealtimeChange) + { + return CurrentPrice - ClosePrice; + } + return ??; + } + } + + /// + /// Gets percentage value + /// + public double ChangePercentage + { + get + { + if (AllowCalculateRealtimeChange) + { + double change = Change; + double closePrice = ClosePrice; + if (double.IsNaN(change) || double.IsNaN(closePrice) || closePrice == 0.0) + { + return double.NaN; + } + return (double)((decimal)change / Math.Abs((decimal)closePrice) * 100m); + } + return ??; + } + } + + private double CurrentPrice => HistoryType switch + { + HistoryType.Ask => Ask, + HistoryType.Last => Last, + HistoryType.Midpoint => (Bid + Ask) / 2.0, + HistoryType.Mark => Mark, + _ => Bid, + }; + + private double ClosePrice + { + get + { + if (!double.IsNaN(PrevSettlement) && PrevSettlement != 0.0) + { + return PrevSettlement; + } + return PrevClose; + } + } + + public double OpenInterest + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double FundingRate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public DateTime FundingTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public double TopPriceLimit + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double BottomPriceLimit + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double AverageTradedPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double TotalBuyQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double TotalSellQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double IV + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Delta + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Vega + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Gamma + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Theta + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Rho + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + internal bool HasAnySubscription => QuotesSubscribed | Level2Subscribed | LastsSubscribed | MarkSubscribed; + + /// + /// Default history type + /// + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = historyType; + } + } + + /// + /// List of all available history types + /// + [NotPublished] + public virtual HistoryMetadata HistoryMetadata + { + get + { + HistoryMetadata historyMetaData = historyMetadata; + if (historyMetaData == null) + { + Connection connection = Connection; + if (connection == null) + { + return null; + } + historyMetaData = connection.HistoryMetaData; + } + return historyMetaData; + } + } + + /// + /// Gets SymbolVolumeType + /// + public SymbolVolumeType VolumeType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbolVolumeType; + } + } + + /// + /// List of all available history types + /// + [NotPublished] + public virtual VolumeAnalysisMetadata VolumeAnalysisMetadata + { + get + { + VolumeAnalysisMetadata obj = volumeAnalysisMetadata; + if (obj == null) + { + Connection connection = Connection; + if (connection == null) + { + return null; + } + obj = connection.VolumeAnalysisMetadata; + } + return obj; + } + } + + internal bool QuotesSubscribed => ?? != null; + + internal bool Level2Subscribed => ?? != null; + + internal bool LastsSubscribed => ?? != null; + + internal bool MarkSubscribed => ?? != null; + + int ?.PriorityIndex => 20; + + ? ?.Rules => ??; + + /// + /// Gets real time calculation setting + /// + [NotPublished] + public bool AllowCalculateRealtimeTicks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + /// + /// Gets real time calculation setting + /// + [NotPublished] + public bool AllowCalculateRealtimeTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + /// + /// Gets real time calculation setting + /// + [NotPublished] + public bool AllowCalculateRealtimeVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + /// + /// Gets real time calculation setting + /// + [NotPublished] + public bool AllowCalculateRealtimeChange + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + [NotPublished] + public bool AllowAbbreviatePriceByTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DeltaCalculationType DeltaCalculationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = deltaCalculationType; + } + } + + public double MinVolumeAnalysisTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public SessionsContainer CurrentSessionsInfo + { + get + { + if (string.IsNullOrEmpty(??)) + { + return Exchange?.CurrentSessionsInfo; + } + if (ConnectionCache?.TradingSessions == null) + { + return null; + } + ConnectionCache.TradingSessions.TryGetValue(??, out var value); + return value; + } + } + + internal int TotalSubscriptionsCount => (LastsSubscribed ? 1 : 0) + (MarkSubscribed ? 1 : 0) + (QuotesSubscribed ? 1 : 0) + (Level2Subscribed ? 1 : 0); + + /// + /// Gets cached tick size if it available, else tries to obtain with Last, Bid, Ask, first element of list otherwise - + /// + public double TickSize + { + get + { + if (??.HasValue) + { + return ??.Value; + } + if (!double.IsNaN(Last)) + { + return GetTickSize(Last); + } + if (!double.IsNaN(Bid)) + { + return GetTickSize(Bid); + } + if (!double.IsNaN(Ask)) + { + return GetTickSize(Ask); + } + return VariableTickList?.FirstOrDefault()?.TickSize ?? double.NaN; + } + } + + /// + /// Will be triggered when new Level1 quote is comming + /// + public event QuoteHandler NewQuote + { + add + { + ?(ref ??, value, SubscribeQuoteType.Quote); + } + remove + { + ?(ref ??, value, SubscribeQuoteType.Quote); + } + } + + /// + /// Will be triggered when new Level2 quote is comming + /// + public event Level2Handler NewLevel2 + { + add + { + ?(ref ??, value, SubscribeQuoteType.Level2); + } + remove + { + ?(ref ??, value, SubscribeQuoteType.Level2); + } + } + + /// + /// Will be triggered when new trade quote is comming + /// + public event LastHandler NewLast + { + add + { + ?(ref ??, value, SubscribeQuoteType.Last); + } + remove + { + ?(ref ??, value, SubscribeQuoteType.Last); + } + } + + public event MarkHandler NewMark + { + add + { + ?(ref ??, value, SubscribeQuoteType.Mark); + } + remove + { + ?(ref ??, value, SubscribeQuoteType.Mark); + } + } + + /// + /// Will be triggered when new correctional quote is comming from the vendor. + /// + public event DayBarHandler NewDayBar + { + [CompilerGenerated] + add + { + DayBarHandler dayBarHandler = ??; + DayBarHandler dayBarHandler2; + do + { + dayBarHandler2 = dayBarHandler; + DayBarHandler value2 = (DayBarHandler)Delegate.Combine(dayBarHandler2, value); + dayBarHandler = Interlocked.CompareExchange(ref ??, value2, dayBarHandler2); + } + while ((object)dayBarHandler != dayBarHandler2); + } + [CompilerGenerated] + remove + { + DayBarHandler dayBarHandler = ??; + DayBarHandler dayBarHandler2; + do + { + dayBarHandler2 = dayBarHandler; + DayBarHandler value2 = (DayBarHandler)Delegate.Remove(dayBarHandler2, value); + dayBarHandler = Interlocked.CompareExchange(ref ??, value2, dayBarHandler2); + } + while ((object)dayBarHandler != dayBarHandler2); + } + } + + /// + /// Will be triggered when symbol updated. + /// + public event SymbolUpdateHandler Updated + { + [CompilerGenerated] + add + { + SymbolUpdateHandler symbolUpdateHandler = ??; + SymbolUpdateHandler symbolUpdateHandler2; + do + { + symbolUpdateHandler2 = symbolUpdateHandler; + SymbolUpdateHandler value2 = (SymbolUpdateHandler)Delegate.Combine(symbolUpdateHandler2, value); + symbolUpdateHandler = Interlocked.CompareExchange(ref ??, value2, symbolUpdateHandler2); + } + while ((object)symbolUpdateHandler != symbolUpdateHandler2); + } + [CompilerGenerated] + remove + { + SymbolUpdateHandler symbolUpdateHandler = ??; + SymbolUpdateHandler symbolUpdateHandler2; + do + { + symbolUpdateHandler2 = symbolUpdateHandler; + SymbolUpdateHandler value2 = (SymbolUpdateHandler)Delegate.Remove(symbolUpdateHandler2, value); + symbolUpdateHandler = Interlocked.CompareExchange(ref ??, value2, symbolUpdateHandler2); + } + while ((object)symbolUpdateHandler != symbolUpdateHandler2); + } + } + + private void ?(ref ? P_0, ? P_1, SubscribeQuoteType P_2) where ? : Delegate + { + lock (??) + { + if (P_0 == null) + { + SubscribeAction(P_2); + } + P_0 = (?)Delegate.Combine(P_0, P_1); + } + } + + private void ?(ref ? P_0, ? P_1, SubscribeQuoteType P_2) where ? : Delegate + { + lock (??) + { + bool flag = P_0 != null; + P_0 = (?)Delegate.Remove(P_0, P_1); + if (P_0 == null && flag) + { + UnSubscribeAction(P_2); + } + } + } + + protected internal Symbol() + { + } + + [NotPublished] + protected internal Symbol(string connectionId) + : base(connectionId) + { + ?? = new object(); + ?(); + ?? = new ?(); + Core.Instance.RulesManager.Defaults.ForEach(delegate(Rule P_0) + { + ??.?(P_0.Name, P_0); + }); + } + + private protected void ?() + { + NettingType = NettingType.Undefined; + Ask = double.NaN; + AskSize = double.NaN; + Bid = double.NaN; + BidSize = double.NaN; + Last = double.NaN; + LastSize = double.NaN; + Mark = double.NaN; + MarkSize = double.NaN; + Open = double.NaN; + PrevClose = double.NaN; + High = double.NaN; + Low = double.NaN; + Volume = double.NaN; + QuoteAssetVolume = double.NaN; + PrevSettlement = double.NaN; + ?? = double.NaN; + ?? = double.NaN; + OpenInterest = double.NaN; + FundingRate = double.NaN; + TopPriceLimit = double.NaN; + BottomPriceLimit = double.NaN; + TotalBuyQuantity = double.NaN; + TotalSellQuantity = double.NaN; + IV = double.NaN; + Delta = double.NaN; + Vega = double.NaN; + Gamma = double.NaN; + Theta = double.NaN; + Rho = double.NaN; + Ticks = 0L; + Trades = 0L; + DepthOfMarket = new DepthOfMarket(this); + AllowCalculateRealtimeTicks = true; + AllowCalculateRealtimeTrades = true; + AllowCalculateRealtimeVolume = true; + AllowCalculateRealtimeChange = true; + DeltaCalculationType = DeltaCalculationType.AggressorFlag; + MinVolumeAnalysisTickSize = double.NaN; + AvailableFutures = AvailableDerivatives.None; + AvailableOptions = AvailableDerivatives.None; + MinLot = 1.0; + MaxLot = 2147483647.0; + LotStep = 1.0; + LotSize = 1.0; + NotionalValueStep = 1.0; + ?? = new List(); + } + + [NotPublished] + protected internal Symbol(BusinessObjectInfo objectInfo) + : this(objectInfo.ConnectionId) + { + Id = objectInfo.Id; + Name = objectInfo.Name; + State = BusinessObjectState.Fake; + if (objectInfo is SymbolInfo symbolInfo) + { + ExchangeId = symbolInfo.ExchangeId; + SymbolType = symbolInfo.SymbolType; + FutureContractType = symbolInfo.FutureContractType; + UnderlierId = symbolInfo.UnderlierId; + Root = symbolInfo.Root; + ExpirationDate = symbolInfo.ExpirationDate; + } + } + + internal void ?(MessageSymbolInfo P_0) + { + if (string.IsNullOrEmpty(Id)) + { + Id = P_0.Id; + } + Name = P_0.Name; + Description = P_0.Description; + SymbolType = P_0.SymbolType; + AvailableFutures = P_0.AvailableFutures; + AvailableOptions = P_0.AvailableOptions; + Root = P_0.Root; + LotStep = P_0.LotStep; + MinLot = P_0.MinLot; + MaxLot = P_0.MaxLot; + HistoryType = P_0.HistoryType; + VariableTickList = P_0.VariableTickList; + StrikePrice = P_0.StrikePrice; + OptionType = P_0.OptionType; + ExpirationDate = P_0.ExpirationDate; + LastTradingDate = P_0.LastTradingDate; + FutureContractType = P_0.FutureContractType; + if (ConnectionCache != null && !string.IsNullOrEmpty(P_0.ExchangeId)) + { + if (ConnectionCache.ExchangesCache.?(P_0.ExchangeId, out var exchange)) + { + Exchange = exchange; + } + else + { + ExchangeId = P_0.ExchangeId; + } + if (P_0.AvailableOptionsExchanges != null) + { + string[] availableOptionsExchanges = P_0.AvailableOptionsExchanges; + foreach (string text in availableOptionsExchanges) + { + if (ConnectionCache.ExchangesCache.?(text, out var item)) + { + ??.Add(item); + } + } + } + } + if (string.IsNullOrEmpty(P_0.UnderlierId)) + { + return; + } + if (ConnectionCache != null && ConnectionCache.SymbolsCache.?(P_0.UnderlierId, out var underlier)) + { + Underlier = underlier; + } + else + { + UnderlierId = P_0.UnderlierId; + } + if (P_0.OptionSerieId != null && Underlier != null) + { + OptionSerie = Connection.?(new GetOptionSeriesRequestParameters(Underlier))?.FirstOrDefault((OptionSerie optionSerie) => optionSerie.Id == P_0.OptionSerieId); + } + } + + internal void ?(MessageSymbol P_0) + { + ?((MessageSymbolInfo)P_0); + if (ConnectionCache != null) + { + if (P_0.ProductAssetId != null && ConnectionCache.??.TryGetValue(P_0.ProductAssetId, out var value)) + { + Product = value; + } + if (P_0.QuotingCurrencyAssetID != null && ConnectionCache.??.TryGetValue(P_0.QuotingCurrencyAssetID, out var value2)) + { + QuotingCurrency = value2; + } + if (!string.IsNullOrEmpty(P_0.GroupId) && ConnectionCache.SymbolGroupsCache.TryGetValue(P_0.GroupId, out var value3)) + { + Group = value3; + } + } + QuoteDelay = P_0.QuoteDelay; + MaturityDate = P_0.MaturityDate; + QuotingType = P_0.QuotingType; + LotSize = P_0.LotSize; + NotionalValueStep = P_0.NotionalValueStep; + NettingType = P_0.NettingType; + if (P_0.SymbolAdditionalInfo != null) + { + if (AdditionalInfo == null) + { + AdditionalInfoCollection additionalInfoCollection = (AdditionalInfo = new AdditionalInfoCollection()); + } + foreach (AdditionalInfoItem item in P_0.SymbolAdditionalInfo) + { + AdditionalInfo.?(item); + } + } + historyMetadata = P_0.HistoryMetadata; + volumeAnalysisMetadata = P_0.VolumeAnalysisMetadata; + VolumeType = P_0.VolumeType; + AllowCalculateRealtimeTicks = P_0.AllowCalculateRealtimeTicks; + AllowCalculateRealtimeTrades = P_0.AllowCalculateRealtimeTrades; + AllowCalculateRealtimeVolume = P_0.AllowCalculateRealtimeVolume; + AllowCalculateRealtimeChange = P_0.AllowCalculateRealtimeChange; + AllowAbbreviatePriceByTickSize = P_0.AllowAbbreviatePriceByTickSize; + DeltaCalculationType = P_0.DeltaCalculationType; + MinVolumeAnalysisTickSize = P_0.MinVolumeAnalysisTickSize; + ?? = P_0.SessionsContainerId; + ?(); + } + + protected internal virtual void SubscribeAction(SubscribeQuoteType type) + { + if (State == BusinessObjectState.Fake) + { + return; + } + if (Core.Instance.SymbolsMapping.TryGetQuotesSymbol(this, out var quotesSymbol) && quotesSymbol != this) + { + switch (type) + { + case SubscribeQuoteType.Quote: + quotesSymbol.NewQuote += ?; + break; + case SubscribeQuoteType.Level2: + { + DOMQuote dOMQuote = ((IMessageBuilder)quotesSymbol.DepthOfMarket).BuildMessage(); + dOMQuote.SymbolId = Id; + ?(dOMQuote); + quotesSymbol.NewLevel2 += ?; + break; + } + case SubscribeQuoteType.Last: + quotesSymbol.NewLast += ?; + break; + case SubscribeQuoteType.Mark: + quotesSymbol.NewMark += ?; + break; + } + bool flag = ((type == SubscribeQuoteType.Quote || (uint)(type - 2) <= 1u) ? true : false); + if (flag && (quotesSymbol.?? == null || !quotesSymbol.??.GetInvocationList().Contains(new DayBarHandler(?)))) + { + quotesSymbol.NewDayBar += ?; + DayBar dayBar = ((IMessageBuilder)quotesSymbol).BuildMessage(); + dayBar.SymbolId = Id; + ?((MessageQuote)dayBar); + } + } + else + { + Core.Instance.Connections[base.ConnectionId]?.?(this, type); + } + } + + protected internal virtual void UnSubscribeAction(SubscribeQuoteType type) + { + if (State == BusinessObjectState.Fake) + { + return; + } + if (Core.Instance.SymbolsMapping.TryGetQuotesSymbol(this, out var quotesSymbol) && quotesSymbol != this) + { + switch (type) + { + case SubscribeQuoteType.Quote: + quotesSymbol.NewQuote -= ?; + break; + case SubscribeQuoteType.Level2: + quotesSymbol.NewLevel2 -= ?; + break; + case SubscribeQuoteType.Last: + quotesSymbol.NewLast -= ?; + break; + case SubscribeQuoteType.Mark: + quotesSymbol.NewMark -= ?; + break; + } + QuoteHandler quoteHandler = quotesSymbol.??; + if (quoteHandler == null || !quoteHandler.GetInvocationList().Contains(new QuoteHandler(?))) + { + LastHandler lastHandler = quotesSymbol.??; + if (lastHandler == null || !lastHandler.GetInvocationList().Contains(new LastHandler(?))) + { + MarkHandler markHandler = quotesSymbol.??; + if (markHandler == null || !markHandler.GetInvocationList().Contains(new MarkHandler(?))) + { + quotesSymbol.NewDayBar -= ?; + ?((MessageQuote)new DayBar(Id, Core.Instance.TimeUtils.DateTimeUtcNow)); + } + } + } + } + else + { + Core.Instance.Connections[base.ConnectionId]?.?(this, type); + } + if (type == SubscribeQuoteType.Level2) + { + DepthOfMarket.?(); + } + } + + private void ?(Symbol P_0, Quote P_1) + { + ?((MessageQuote)P_1); + } + + private void ?(Symbol P_0, Level2Quote P_1, DOMQuote P_2) + { + ?(P_2); + ?(P_1); + } + + private void ?(Symbol P_0, Last P_1) + { + ?((MessageQuote)P_1); + } + + private void ?(Symbol P_0, Mark P_1) + { + ?((MessageQuote)P_1); + } + + private void ?(Symbol P_0, DayBar P_1) + { + ?((MessageQuote)P_1); + } + + internal void ?(Action P_0) + { + lock (??) + { + P_0(); + } + } + + internal void ?(MessageQuote P_0) + { + if (P_0 == null) + { + return; + } + if (!(P_0 is Quote quote)) + { + if (!(P_0 is Level2Quote level2Quote)) + { + if (!(P_0 is DOMQuote dOMQuote)) + { + if (!(P_0 is Last last)) + { + if (!(P_0 is Mark mark)) + { + if (!(P_0 is DayBar dayBar)) + { + return; + } + Func func; + Func func2; + Func func3; + if (dayBar.FullRefresh) + { + func = (double result, double num) => result; + func2 = (long result, long num) => result; + func3 = (DateTime result, DateTime dateTime) => result; + } + else + { + func = CoreMath.ProcessNaN; + func2 = (long num, long num2) => (num < 0) ? num2 : num; + func3 = (DateTime dateTime, DateTime dateTime2) => (!(dateTime != default(DateTime))) ? dateTime2 : dateTime; + } + Open = func(dayBar.Open, Open); + High = func(dayBar.High, High); + Low = func(dayBar.Low, Low); + PrevClose = func(dayBar.PreviousClose, PrevClose); + Volume = func(dayBar.Volume, Volume); + QuoteAssetVolume = func(dayBar.QuoteAssetVolume, QuoteAssetVolume); + PrevSettlement = func(dayBar.PrevSettlementPrice, PrevSettlement); + Ticks = func2(dayBar.Ticks, Ticks); + Trades = func2(dayBar.Trades, Trades); + Bid = func(dayBar.Bid, Bid); + BidSize = func(dayBar.BidSize, BidSize); + Ask = func(dayBar.Ask, Ask); + AskSize = func(dayBar.AskSize, AskSize); + Last = func(dayBar.Last, Last); + LastSize = func(dayBar.LastSize, LastSize); + Mark = func(dayBar.Mark, Mark); + MarkSize = func(dayBar.MarkSize, MarkSize); + if (!AllowCalculateRealtimeChange) + { + ?? = func(dayBar.Change, ??); + ?? = func(dayBar.ChangePercentage, ??); + } + OpenInterest = func(dayBar.OpenInterest, OpenInterest); + FundingRate = func(dayBar.FundingRate, FundingRate); + FundingTime = func3(dayBar.FundingTime, FundingTime); + TopPriceLimit = func(dayBar.TopPriceLimit, TopPriceLimit); + BottomPriceLimit = func(dayBar.BottomPriceLimit, BottomPriceLimit); + AverageTradedPrice = func(dayBar.AverageTradedPrice, AverageTradedPrice); + TotalBuyQuantity = dayBar.TotalBuyQuantity; + TotalSellQuantity = dayBar.TotalSellQuantity; + IV = dayBar.IV; + Delta = dayBar.Delta; + Vega = dayBar.Vega; + Gamma = dayBar.Gamma; + Theta = dayBar.Theta; + Rho = dayBar.Rho; + ?(dayBar); + } + else + { + Mark = mark.Price; + MarkSize = CoreMath.ProcessNaN(mark.Size, MarkSize); + ?(mark); + } + return; + } + if (HistoryMetadata != null && !HistoryMetadata.ServerSideTickDirectionAvailable) + { + last.TickDirection = DetermineTickDirection(Last, last.Price, ??); + } + ?? = last.TickDirection; + Last = last.Price; + LastSize = last.Size; + LastDateTime = last.Time; + if (AllowCalculateRealtimeVolume) + { + Volume += last.Size; + if (!double.IsNaN(last.QuoteAssetVolume)) + { + QuoteAssetVolume += last.QuoteAssetVolume; + } + } + if (AllowCalculateRealtimeTrades) + { + Trades++; + } + if (!double.IsNaN(last.OpenInterest)) + { + OpenInterest = last.OpenInterest; + } + ?(last); + } + else + { + DepthOfMarket.?(dOMQuote); + ?(null, dOMQuote); + } + } + else + { + DepthOfMarket.?(level2Quote); + ?(level2Quote, null); + } + } + else + { + quote.BidTickDirection = DetermineTickDirection(Bid, quote.Bid, ??); + quote.AskTickDirection = DetermineTickDirection(Ask, quote.Ask, ??); + ?? = quote.BidTickDirection; + ?? = quote.AskTickDirection; + if (!double.IsNaN(quote.Bid)) + { + Bid = quote.Bid; + } + if (!double.IsNaN(quote.BidSize)) + { + BidSize = quote.BidSize; + } + if (!double.IsNaN(quote.Ask)) + { + Ask = quote.Ask; + } + if (!double.IsNaN(quote.AskSize)) + { + AskSize = quote.AskSize; + } + QuoteDateTime = quote.Time; + if (AllowCalculateRealtimeTicks) + { + Ticks++; + } + ?(quote); + } + } + + private void ?(Quote P_0) + { + ???.Invoke(this, P_0); + } + + private void ?(Level2Quote P_0, DOMQuote P_1) + { + ???.Invoke(this, P_0, P_1); + } + + private void ?(Last P_0) + { + ???.Invoke(this, P_0); + } + + private void ?(Mark P_0) + { + ???.Invoke(this, P_0); + } + + private void ?(DayBar P_0) + { + ???.Invoke(this, P_0); + } + + /// + /// Gets historical data according to period and other parameters + /// + /// + /// + /// + /// + public HistoricalData GetHistory(Period period, DateTime fromTime, DateTime toTime = default(DateTime)) + { + return GetHistory(period, HistoryType, fromTime, toTime); + } + + /// + /// Gets historical data according to period and other parameters + /// + /// + /// + /// + /// + /// + public HistoricalData GetHistory(Period period, HistoryType historyType, DateTime fromTime, DateTime toTime = default(DateTime)) + { + HistoryAggregation aggregation = ((period.BasePeriod != BasePeriod.Tick) ? new HistoryAggregationTime(period, historyType) : ((period.PeriodMultiplier != 1) ? ((HistoryAggregation)new HistoryAggregationTickBars(period.PeriodMultiplier, historyType)) : ((HistoryAggregation)new HistoryAggregationTick(historyType)))); + HistoryRequestParameters historyRequestParameters = new HistoryRequestParameters + { + Symbol = this, + Aggregation = aggregation, + FromTime = fromTime, + ToTime = toTime + }; + return GetHistory(historyRequestParameters); + } + + /// + /// Gets historical data according to aggregation and other parameters + /// + /// + /// + /// + /// + /// + public HistoricalData GetHistory(HistoryAggregation aggregation, DateTime fromTime, DateTime toTime = default(DateTime)) + { + return GetHistory(new HistoryRequestParameters + { + Symbol = this, + Aggregation = aggregation, + FromTime = fromTime, + ToTime = toTime + }); + } + + /// + /// Gets historical data according to given history request + /// + /// + /// + public HistoricalData GetHistory(HistoryRequestParameters historyRequestParameters) + { + if (historyRequestParameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + historyRequestParameters.Symbol = this; + HistoricalData historicalData = ?(historyRequestParameters); + historicalData.Reload(); + return historicalData; + } + + private protected virtual HistoricalData ?(HistoryRequestParameters P_0) + { + return new HistoricalData(P_0); + } + + /// + /// Gets historical ticks data according to given parameters + /// + /// + /// + /// + /// + public HistoricalData GetTickHistory(HistoryType historyType, DateTime fromTime, DateTime toTime = default(DateTime)) + { + return GetHistory(new HistoryRequestParameters + { + Symbol = this, + Aggregation = new HistoryAggregationTick(historyType), + FromTime = fromTime, + ToTime = toTime + }); + } + + /// + /// Returns rounded to price + /// + public double RoundPriceToTickSize(double price, double tickSize = double.NaN) + { + if (double.IsNaN(price) || (VariableTickList == null && tickSize.IsNanOrDefault())) + { + return 0.0; + } + if (tickSize.IsNanOrDefault()) + { + VariableTick variableTick = FindVariableTick(price); + if (variableTick == null) + { + return price; + } + tickSize = variableTick.TickSize; + } + return CoreMath.RoundToIncrement(price, tickSize); + } + + /// + /// Calculates new price which equal to given price shifted by a number of given ticks + /// + /// + /// + /// + public double CalculatePrice(double price, double ticks) + { + decimal num = (decimal)price; + decimal num2 = (decimal)ticks; + return (double)(num + num2 * (decimal)GetTickSize(price)); + } + + /// + /// Calculates ticks between two prices + /// + /// + /// + /// + public double CalculateTicks(double price1, double price2) + { + if (double.IsNaN(price1) || double.IsNaN(price2)) + { + return double.NaN; + } + decimal num = (decimal)price1; + decimal num2 = (decimal)price2; + decimal num3 = (decimal)GetTickSize(price1); + decimal num4 = default(decimal); + if (num3 != 0m) + { + num4 = (num2 - num) / num3; + } + return (double)num4; + } + + /// + /// Gets cached symbol tick size or retrives it from the list + /// + /// + /// + public double GetTickSize(double price) + { + if (??.HasValue) + { + return ??.Value; + } + return FindVariableTick(price)?.TickSize ?? double.NaN; + } + + /// + /// Gets symbol tick cost retrived from the list by price + /// + /// + /// + public double GetTickCost(double price) + { + return FindVariableTick(price)?.TickCost ?? double.NaN; + } + + /// + /// Returns VariableTick if it can be retrived from list by price or null + /// + /// + /// + public VariableTick FindVariableTick(double price) + { + List variableTickList = VariableTickList; + if (variableTickList == null) + { + if (Underlier != null) + { + variableTickList = Underlier.VariableTickList; + } + if (variableTickList == null) + { + return null; + } + } + for (int num = variableTickList.Count - 1; num >= 0; num--) + { + VariableTick variableTick = variableTickList[num]; + if (variableTick.CheckPrice(price)) + { + return variableTick; + } + } + return null; + } + + private protected void ?() + { + ???.Invoke(this); + } + + [NotPublished] + public override string ToString() + { + return Name; + } + + [NotPublished] + public override BusinessObjectInfo CreateInfo() + { + return new SymbolInfo + { + ConnectionId = base.ConnectionId, + Id = Id, + Name = Name, + ExchangeId = ExchangeId, + SymbolType = SymbolType, + FutureContractType = FutureContractType, + UnderlierId = UnderlierId, + Root = Root, + ExpirationDate = ExpirationDate + }; + } + + public override bool Equals(object obj) + { + return Equals(obj as Symbol); + } + + public bool Equals(Symbol other) + { + if (other != null && base.ConnectionId == other.ConnectionId) + { + return Id == other.Id; + } + return false; + } + + public override int GetHashCode() + { + return (-1919740922 * -1521134295 + EqualityComparer.Default.GetHashCode(base.ConnectionId)) * -1521134295 + EqualityComparer.Default.GetHashCode(Id); + } + + /// + /// Formats price value to the appropriative string with a counting on tick precision. + /// + /// + /// + public string FormatPrice(double price) + { + VariableTick variableTick = FindVariableTick(price); + return FormatPrice(price, variableTick); + } + + /// + /// Formats price value to the appropriative string with a counting on tick precision. + /// + /// + /// + /// + public string FormatPrice(double price, VariableTick variableTick) + { + double num = Math.Abs(price); + if (AllowAbbreviatePriceByTickSize && GlobalSettings.AbbreviateCryptoPrices && price != 0.0 && num < 1.0 && variableTick != null) + { + int num2 = -(int)Math.Floor(Math.Log10(num)) - 1; + if (num2 < 0) + { + num2 *= -1; + } + if (num2 == 0) + { + if (variableTick != null) + { + return price.Format(variableTick.Precision); + } + return price.Format(); + } + string value = string.Empty; + if (price < 0.0) + { + value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 2); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear() + (num / variableTick.TickSize).ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture); + } + if (variableTick != null && (variableTick.TickSize == 1.0 / 32.0 || variableTick.TickSize == 1.0 / 64.0 || variableTick.TickSize == 1.0 / 128.0 || variableTick.TickSize == 1.0 / 256.0)) + { + return ?(price, variableTick); + } + if (variableTick != null) + { + return price.Format(variableTick.Precision); + } + return price.Format(); + } + + /// + /// Formats price value to the appropriative string with a counting on max tick precision. + /// + /// + /// + public string FormatPriceWithMaxPrecision(double price) + { + VariableTick variableTick = FindVariableTick(price); + if (variableTick != null && (variableTick.TickSize == 1.0 / 32.0 || variableTick.TickSize == 1.0 / 64.0 || variableTick.TickSize == 1.0 / 128.0 || variableTick.TickSize == 1.0 / 256.0)) + { + return ?(price, variableTick); + } + if (variableTick != null) + { + return price.FormatPriceWithMaxPrecision(variableTick.Precision); + } + return price.FormatPriceWithMaxPrecision(); + } + + private static string ?(double P_0, VariableTick P_1) + { + double num = Math.Abs(P_0 - (double)(long)P_0); + string value = ((P_1.TickSize == 1.0 / 32.0) ? ((double)(decimal)(num / P_1.TickSize)).ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) : ((P_1.TickSize == 1.0 / 64.0) ? ((double)(decimal)(num / P_1.TickSize / 2.0 * 10.0)).ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) : ((P_1.TickSize != 1.0 / 128.0) ? ((double)(decimal)(long)(num / P_1.TickSize / 8.0 * 10.0)).ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) : ((double)(decimal)(long)(num / P_1.TickSize / 4.0 * 10.0)).ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())))); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 3); + defaultInterpolatedStringHandler.AppendFormatted((P_0 < 0.0) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted((long)Math.Abs(P_0)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public virtual string FormatQuantity(double quantity, bool inLots = true, bool abbreviate = false) + { + if (inLots) + { + int valuePrecision = CoreMath.GetValuePrecision((decimal)LotStep); + return quantity.Format(valuePrecision, abbreviate); + } + return (quantity * LotSize).Format(CoreMath.GetValuePrecision((decimal)NotionalValueStep), abbreviate); + } + + /// + /// Returns string with formatted ticks value + /// + /// + /// + /// + public string FormatOffset(double offset, string dimension = "ticks") + { + return offset.FormatPriceWithMaxPrecision(0) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + dimension; + } + + [NotPublished] + public string FormatQuoteAssetVolume(double volume) + { + return volume.Format(); + } + + /// + /// Comparing by value + /// + [NotPublished] + public int CompareTo(Symbol symbol) + { + return Name.CompareTo(symbol.Name); + } + + private MessageSymbol ?() + { + return new MessageSymbol(Id) + { + GroupId = Group?.Id, + Name = Name, + Description = Description, + SymbolType = SymbolType, + ProductAssetId = Product?.Id, + QuotingCurrencyAssetID = QuotingCurrency?.Id, + ExchangeId = ExchangeId, + QuoteDelay = QuoteDelay, + QuotingType = QuotingType, + LotSize = LotSize, + VariableTickList = VariableTickList, + LotStep = LotStep, + NotionalValueStep = NotionalValueStep, + MaxLot = MaxLot, + MinLot = MinLot, + SymbolAdditionalInfo = AdditionalInfo?.Items.ToList(), + NettingType = NettingType, + Root = Root, + OptionType = OptionType, + StrikePrice = StrikePrice, + ExpirationDate = ExpirationDate, + HistoryType = HistoryType, + VolumeType = VolumeType, + LastTradingDate = LastTradingDate, + AllowCalculateRealtimeTicks = AllowCalculateRealtimeTicks, + AllowCalculateRealtimeTrades = AllowCalculateRealtimeTrades, + AllowCalculateRealtimeVolume = AllowCalculateRealtimeVolume, + AllowCalculateRealtimeChange = AllowCalculateRealtimeChange, + AllowAbbreviatePriceByTickSize = AllowAbbreviatePriceByTickSize, + DeltaCalculationType = DeltaCalculationType, + MinVolumeAnalysisTickSize = MinVolumeAnalysisTickSize, + AvailableFutures = AvailableFutures, + AvailableOptions = AvailableOptions, + AvailableOptionsExchanges = (AvailableOptionsExchanges.Any() ? AvailableOptionsExchanges.Select((Exchange P_0) => P_0.Id).ToArray() : null), + UnderlierId = Underlier?.Id, + MaturityDate = MaturityDate, + OptionSerieId = OptionSerie?.Id, + SessionsContainerId = ??, + HistoryMetadata = ((historyMetadata == null) ? null : new HistoryMetadata(historyMetadata)), + FutureContractType = FutureContractType + }; + } + + MessageSymbol IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + private DayBar ?() + { + return new DayBar(Id, Core.Instance.TimeUtils.DateTimeUtcNow) + { + Ask = Ask, + AskSize = AskSize, + AverageTradedPrice = AverageTradedPrice, + TotalBuyQuantity = TotalBuyQuantity, + TotalSellQuantity = TotalSellQuantity, + Bid = Bid, + BidSize = BidSize, + BottomPriceLimit = BottomPriceLimit, + Change = Change, + ChangePercentage = ChangePercentage, + High = High, + Last = Last, + LastSize = LastSize, + Mark = Mark, + Low = Low, + Open = Open, + OpenInterest = OpenInterest, + FundingRate = FundingRate, + FundingTime = FundingTime, + PreviousClose = PrevClose, + PrevSettlementPrice = PrevSettlement, + Ticks = Ticks, + TopPriceLimit = TopPriceLimit, + Trades = Trades, + Volume = Volume, + QuoteAssetVolume = QuoteAssetVolume, + IV = IV, + Delta = Delta, + Vega = Vega, + Gamma = Gamma, + Theta = Theta, + Rho = Rho + }; + } + + DayBar IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + /// + /// Gets symbol orders types list which are allowed. + /// + /// + /// + [NotPublished] + public virtual List GetAlowedOrderTypes(OrderTypeUsage? usage) + { + if (State == BusinessObjectState.Fake) + { + return new List(); + } + string connectionId = base.ConnectionId; + Connection connection = Core.Instance.Connections[connectionId]; + if (connection == null || connection.BusinessObjects.OrderTypes == null) + { + return null; + } + if (!usage.HasValue) + { + return connection.BusinessObjects.OrderTypes.ToList(); + } + return connection.BusinessObjects.OrderTypes.Where((OrderType P_0) => P_0.Usage.HasFlag(usage)).ToList(); + } + + public virtual bool IsTradingAllowed(Account account) + { + return TradingOperations.IsAllowed(TradingOperation.PlaceOrder, new TradingOperationParameters + { + Symbol = this, + Account = account + }).Status != TradingOperationStatus.NotAllowed; + } + + internal virtual TradingOperationResult ?(PlaceOrderRequestParameters P_0) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Connection.?(P_0); + } + + /// + /// An symbol has possibility to obtain the default account + /// + [NotPublished] + public virtual Account GetDefaultAccount(Account currentValue = null) + { + if (currentValue?.ConnectionId == base.ConnectionId) + { + return currentValue; + } + return Connection?.BusinessObjects?.Accounts?.FirstOrDefault(); + } + + public MarginInfo GetMarginInfo(OrderRequestParameters orderRequestParameters) + { + return Connection?.?(orderRequestParameters); + } + + public virtual ConnectionDependency GetConnectionStateDependency() + { + ConnectionDependency connectionDependency = new ConnectionDependency(); + connectionDependency.Behavior = ConnectionDependencyBehavior.PartialDependency; + connectionDependency.DependentConnectionsIds = new string[1] { base.ConnectionId }; + return connectionDependency; + } + + public virtual void OnConnectionStateChanged(Connection connection, ConnectionStateChangedEventArgs e) + { + } + + public static TickDirection DetermineTickDirection(double previousPrice, double currentPrice, TickDirection prevItemTickDirection) + { + if (double.IsNaN(previousPrice)) + { + return TickDirection.NotSet; + } + if (double.IsNaN(currentPrice)) + { + return TickDirection.NotSet; + } + if (currentPrice > previousPrice) + { + return TickDirection.Up; + } + if (currentPrice < previousPrice) + { + return TickDirection.Down; + } + return prevItemTickDirection; + } + + [NotPublished] + public static AggressorFlag ConvertTickDirection(TickDirection tickDirection) + { + return tickDirection switch + { + TickDirection.None => AggressorFlag.None, + TickDirection.Up => AggressorFlag.Buy, + TickDirection.Down => AggressorFlag.Sell, + _ => AggressorFlag.NotSet, + }; + } + + [CompilerGenerated] + private void ?(Rule P_0) + { + ??.?(P_0.Name, P_0); + } + } + public delegate void QuoteHandler(Symbol symbol, Quote quote); + public delegate void Level2Handler(Symbol symbol, Level2Quote level2, DOMQuote dom); + public delegate void LastHandler(Symbol symbol, Last last); + public delegate void MarkHandler(Symbol symbol, Mark mark); + public delegate void DayBarHandler(Symbol symbol, DayBar dayBar); + public delegate void SymbolUpdateHandler(Symbol symbol); + public struct VWAP + { + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private Side ?; + + public double Price + { + [CompilerGenerated] + readonly get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = num; + } + } + + public Side Side + { + [CompilerGenerated] + readonly get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = side; + } + } + } + /// + /// Represents information about trade. + /// + [Published] + public class Trade : TradingObject, IMessageBuilder + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private PnLItem ??; + + [CompilerGenerated] + private PnLItem ??; + + [CompilerGenerated] + private PnLItem ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private PositionImpactType ??; + + [CompilerGenerated] + private Action ??; + + /// + /// Gets the unique identifier of the order initiating the trade. + /// + public string OrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets a unique identifier of the position, which is related to this trade. + /// + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Get the price where trade was executed + /// + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Get the trade quantity + /// + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Get the date and time when trade was executed + /// + public DateTime DateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + /// + /// Get the trade Gross P&L + /// + public PnLItem GrossPnl + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = pnLItem; + } + } + + /// + /// Get the trade Net P&L + /// + public PnLItem NetPnl + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = pnLItem; + } + } + + /// + /// Get the fee value that was charged for this trade + /// + public PnLItem Fee + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = pnLItem; + } + } + + /// + /// Get the trade order type + /// + public string OrderTypeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public PositionImpactType PositionImpactType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = positionImpactType; + } + } + + /// + /// Will be triggered on trade updating + /// + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public Trade(string connectionId) + : base(connectionId) + { + } + + internal void ?(MessageTrade P_0) + { + base.Id = P_0.TradeId; + if (ConnectionCache != null && ConnectionCache.SymbolsCache.?(P_0.SymbolId, out var symbol)) + { + base.Symbol = symbol; + } + else if (!string.IsNullOrEmpty(P_0.SymbolId)) + { + base.Symbol = new Symbol(new BusinessObjectInfo + { + Id = P_0.SymbolId, + Name = P_0.SymbolId + }); + } + if (ConnectionCache != null && ConnectionCache.AccountsCache.?(P_0.AccountId, out var account)) + { + base.Account = account; + } + else if (!string.IsNullOrEmpty(P_0.AccountId)) + { + base.Account = new Account(new BusinessObjectInfo + { + Id = P_0.AccountId, + Name = P_0.AccountId + }); + } + OrderId = P_0.OrderId; + PositionId = P_0.PositionId; + Price = P_0.Price; + Quantity = P_0.Quantity; + base.Side = P_0.Side; + base.Comment = P_0.Comment; + DateTime = P_0.DateTime; + OrderTypeId = P_0.OrderTypeId; + PositionImpactType = P_0.PositionImpactType; + GrossPnl = P_0.GrossPnl; + if (GrossPnl != null) + { + GrossPnl.ConnectionId = base.ConnectionId; + } + NetPnl = P_0.NetPnl; + if (NetPnl != null) + { + NetPnl.ConnectionId = base.ConnectionId; + } + Fee = P_0.Fee; + if (Fee != null) + { + Fee.ConnectionId = base.ConnectionId; + } + ???.Invoke(); + } + + public MessageTrade BuildMessage() + { + return new MessageTrade + { + TradeId = base.Id, + SymbolId = base.Symbol?.Id, + AccountId = base.Account?.Id, + OrderId = OrderId, + PositionId = PositionId, + Price = Price, + Quantity = Quantity, + Side = base.Side, + Comment = base.Comment, + DateTime = DateTime, + OrderTypeId = OrderTypeId, + PositionImpactType = PositionImpactType, + GrossPnl = GrossPnl, + NetPnl = NetPnl, + Fee = Fee + }; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(50, 7); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Quantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Comment); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public sealed class TradingSignal : BusinessObject, IMessageBuilder + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private OrderTypeBehavior ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Ticker + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Root + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string VendorName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = side; + } + } + + public OrderTypeBehavior OrderTypeBehavior + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = orderTypeBehavior; + } + } + + public double EntryPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double TargetPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double StopPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Confidence + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double Profitability + { + get + { + if (Side != Side.Buy) + { + return 1.0 - TargetPrice / EntryPrice; + } + return TargetPrice / EntryPrice - 1.0; + } + } + + public DateTime Published + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public DateTime Updated + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public DateTime ExpiresAt + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public string Duration + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Details + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Source + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal TradingSignal(string P_0) + : base(P_0) + { + } + + internal void ?(MessageTradingSignal P_0) + { + Id = P_0.Id; + Ticker = P_0.Ticker; + Root = P_0.Root; + VendorName = P_0.VendorName; + Side = P_0.Side; + OrderTypeBehavior = P_0.OrderTypeBehavior; + EntryPrice = P_0.EntryPrice; + TargetPrice = P_0.TargetPrice; + StopPrice = P_0.StopPrice; + Confidence = P_0.Confidence; + Published = P_0.Published; + Updated = P_0.Updated; + ExpiresAt = P_0.ExpiresAt; + Duration = P_0.Duration; + Status = P_0.Status; + Description = P_0.Description; + Details = P_0.Details; + Source = P_0.Source; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(5, 4); + defaultInterpolatedStringHandler.AppendFormatted(Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderTypeBehavior); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Ticker ?? Root); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(Description); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private MessageTradingSignal ?() + { + return new MessageTradingSignal(Id) + { + Ticker = Ticker, + Root = Root, + VendorName = VendorName, + Side = Side, + OrderTypeBehavior = OrderTypeBehavior, + EntryPrice = EntryPrice, + TargetPrice = TargetPrice, + StopPrice = StopPrice, + Confidence = Confidence, + Published = Published, + Updated = Updated, + ExpiresAt = ExpiresAt, + Duration = Duration, + Status = Status, + Description = Description, + Details = Details, + Source = Source + }; + } + + MessageTradingSignal IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + public string Format() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(18, 7); + defaultInterpolatedStringHandler.AppendFormatted(Confidence, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Status); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Ticker ?? Root); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(EntryPrice); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TargetPrice); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(StopPrice); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Updated, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } +} +namespace ? +{ + [Serializable] + [DataContract] + internal class ? : BusinessObjectInfo + { + [CompilerGenerated] + private bool ??; + + [DataMember(Name = "IsCrypto")] + public bool IsCrypto + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + + protected override bool NeedToEncryptInfo => true; + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsCrypto)); + return xElement; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + IsCrypto = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToBool() ?? false; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + [Serializable] + [DataContract] + public class BusinessObjectInfo : IXElementSerialization, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [DataMember(Name = "Id")] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + [DataMember(Name = "ConnectionId")] + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + [DataMember(Name = "Name")] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + protected virtual bool NeedToEncryptInfo => false; + + public static BusinessObjectInfo Empty => new BusinessObjectInfo + { + Id = string.Empty, + ConnectionId = string.Empty, + Name = string.Empty + }; + + public virtual XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), NeedToEncryptInfo ? Encryptor.?(Id) : Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ConnectionId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), NeedToEncryptInfo ? Encryptor.?(Name) : Name)); + return xElement; + } + + public virtual void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + string value = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + if (NeedToEncryptInfo) + { + string text = Encryptor.?(value); + if (text != null) + { + Id = text; + goto IL_0038; + } + } + Id = value; + goto IL_0038; + IL_0038: + ConnectionId = ConnectionsManager.??.?(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value); + string value2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + if (NeedToEncryptInfo) + { + string text2 = Encryptor.?(value2); + if (text2 != null) + { + Name = text2; + return; + } + } + Name = value2; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 3); + defaultInterpolatedStringHandler.AppendFormatted(ConnectionId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public bool Equals(BusinessObjectInfo other) + { + if ((object)other == null) + { + return false; + } + if ((object)this == other) + { + return true; + } + if (Id == other.Id && ConnectionId == other.ConnectionId) + { + return Name == other.Name; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((BusinessObjectInfo)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Id, ConnectionId, Name); + } + + public static bool operator ==(BusinessObjectInfo left, BusinessObjectInfo right) + { + return object.Equals(left, right); + } + + public static bool operator !=(BusinessObjectInfo left, BusinessObjectInfo right) + { + return !object.Equals(left, right); + } + } + public class CryptoAccountEventArgs : EventArgs + { + [CompilerGenerated] + private readonly AccountBalanceEventReason ?; + + [CompilerGenerated] + private readonly CryptoAssetBalances ?; + + public AccountBalanceEventReason Reason + { + [CompilerGenerated] + get + { + return ?; + } + } + + public CryptoAssetBalances Balances + { + [CompilerGenerated] + get + { + return ?; + } + } + + public CryptoAccountEventArgs(AccountBalanceEventReason reason, CryptoAssetBalances balances) + { + ? = reason; + ? = balances; + } + } + public sealed class CustomAccountPropertiesProvider : ICustomizable + { + public const string CUSTOM_NAME = "CustomName"; + + public const string LOCKED = "Locked"; + + [CompilerGenerated] + private Action ??; + + private readonly ConcurrentDictionary> ??; + + public IList Settings + { + get + { + List list = new List(); + foreach (KeyValuePair> item2 in ??) + { + List list2 = new List + { + new SettingItemAccount(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), item2.Key) + }; + foreach (KeyValuePair item3 in item2.Value) + { + list2.Add(?(item3.Key, item3.Value)); + } + SettingItemGroup item = new SettingItemGroup(string.Empty, list2); + list.Add(item); + } + return list; + } + set + { + foreach (SettingItem item in value) + { + if (!(item is SettingItemGroup settingItemGroup)) + { + continue; + } + Account account = null; + Dictionary dictionary = new Dictionary(); + foreach (SettingItem item2 in settingItemGroup.Value as IList) + { + if (item2.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + account = item2.Value as Account; + } + else + { + dictionary[item2.Name] = item2.Value; + } + } + if (account != null) + { + ??[account] = dictionary; + } + } + } + } + + public event Action ParametersChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public CustomAccountPropertiesProvider() + { + ?? = new ConcurrentDictionary>(); + } + + public void SetProperty(Account account, string name, object value) + { + if (??.ContainsKey(account)) + { + ??[account][name] = value; + } + else + { + ??[account] = new Dictionary { { name, value } }; + } + ???.Invoke(); + } + + public object GetProperty(Account account, string name) + { + if (account == null) + { + return null; + } + if (??.TryGetValue(account, out var value) && value.TryGetValue(name, out var value2)) + { + return value2; + } + return null; + } + + private SettingItem ?(string P_0, object P_1) + { + if (!(P_1 is int)) + { + if (!(P_1 is double)) + { + if (!(P_1 is string)) + { + if (P_1 is bool) + { + return new SettingItemBoolean(P_0, (bool)P_1); + } + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return new SettingItemString(P_0, (string)P_1); + } + return new SettingItemDouble(P_0, (double)P_1); + } + return new SettingItemInteger(P_0, (int)P_1); + } + } + public class DealTicket + { + [CompilerGenerated] + private readonly string ?; + + [CompilerGenerated] + private readonly string ?; + + [CompilerGenerated] + private readonly DealTicketType ?; + + [CompilerGenerated] + private readonly DateTime ?; + + [CompilerGenerated] + private readonly Action ?; + + public string Header + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + init + { + ? = value; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + init + { + ? = value; + } + } + + public DealTicketType Type + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + init + { + ? = value; + } + } + + public DateTime CreationTime + { + [CompilerGenerated] + get + { + return ?; + } + } + + public Action CustomAction + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + init + { + ? = value; + } + } + + internal DealTicket(string P_0, string P_1, DealTicketType P_2) + : this() + { + Header = P_0; + Description = P_1; + Type = P_2; + } + + protected DealTicket() + { + ? = Core.Instance.TimeUtils.DateTimeUtcNow; + } + } + public sealed class DealticketConnection : DealTicket, IConnectionBindedObject, ILoggable + { + private readonly string ??; + + string IConnectionBindedObject.ConnectionId => ??; + + public string Event => base.Header; + + public string Message => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + base.Description + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public DealticketConnection(string connectionId, MessageDealTicket message) + { + ?? = connectionId; + base.Header = message.Header; + base.Description = message.Description; + base.Type = message.DealTicketType; + } + } + [DataContract] + public sealed class DealTicketItem + { + [CompilerGenerated] + private string ?; + + private readonly object ?; + + [CompilerGenerated] + private readonly int ?; + + [DataMember(Name = "key")] + public string Key + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = text; + } + } + + [DataMember(Name = "value")] + public string FormattedValue => ??.ToString(); + + public int SortIndex + { + [CompilerGenerated] + get + { + return ?; + } + } + + public DealTicketItem(string key, object value, int sortIndex = 0) + { + Key = key; + ? = value; + ? = sortIndex; + } + } + public readonly struct ExchangeComplexIdentifier : IEquatable + { + [CompilerGenerated] + private readonly string ?; + + [CompilerGenerated] + private readonly string ?; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ?; + } + } + + public string ExchangeId + { + [CompilerGenerated] + get + { + return ?; + } + } + + public ExchangeComplexIdentifier(string connectionId, string exchangeId) + { + ? = connectionId; + ? = exchangeId; + } + + public bool Equals(ExchangeComplexIdentifier other) + { + if (ConnectionId == other.ConnectionId) + { + return ExchangeId == other.ExchangeId; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj is ExchangeComplexIdentifier other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (ConnectionId.GetHashCode() * 397) ^ ExchangeId.GetHashCode(); + } + + public static bool operator ==(ExchangeComplexIdentifier left, ExchangeComplexIdentifier right) + { + return left.Equals(right); + } + + public static bool operator !=(ExchangeComplexIdentifier left, ExchangeComplexIdentifier right) + { + return !left.Equals(right); + } + } + /// + /// The symbols list manager. + /// + public sealed class SymbolsListManager : ICustomizable + { + [CompilerGenerated] + private static class ? + { + public static Func ??; + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(FtpListItem P_0) + { + return P_0.Type == FtpObjectType.Directory; + } + + internal bool ?(FtpListItem P_0) + { + return P_0.Type == FtpObjectType.File; + } + + internal bool ?(FtpListItem P_0) + { + return Path.GetExtension(P_0.Name) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + /// + /// Gets the count. + /// + public int Count => ??.Count + ??.Count; + + /// + /// Gets or Sets the settings. + /// + public IList Settings + { + get + { + List list = new List(); + foreach (KeyValuePair item in ??) + { + list.Add(new SettingItemGroup(item.Key, item.Value.Settings)); + } + return list; + } + set + { + foreach (SettingItem item in value) + { + if (item.Value is IList settings) + { + if (??.TryGetValue(item.Name, out var value2)) + { + value2.Settings = settings; + continue; + } + value2 = new SymbolList + { + Settings = settings + }; + ??.Add(item.Name, value2); + } + } + } + } + + internal SymbolList[] Items => ??.Values.Concat(??.Values).ToArray(); + + internal SymbolsListManager() + { + ?? = new Dictionary(); + ?? = new Dictionary(); + } + + internal void ?() + { + } + + internal void ?(string P_0, IEnumerable P_1) + { + ??.Add(P_0, new SymbolList(P_0, P_1)); + } + + internal void ?(string P_0, IList P_1) + { + ??[P_0].Symbols = P_1; + } + + internal void ?(string P_0) + { + ??.Remove(P_0); + } + + internal void ?(string P_0, string P_1) + { + if (!??.TryGetValue(P_0, out var value)) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0); + } + ??.Remove(P_0); + value.?(P_1); + ??.Add(P_1, value); + } + + [Conditional("quantower_in_licences")] + private void ?() + { + Task.Factory.StartNew(delegate + { + try + { + using FtpClient ftpClient = new FtpClient(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ftpClient.Connect(); + foreach (FtpListItem item in from P_0 in ftpClient.GetListing(Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + where P_0.Type == FtpObjectType.Directory + select P_0) + { + FtpListItem[] array = (from P_0 in ftpClient.GetListing(item.FullName) + where P_0.Type == FtpObjectType.File + where Path.GetExtension(P_0.Name) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + select P_0).ToArray(); + foreach (FtpListItem ftpListItem in array) + { + using MemoryStream memoryStream = new MemoryStream(); + ftpClient.DownloadStream(memoryStream, ftpListItem.FullName, 0L, null, 0L); + memoryStream.Position = 0L; + double version; + List list = Serializer.DeserializeXML(memoryStream, out version, SettingItem.DesserrializationFabric).OfType().ToList(); + if (list != null && list.Any()) + { + SymbolList symbolList = new SymbolList(list, false) + { + Group = item.Name + }; + string key = Path.Combine(item.Name, symbolList.Name); + ??[key] = symbolList; + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + }); + } + + [CompilerGenerated] + private void ?() + { + try + { + using FtpClient ftpClient = new FtpClient(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ftpClient.Connect(); + foreach (FtpListItem item in from P_0 in ftpClient.GetListing(Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + where P_0.Type == FtpObjectType.Directory + select P_0) + { + FtpListItem[] array = (from P_0 in ftpClient.GetListing(item.FullName) + where P_0.Type == FtpObjectType.File + where Path.GetExtension(P_0.Name) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + select P_0).ToArray(); + foreach (FtpListItem ftpListItem in array) + { + using MemoryStream memoryStream = new MemoryStream(); + ftpClient.DownloadStream(memoryStream, ftpListItem.FullName, 0L, null, 0L); + memoryStream.Position = 0L; + double version; + List list = Serializer.DeserializeXML(memoryStream, out version, SettingItem.DesserrializationFabric).OfType().ToList(); + if (list != null && list.Any()) + { + SymbolList symbolList = new SymbolList(list, false) + { + Group = item.Name + }; + string key = Path.Combine(item.Name, symbolList.Name); + ??[key] = symbolList; + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + /// + /// Represent access to level2 data. + /// + [Published] + public class DepthOfMarket : IMessageBuilder + { + [CompilerGenerated] + private ? ?; + + [CompilerGenerated] + private ? ?; + + private Dictionary ?; + + private readonly Symbol ?; + + private readonly object ?; + + /// + /// Gets Level2 Asks list + /// + internal ? Asks + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = ?; + } + } + + /// + /// Gets Level2 Bids list + /// + internal ? Bids + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = ?; + } + } + + internal DepthOfMarket(Symbol P_0) + { + ? = P_0; + bool flag = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ?.ConnectionId).Status == TradingOperationStatus.Allowed; + Asks = new ?(QuotePriceType.Ask, flag); + Bids = new ?(QuotePriceType.Bid, flag); + ? = new object(); + ? = new Dictionary(); + } + + internal void ?(Level2Quote P_0) + { + lock (?) + { + if (P_0.PriceType == QuotePriceType.Ask) + { + Asks.?(P_0); + } + else + { + Bids.?(P_0); + } + ? = new Dictionary(); + } + } + + internal void ?(DOMQuote P_0) + { + lock (?) + { + Asks.?(P_0.Asks); + Bids.?(P_0.Bids); + ? = new Dictionary(); + } + } + + internal void ?() + { + lock (?) + { + Asks.?(); + Bids.?(); + ?.Clear(); + } + } + + /// + /// Gets current Level2 data + /// + /// Parameters of DepthOfMarket + /// + public DepthOfMarketAggregatedCollections GetDepthOfMarketAggregatedCollections(GetDepthOfMarketParameters parameters = null) + { + if (parameters == null) + { + parameters = new GetDepthOfMarketParameters(); + } + lock (?) + { + int hashCode = parameters.GetHashCode(); + if (!?.TryGetValue(hashCode, out var value)) + { + value = new DepthOfMarketAggregatedCollections + { + Asks = Asks.?(parameters.GetLevel2ItemsParameters), + Bids = Bids.?(parameters.GetLevel2ItemsParameters) + }; + if (parameters.CalculateImbalancePercent) + { + ?(value.Asks, value.Bids); + } + ?[hashCode] = value; + } + return value; + } + } + + /// + /// Gets current Level2 data + /// + /// Parameters of request for Leve2Item collection + /// + public DepthOfMarketAggregatedCollections GetDepthOfMarketAggregatedCollections(GetLevel2ItemsParameters parameters) + { + return GetDepthOfMarketAggregatedCollections(new GetDepthOfMarketParameters + { + GetLevel2ItemsParameters = parameters + }); + } + + private static void ?(Level2Item[] P_0, Level2Item[] P_1) + { + int num = Math.Min(P_1.Length, P_0.Length); + for (int i = 0; i < num; i++) + { + Level2Item level2Item = P_0[i]; + Level2Item level2Item2 = P_1[i]; + double cumulative = level2Item.Cumulative; + double cumulative2 = level2Item2.Cumulative; + if (cumulative >= 0.0 && cumulative2 >= 0.0) + { + level2Item.ImbalancePercent = Math.Round(level2Item.Cumulative / (level2Item.Cumulative + level2Item2.Cumulative) * 100.0, 2); + level2Item2.ImbalancePercent = 100.0 - level2Item.ImbalancePercent; + } + } + } + + private DOMQuote ?() + { + return new DOMQuote(?.Id, Core.Instance.TimeUtils.DateTimeUtcNow) + { + Asks = Asks.Items.Values.ToList(), + Bids = Bids.Items.Values.ToList() + }; + } + + DOMQuote IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } + /// + /// Leve2 data. Contains Bids and Ask collections + /// + [Published] + public class DepthOfMarketAggregatedCollections + { + [CompilerGenerated] + private Level2Item[] ?; + + [CompilerGenerated] + private Level2Item[] ?; + + public Level2Item[] Asks + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = array; + } + } + + public Level2Item[] Bids + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = array; + } + } + } + /// + /// Represent parameters of DepthOfMarket + /// + [Published] + public class GetDepthOfMarketParameters + { + [CompilerGenerated] + private GetLevel2ItemsParameters ?; + + [CompilerGenerated] + private bool ?; + + public GetLevel2ItemsParameters GetLevel2ItemsParameters + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public bool CalculateImbalancePercent + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public GetDepthOfMarketParameters() + { + GetLevel2ItemsParameters = new GetLevel2ItemsParameters(); + } + + public static bool operator ==(GetDepthOfMarketParameters p1, GetDepthOfMarketParameters p2) + { + if ((object)p1 == null || (object)p2 == null) + { + if ((object)p1 == null) + { + return (object)p2 == null; + } + return false; + } + return p1.Equals(p2); + } + + public static bool operator !=(GetDepthOfMarketParameters p1, GetDepthOfMarketParameters p2) + { + if ((object)p1 == null || (object)p2 == null) + { + if ((object)p1 == null) + { + return (object)p2 != null; + } + return true; + } + return !p1.Equals(p2); + } + + public override bool Equals(object obj) + { + if (!(obj is GetDepthOfMarketParameters getDepthOfMarketParameters)) + { + return false; + } + if (GetLevel2ItemsParameters != getDepthOfMarketParameters.GetLevel2ItemsParameters) + { + return false; + } + if (CalculateImbalancePercent != getDepthOfMarketParameters.CalculateImbalancePercent) + { + return false; + } + return true; + } + + public override int GetHashCode() + { + return GetLevel2ItemsParameters.GetHashCode() ^ CalculateImbalancePercent.GetHashCode(); + } + } + /// + /// Represent parameters of request for Leve2Item collection + /// + [Published] + public class GetLevel2ItemsParameters + { + [CompilerGenerated] + private AggregateMethod ?; + + [CompilerGenerated] + private ImplicitOrderBookType ?; + + [CompilerGenerated] + private int ?; + + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private bool ?; + + [CompilerGenerated] + private bool ?; + + /// + /// Aggregation method + /// + public AggregateMethod AggregateMethod + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public ImplicitOrderBookType ImplicitOrderBookType + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + /// + /// Required amount of level2 + /// + public int LevelsCount + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + /// + /// Use custom tick size + /// + public double CustomTickSize + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + /// + /// Calculate cumulative size + /// + public bool CalculateCumulative + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public bool GetMBOItems + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public static bool operator ==(GetLevel2ItemsParameters p1, GetLevel2ItemsParameters p2) + { + if ((object)p1 == null || (object)p2 == null) + { + if ((object)p1 == null) + { + return (object)p2 == null; + } + return false; + } + return p1.Equals(p2); + } + + public static bool operator !=(GetLevel2ItemsParameters p1, GetLevel2ItemsParameters p2) + { + if ((object)p1 == null || (object)p2 == null) + { + if ((object)p1 == null) + { + return (object)p2 != null; + } + return true; + } + return !p1.Equals(p2); + } + + public override bool Equals(object obj) + { + if (!(obj is GetLevel2ItemsParameters getLevel2ItemsParameters)) + { + return false; + } + if (AggregateMethod != getLevel2ItemsParameters.AggregateMethod) + { + return false; + } + if (LevelsCount != getLevel2ItemsParameters.LevelsCount) + { + return false; + } + if (CustomTickSize != getLevel2ItemsParameters.CustomTickSize) + { + return false; + } + if (CalculateCumulative != getLevel2ItemsParameters.CalculateCumulative) + { + return false; + } + if (ImplicitOrderBookType != getLevel2ItemsParameters.ImplicitOrderBookType) + { + return false; + } + if (GetMBOItems != getLevel2ItemsParameters.GetMBOItems) + { + return false; + } + return true; + } + + public override int GetHashCode() + { + return (int)((uint)AggregateMethod ^ (uint)LevelsCount ^ (uint)CustomTickSize.GetHashCode() ^ (uint)CalculateCumulative.GetHashCode() ^ (uint)ImplicitOrderBookType.GetHashCode()) ^ GetMBOItems.GetHashCode(); + } + } +} +namespace ? +{ + internal sealed class ? + { + [CompilerGenerated] + private static class ? + { + public static Func ??; + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal string ?(Level2Quote P_0) + { + return P_0.Id; + } + + internal Level2Quote ?(Level2Quote P_0) + { + return P_0; + } + + internal double ?(Level2Quote P_0) + { + return P_0.ImpliedSize; + } + + internal double ?(Level2Quote P_0) + { + return P_0.Size - P_0.ImpliedSize; + } + + internal double ?(Level2Quote P_0) + { + return P_0.Size; + } + + internal double ?(Level2Quote P_0) + { + return P_0.Price; + } + + internal Level2Item ?(Level2Item P_0) + { + return P_0; + } + + internal Level2Item ?(Level2Item P_0) + { + return P_0; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ? ??; + + public GetLevel2ItemsParameters ??; + + public Func ??; + + public Func ??; + + public Func ??; + + internal double ?(Level2Quote P_0) + { + return (double)??.?((decimal)P_0.Price, (decimal)??.CustomTickSize); + } + + internal Level2Item ?(IGrouping P_0) + { + Level2Quote level2Quote = P_0.First(); + if (P_0.Count() == 1) + { + double num = ??(level2Quote); + return new Level2Item(P_0.Key, num, level2Quote.Time, level2Quote.Broker, level2Quote.Priority, level2Quote.NumberOrders, (!??.GetMBOItems) ? new Level2Item[0] : new Level2Item[1] + { + new Level2Item(P_0.Key, num, level2Quote.Time, level2Quote.Broker, level2Quote.Priority, 1) + { + Id = level2Quote.Id + } + }); + } + return new Level2Item(P_0.Key, P_0.Sum((Level2Quote arg) => ??(arg)), level2Quote.Time, string.Empty, 0L, P_0.Count(), ??.GetMBOItems ? P_0.Select((Level2Quote level2Quote2) => new Level2Item(level2Quote2.Price, ??(level2Quote2), level2Quote2.Time, level2Quote2.Broker, level2Quote2.Priority, 1) + { + Id = level2Quote2.Id + }).OrderBy(?.?.??.?, ??.?).ToArray() : new Level2Item[0]); + } + + internal double ?(Level2Quote P_0) + { + return ??(P_0); + } + + internal Level2Item ?(Level2Quote P_0) + { + return new Level2Item(P_0.Price, ??(P_0), P_0.Time, P_0.Broker, P_0.Priority, 1) + { + Id = P_0.Id + }; + } + + internal Level2Item ?(Level2Quote P_0) + { + return new Level2Item(P_0.Price, ??(P_0), P_0.Time, P_0.Broker, P_0.Priority, P_0.NumberOrders); + } + } + + [CompilerGenerated] + private sealed class ? + { + public double ??; + + internal Level2Item ?(Level2Item P_0) + { + ?? += P_0.Size; + P_0.Cumulative = ??; + return P_0; + } + } + + [CompilerGenerated] + private Dictionary ?; + + private readonly object ?; + + private readonly QuotePriceType ?; + + private readonly ? ?; + + private readonly Func ?; + + private Dictionary ?; + + private readonly bool ?; + + internal Dictionary Items + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = dictionary; + } + } + + internal ?(QuotePriceType P_0, bool P_1) + { + ? = P_0; + ? = P_1; + ? = new ?(? == QuotePriceType.Bid); + ? = ?; + Items = new Dictionary(); + ? = new Dictionary(); + ? = new object(); + } + + internal void ?() + { + lock (?) + { + Items.Clear(); + ?.Clear(); + } + } + + internal Level2Item[] ?(GetLevel2ItemsParameters P_0 = null) + { + if (P_0 == null) + { + P_0 = new GetLevel2ItemsParameters(); + } + lock (?) + { + int hashCode = P_0.GetHashCode(); + if (!?.TryGetValue(hashCode, out var value)) + { + value = ?(P_0); + ?[hashCode] = value; + } + return value; + } + } + + internal void ?(Level2Quote P_0) + { + lock (?) + { + if (P_0.Closed) + { + Items.Remove(P_0.Id); + } + else + { + Items[P_0.Id] = P_0; + } + ? = new Dictionary(); + } + } + + internal void ?(IEnumerable P_0) + { + lock (?) + { + Items = P_0.ToDictionary((Level2Quote level2Quote) => level2Quote.Id, (Level2Quote result) => result); + ? = new Dictionary(); + } + } + + private Level2Item[] ?(GetLevel2ItemsParameters P_0) + { + Dictionary.ValueCollection values = Items.Values; + bool flag = P_0.CustomTickSize > 0.0 && !P_0.CustomTickSize.IsNanOrDefault(); + _ = P_0.AggregateMethod; + if (?) + { + } + Func ?? = P_0.ImplicitOrderBookType switch + { + ImplicitOrderBookType.Implied => (Level2Quote level2Quote) => level2Quote.ImpliedSize, + ImplicitOrderBookType.Outright => (Level2Quote level2Quote) => level2Quote.Size - level2Quote.ImpliedSize, + _ => (Level2Quote level2Quote) => level2Quote.Size, + }; + IEnumerable source = (P_0.AggregateMethod switch + { + AggregateMethod.ByPriceLVL => (flag ? (from level2Quote in values + group level2Quote by (double)?((decimal)level2Quote.Price, (decimal)P_0.CustomTickSize)) : (from level2Quote in values + group level2Quote by level2Quote.Price)).Select(delegate(IGrouping grouping) + { + Level2Quote level2Quote = grouping.First(); + if (grouping.Count() == 1) + { + double num = ??(level2Quote); + return new Level2Item(grouping.Key, num, level2Quote.Time, level2Quote.Broker, level2Quote.Priority, level2Quote.NumberOrders, (!P_0.GetMBOItems) ? new Level2Item[0] : new Level2Item[1] + { + new Level2Item(grouping.Key, num, level2Quote.Time, level2Quote.Broker, level2Quote.Priority, 1) + { + Id = level2Quote.Id + } + }); + } + return new Level2Item(grouping.Key, grouping.Sum((Level2Quote arg) => ??(arg)), level2Quote.Time, string.Empty, 0L, grouping.Count(), P_0.GetMBOItems ? grouping.Select((Level2Quote level2Quote2) => new Level2Item(level2Quote2.Price, ??(level2Quote2), level2Quote2.Time, level2Quote2.Broker, level2Quote2.Priority, 1) + { + Id = level2Quote2.Id + }).OrderBy(?.?.??.?, ?).ToArray() : new Level2Item[0]); + }), + _ => values.Select((Level2Quote level2Quote) => new Level2Item(level2Quote.Price, ??(level2Quote), level2Quote.Time, level2Quote.Broker, level2Quote.Priority, level2Quote.NumberOrders)), + }).OrderBy((Level2Item result) => result, ?); + if (P_0.LevelsCount > 0) + { + source = source.Take(P_0.LevelsCount); + } + if (P_0.CalculateCumulative) + { + double ?? = 0.0; + source = source.Select(delegate(Level2Item level2Item) + { + ?? += level2Item.Size; + level2Item.Cumulative = ??; + return level2Item; + }); + } + return source.ToArray(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static decimal ?(decimal P_0, decimal P_1) + { + return P_0 - P_0 % P_1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static decimal ?(decimal P_0, decimal P_1) + { + decimal num = ?(P_0, P_1); + if (num == P_0) + { + return P_0; + } + return num + P_1; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// Aggregation method + /// + [Published] + public enum AggregateMethod + { + ByPriceLVL, + ByMMIDAndPrice, + None + } + public enum ImplicitOrderBookType + { + Combined, + Implied, + Outright + } + /// + /// Represent access to level2 item. + /// + [Published] + public class Level2Item + { + [CompilerGenerated] + private string ?; + + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private DateTime ?; + + [CompilerGenerated] + private string ?; + + [CompilerGenerated] + private long ?; + + [CompilerGenerated] + private int ?; + + [CompilerGenerated] + private Level2Item[] ?; + + public string Id + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = text; + } + } + + /// + /// Cumulative size + /// + public double Cumulative + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = num; + } + } + + /// + /// Imbalance Percent + /// + public double ImbalancePercent + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + internal set + { + ? = num; + } + } + + /// + /// Price + /// + public double Price + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + /// + /// Size + /// + public double Size + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + /// + /// Time + /// + public DateTime QuoteTime + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = dateTime; + } + } + + /// + /// MMID + /// + public string MMID + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = text; + } + } + + public long Priority + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + /// + /// Number orders + /// + public int NumberOrders + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + public Level2Item[] DetailedLevels + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + private Level2Item() + { + Cumulative = double.NaN; + ImbalancePercent = double.NaN; + } + + internal Level2Item(double P_0, double P_1, DateTime P_2, string P_3, long P_4, int P_5) + : this() + { + Price = P_0; + Size = P_1; + QuoteTime = P_2; + MMID = P_3; + Priority = P_4; + NumberOrders = P_5; + } + + internal Level2Item(double P_0, double P_1, DateTime P_2, string P_3, long P_4, int P_5, Level2Item[] P_6) + : this(P_0, P_1, P_2, P_3, P_4, P_5) + { + DetailedLevels = P_6; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(Size); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } +} +namespace ? +{ + internal class ? : IComparer + { + private readonly bool ?; + + public ?(bool P_0) + { + ? = P_0; + } + + public int Compare(Level2Item x, Level2Item y) + { + double price = x.Price; + double size = x.Size; + long ticks = x.QuoteTime.Ticks; + double price2 = y.Price; + double size2 = y.Size; + long ticks2 = y.QuoteTime.Ticks; + double num = price - price2; + if (num <= -1E-12) + { + if (!?) + { + return -1; + } + return 1; + } + if (num >= 1E-12) + { + if (!?) + { + return 1; + } + return -1; + } + if (ticks > ticks2) + { + return 1; + } + if (ticks < ticks2) + { + return -1; + } + if (size > size2) + { + return -1; + } + if (size < size2) + { + return 1; + } + return string.CompareOrdinal(x.MMID, y.MMID); + } + } +} +namespace TradingPlatform.BusinessLayer +{ + [DataContract(Name = "OptionSerie", Namespace = "TradingPlatform")] + public sealed class OptionSerie : BusinessObject, IMessageBuilder, IComparable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Exchange ??; + + [CompilerGenerated] + private OptionSerieType ??; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public DateTime ExpirationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public Exchange Exchange + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = exchange; + } + } + + public OptionSerieType SerieType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = optionSerieType; + } + } + + public string VisualName + { + get + { + string text = ExpirationDate.ToShortDateString(); + if (string.IsNullOrEmpty(Name)) + { + return text; + } + return Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + text; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 3); + defaultInterpolatedStringHandler.AppendFormatted(UnderlierId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ExpirationDate.ToShortDateString()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + internal OptionSerie(string P_0) + : base(P_0) + { + } + + internal void ?(MessageOptionSerie P_0) + { + Id = P_0.Id; + ExpirationDate = P_0.ExpirationDate; + Name = P_0.Name; + UnderlierId = P_0.UnderlierId; + SerieType = P_0.SerieType; + if (!string.IsNullOrEmpty(P_0.ExchangeId) && ConnectionCache != null && ConnectionCache.ExchangesCache.?(P_0.ExchangeId, out var exchange)) + { + Exchange = exchange; + } + } + + private MessageOptionSerie ?() + { + return new MessageOptionSerie + { + Id = Id, + ExpirationDate = ExpirationDate, + Name = Name, + UnderlierId = UnderlierId + }; + } + + MessageOptionSerie IMessageBuilder.BuildMessage() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + public override bool Equals(object obj) + { + if (obj is OptionSerie optionSerie && base.ConnectionId == optionSerie.ConnectionId && Id == optionSerie.Id) + { + return UnderlierId == optionSerie.UnderlierId; + } + return false; + } + + public override int GetHashCode() + { + return ((-1159877490 * -1521134295 + ExpirationDate.GetHashCode()) * -1521134295 + EqualityComparer.Default.GetHashCode(Id)) * -1521134295 + EqualityComparer.Default.GetHashCode(UnderlierId); + } + + public int CompareTo(object obj) + { + return CompareTo(obj); + } + } + [ProtoContract] + public class PnL + { + [CompilerGenerated] + private PnLItem ?; + + [CompilerGenerated] + private PnLItem ?; + + [CompilerGenerated] + private PnLItem ?; + + [CompilerGenerated] + private PnLItem ?; + + [ProtoMember(1)] + public PnLItem GrossPnL + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + [ProtoMember(2)] + public PnLItem NetPnL + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + [ProtoMember(3)] + public PnLItem Fee + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + [ProtoMember(4)] + public PnLItem Swaps + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + } + [DataContract(Name = "PnLItem", Namespace = "TradingPlatform")] + [ProtoContract] + public class PnLItem : BusinessObject + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + private Asset ??; + + [DataMember(Name = "Value")] + [ProtoMember(1)] + public double Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AssetID")] + [ProtoMember(2)] + public string AssetID + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "ValuePercent")] + [ProtoMember(3)] + public double ValuePercent + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Asset Asset => ?? ?? (?? = Core.Instance.Assets.FirstOrDefault((Asset P_0) => P_0.ConnectionId == base.ConnectionId && P_0.Id == AssetID)); + + public PnLItem() + : base(string.Empty) + { + ValuePercent = double.NaN; + } + + public override bool Equals(object obj) + { + if (!(obj is PnLItem pnLItem)) + { + return false; + } + if (Value != pnLItem.Value) + { + return false; + } + if (AssetID != pnLItem.AssetID) + { + return false; + } + return true; + } + + public override int GetHashCode() + { + return (13 * 7 + Value.GetHashCode()) * 7 + AssetID.GetHashCode(); + } + + public string Format() + { + string text = FormatPercent(); + if (text == null) + { + return FormatValue(); + } + return FormatValue() + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + + public string FormatValue() + { + return Asset?.FormatPriceWithCurrency(Value) ?? Value.Format(); + } + + public string FormatPercent() + { + if (!double.IsNaN(ValuePercent)) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(0, 1); + defaultInterpolatedStringHandler.AppendFormatted(ValuePercent, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + return null; + } + + public override string ToString() + { + return Format(); + } + + [CompilerGenerated] + private bool ?(Asset P_0) + { + if (P_0.ConnectionId == base.ConnectionId) + { + return P_0.Id == AssetID; + } + return false; + } + } + [ProtoContract] + public sealed class SlTpHolder : ICloneable, IXElementSerialization, IEquatable, ICustomizable + { + [CompilerGenerated] + private CloseOrderType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private PriceMeasurement ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private double ??; + + [ProtoMember(1)] + public CloseOrderType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = closeOrderType; + } + } + + [ProtoMember(2)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + [ProtoMember(3)] + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + public PriceMeasurement PriceMeasurement + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = priceMeasurement; + } + } + + [ProtoMember(5)] + public bool IsTrailing + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + [ProtoMember(6)] + public double QuantityPercentage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Type, new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1) + }), + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Price), + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity), + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)PriceMeasurement, new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1) + }), + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsTrailing), + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuantityPercentage) + }; + } + set + { + Type = (CloseOrderType)value.GetValueOrDefault((int)Type, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Price = value.GetValueOrDefault(Price, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Quantity = value.GetValueOrDefault(Quantity, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + PriceMeasurement = (PriceMeasurement)value.GetValueOrDefault((int)PriceMeasurement, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + IsTrailing = value.GetValueOrDefault(IsTrailing, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + QuantityPercentage = value.GetValueOrDefault(QuantityPercentage, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [NotPublished] + public SlTpHolder(IList settings) + { + Settings = settings; + } + + internal SlTpHolder() + { + } + + public static SlTpHolder CreateSL(double price, PriceMeasurement priceMeasurement = PriceMeasurement.Absolute, bool isTrailing = false, double quantity = double.NaN, double quantityPercentage = double.NaN) + { + return new SlTpHolder + { + Type = CloseOrderType.StopLoss, + Price = price, + Quantity = quantity, + PriceMeasurement = priceMeasurement, + IsTrailing = isTrailing, + QuantityPercentage = quantityPercentage + }; + } + + public static SlTpHolder CreateTP(double price, PriceMeasurement priceMeasurement = PriceMeasurement.Absolute, double quantity = double.NaN, double quantityPercentage = double.NaN) + { + return new SlTpHolder + { + Type = CloseOrderType.TakeProfit, + Price = price, + Quantity = quantity, + PriceMeasurement = priceMeasurement, + IsTrailing = false, + QuantityPercentage = quantityPercentage + }; + } + + public string Format(Symbol symbol) + { + if (symbol == null) + { + return Price.ToString(); + } + if (PriceMeasurement == PriceMeasurement.Absolute) + { + return symbol.FormatPrice(Price); + } + return symbol.FormatOffset(Price, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + public object Clone() + { + if (Type == CloseOrderType.StopLoss) + { + return CreateSL(Price, PriceMeasurement, IsTrailing, Quantity, QuantityPercentage); + } + return CreateTP(Price, PriceMeasurement, Quantity, QuantityPercentage); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(GetType().Name); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)Type).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Price)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)PriceMeasurement).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsTrailing)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuantityPercentage)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Type = (CloseOrderType)xElement.ToInt(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Price = xElement2.ToDouble(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + PriceMeasurement = (PriceMeasurement)xElement3.ToInt(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + IsTrailing = xElement4.ToBool(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + Quantity = xElement5.ToDouble(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + QuantityPercentage = xElement6.ToDouble(); + } + if (Quantity == 0.0) + { + Quantity = double.NaN; + } + } + + public bool Equals(SlTpHolder other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Type == other.Type && Price.Equals(other.Price) && Quantity.Equals(other.Quantity) && QuantityPercentage.Equals(other.QuantityPercentage) && PriceMeasurement == other.PriceMeasurement) + { + return IsTrailing == other.IsTrailing; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((SlTpHolder)obj); + } + + public override int GetHashCode() + { + return (int)(((uint)((((((((int)Type * 397) ^ Price.GetHashCode()) * 397) ^ Quantity.GetHashCode()) * 397) ^ QuantityPercentage.GetHashCode()) * 397) ^ (uint)PriceMeasurement) * 397) ^ IsTrailing.GetHashCode(); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(9, 4); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PriceMeasurement); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + object value; + if (!double.IsNaN(QuantityPercentage)) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler2 = new DefaultInterpolatedStringHandler(0, 1); + defaultInterpolatedStringHandler2.AppendFormatted(QuantityPercentage, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + value = defaultInterpolatedStringHandler2.ToStringAndClear(); + } + else + { + value = $"{Quantity}"; + } + defaultInterpolatedStringHandler.AppendFormatted((string?)value); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public readonly struct SymbolComplexIdentifier : IEquatable + { + [CompilerGenerated] + private readonly string ?; + + private readonly ExchangeComplexIdentifier ?; + + public string ConnectionId => ?.ConnectionId; + + public string ExchangeId => ?.ExchangeId; + + public string SymbolId + { + [CompilerGenerated] + get + { + return ?; + } + } + + public SymbolComplexIdentifier(string connectionId, string exchangeId, string symbolId) + { + ? = new ExchangeComplexIdentifier(connectionId, exchangeId); + ? = symbolId; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 3); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(ExchangeId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(ConnectionId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public bool Equals(SymbolComplexIdentifier other) + { + if (?.Equals(other.?)) + { + return SymbolId == other.SymbolId; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj is SymbolComplexIdentifier other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (?.GetHashCode() * 397) ^ SymbolId.GetHashCode(); + } + + public static bool operator ==(SymbolComplexIdentifier left, SymbolComplexIdentifier right) + { + return left.Equals(right); + } + + public static bool operator !=(SymbolComplexIdentifier left, SymbolComplexIdentifier right) + { + return !left.Equals(right); + } + } + [Serializable] + [DataContract] + public class SymbolInfo : BusinessObjectInfo, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private SymbolType ??; + + [CompilerGenerated] + private FutureContractType? ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [DataMember(Name = "exchangeId")] + public string ExchangeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + [DataMember(Name = "symbolType")] + public SymbolType SymbolType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = symbolType; + } + } + + [DataMember(Name = "futuresContractType")] + public FutureContractType? FutureContractType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = futureContractType; + } + } + + [DataMember(Name = "underlierId")] + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + [DataMember(Name = "root")] + public string Root + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + [DataMember(Name = "expirationTime")] + public DateTime ExpirationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = dateTime; + } + } + + public new static SymbolInfo Empty => new SymbolInfo + { + Id = string.Empty, + ConnectionId = string.Empty, + Name = string.Empty, + ExchangeId = string.Empty, + SymbolType = SymbolType.Unknown, + FutureContractType = null, + UnderlierId = string.Empty, + Root = string.Empty, + ExpirationDate = default(DateTime) + }; + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExchangeId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SymbolType.ToString())); + if (FutureContractType.HasValue) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), FutureContractType.ToString())); + } + if (!string.IsNullOrEmpty(UnderlierId)) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), UnderlierId)); + } + if (!string.IsNullOrEmpty(Root)) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Root)); + } + if (ExpirationDate != default(DateTime)) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationDate)); + } + return xElement; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ExchangeId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null && Enum.TryParse(xElement2.Value, out var result)) + { + FutureContractType = result; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null && Enum.TryParse(xElement3.Value, out var result2)) + { + SymbolType = result2; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + UnderlierId = xElement4.Value; + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + Root = xElement5.Value; + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + ExpirationDate = xElement6.ToDateTime(); + } + } + + public bool Equals(SymbolInfo other) + { + if ((object)other == null) + { + return false; + } + if ((object)this == other) + { + return true; + } + if (Equals((BusinessObjectInfo)other) && ExchangeId == other.ExchangeId && SymbolType == other.SymbolType && FutureContractType == other.FutureContractType && UnderlierId == other.UnderlierId && Root == other.Root) + { + return ExpirationDate.Equals(other.ExpirationDate); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((SymbolInfo)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(base.GetHashCode(), ExchangeId, (int)SymbolType, FutureContractType, UnderlierId, Root, ExpirationDate); + } + + public static bool operator ==(SymbolInfo left, SymbolInfo right) + { + return object.Equals(left, right); + } + + public static bool operator !=(SymbolInfo left, SymbolInfo right) + { + return !object.Equals(left, right); + } + } + [DataContract(Name = "TradingObject")] + public abstract class TradingObject : BusinessObject, ITradingObject + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Account ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private string ??; + + private readonly Lazy ??; + + [DataMember(Name = "ID")] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + [DataMember(Name = "Account")] + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + [DataMember(Name = "Instrument")] + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + [DataMember(Name = "Side")] + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + [DataMember(Name = "Comment")] + public string Comment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public AdditionalInfoCollection AdditionalInfo + { + get + { + if (!??.IsValueCreated) + { + return null; + } + return ??.Value; + } + } + + protected TradingObject(string connectionId) + : base(connectionId) + { + ?? = new Lazy(); + } + + protected void ProcessAdditionalItems(List items) + { + if (items == null) + { + return; + } + foreach (AdditionalInfoItem item in items) + { + ??.Value.?(item); + } + } + } + public class TradingSignalEventArgs : EntityLifecycleEventArgs + { + [CompilerGenerated] + private readonly TradingSignal ??; + + public TradingSignal TradingSignal + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } + [DataContract(Name = "VariableTick", Namespace = "TradingPlatform")] + [ProtoContract] + public class VariableTick : IXElementSerialization + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [DataMember] + [ProtoMember(1)] + public double LeftBorder + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + [DataMember] + [ProtoMember(2)] + public bool IncludeLeftBorder + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + [DataMember] + [ProtoMember(3)] + public double TickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + [DataMember] + [ProtoMember(4)] + public double TickCost + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + [DataMember] + [ProtoMember(5)] + public double RightBorder + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + [DataMember] + [ProtoMember(6)] + public int Precision + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// ???????? ?? ????????? + /// + public bool CheckPrice(double price) + { + if ((!(price > LeftBorder) || !(price < RightBorder)) && (price != LeftBorder || !IncludeLeftBorder)) + { + if (price == RightBorder) + { + return !IncludeLeftBorder; + } + return false; + } + return true; + } + + public VariableTick(double lowLimit, double highLimit, bool allowLimit, double tickSize, double tickCost, int? precision = null) + { + LeftBorder = lowLimit; + RightBorder = highLimit; + IncludeLeftBorder = allowLimit; + TickSize = (double)(decimal)tickSize; + TickCost = tickCost; + Precision = ((!precision.HasValue) ? CoreMath.GetValuePrecision((decimal)TickSize) : precision.Value); + } + + public VariableTick(double tickSize, double tickCost = 1.0, int? precision = null) + : this(double.NegativeInfinity, double.PositiveInfinity, allowLimit: true, tickSize, tickCost, precision) + { + } + + internal VariableTick() + { + } + + public override string ToString() + { + return LeftBorder + ((IncludeLeftBorder && LeftBorder != double.NegativeInfinity) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ((!IncludeLeftBorder && RightBorder != double.PositiveInfinity) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + RightBorder; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LeftBorder.ToString(CultureInfo.InvariantCulture))); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), RightBorder.ToString(CultureInfo.InvariantCulture))); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IncludeLeftBorder)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TickSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TickCost)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Precision)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + LeftBorder = xElement.ToDouble(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + RightBorder = xElement2.ToDouble(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + IncludeLeftBorder = xElement3.ToBool(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + TickSize = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + TickCost = xElement5.ToDouble(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + Precision = xElement6.ToInt(); + } + } + } + /// + /// Represents information about connection and provides an access to the current trading information(Symbols, Orders, Position, Accounts etc.). + /// + [Published] + public sealed class Connection : ICustomizable, IComparable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func> ??; + + public static Func> ??; + + public static Func ??; + + public static Func, Symbol> ??; + + public static Func ??; + + public static Func, Symbol> ??; + + internal SettingItem ?(SettingItem P_0) + { + return P_0.GetCopy(); + } + + internal int ?(Symbol P_0) + { + return P_0.TotalSubscriptionsCount; + } + + internal long ?(Period P_0) + { + return P_0.Ticks; + } + + internal bool ?(Connection P_0) + { + if (P_0.State != ConnectionState.Connected) + { + return P_0.State == ConnectionState.Connecting; + } + return true; + } + + internal bool ?(Connection P_0) + { + return P_0.Type == ConnectionType.General; + } + + internal bool ?(Connection P_0) + { + return Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), P_0.Id).Status != TradingOperationStatus.Allowed; + } + + internal bool ?(SettingItem P_0) + { + return P_0 is SettingItemOAuth; + } + + internal string ?(PlaceOrderRequestParameters P_0) + { + return P_0.Symbol.ConnectionId; + } + + internal DateTime ?(OptionSerie P_0) + { + return P_0.ExpirationDate; + } + + internal DateTime ?(UserTradesInterval P_0) + { + return P_0.Interval.From; + } + + internal IEnumerable ?(UserTradesInterval P_0) + { + return P_0.Trades; + } + + internal IEnumerable ?(UserTradesInterval P_0) + { + return P_0.Trades; + } + + internal Symbol ?(Order P_0) + { + return P_0.Symbol; + } + + internal Symbol ?(IGrouping P_0) + { + return P_0.Key; + } + + internal Symbol ?(Position P_0) + { + return P_0.Symbol; + } + + internal Symbol ?(IGrouping P_0) + { + return P_0.Key; + } + } + + [CompilerGenerated] + private sealed class ? + { + public GetStrikesRequestParameters ??; + + internal bool ?(Symbol P_0) + { + if (P_0.OptionSerie != null) + { + return P_0.OptionSerie.Id == ??.SerieId; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public IList ??; + + public IList ??; + + public string[] ??; + + public SearchSymbolsRequestParameters ??; + + internal bool ?(Symbol P_0) + { + return ??.Contains(P_0.ExchangeId); + } + + internal bool ?(Symbol P_0) + { + return ??.Contains(P_0.SymbolType); + } + + internal bool ?(Symbol P_0) + { + return Connection.?(??, P_0, ??.GetSynonyms); + } + } + + [CompilerGenerated] + private sealed class ? + { + public TradesHistoryRequestParameters ??; + + internal bool ?(MessageTrade P_0) + { + if (!string.IsNullOrEmpty(??.SymbolId)) + { + return P_0.SymbolId == ??.SymbolId; + } + return true; + } + } + + [CompilerGenerated] + private sealed class ? + { + public CancellationToken ??; + + public AccountTradesLoadingCallback ??; + + public Connection ??; + + public TradesHistoryRequestParameters ??; + + public CancellationTokenSource ??; + } + + [CompilerGenerated] + private sealed class ? + { + public Interval ??; + + public TradesHistoryRequestParameters ??; + + public List ??; + + public ? ??; + + internal void ?(IList P_0, bool P_1) + { + try + { + if (??.??.IsCancellationRequested) + { + return; + } + if (P_0 == null) + { + if (P_1) + { + ??.??.InvokeSafely(new List(), P_1); + } + return; + } + P_0 = ??.??.?(??, P_0).Trades.ToList(); + ??.AddRange(P_0); + List list = ??.??.?(P_0, ??.??).ToList(); + ??.??.InvokeSafely(list, P_1); + if (P_1 && string.IsNullOrEmpty(??.??.SymbolId) && !??.??.??.UsersTradesCacheMetadata.AllowSingleSymbolLoading) + { + ??.??.???.Save(new UserTradesInterval + { + Interval = ??, + Trades = ?? + }); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + if (P_1) + { + ??.??.Dispose(); + } + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public TradesHistoryRequestParameters ??; + + internal bool ?(MessageTrade P_0) + { + return ??.Interval.Contains(P_0.DateTime); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Connection ??; + + public CancellationToken ??; + + internal void ?(string P_0) + { + ??.ConnectingProgress = P_0; + } + + internal bool ?(Connection P_0) + { + return P_0 != ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + public ? ??; + + internal void ?() + { + try + { + ??.??.GetTrades(new TradesHistoryRequestParameters + { + From = ??.AddDays(-2.0), + To = ??, + CancellationToken = ??.?? + }); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public Connection ??; + + public SubscribeQuotesParameters ??; + + internal void ?() + { + ??.??.SubscribeSymbol(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Connection ??; + + public SubscribeQuotesParameters ??; + + internal void ?() + { + ??.??.UnSubscribeSymbol(??); + } + } + + internal const string ?? = "Test"; + + internal ? ??; + + private string ??; + + [CompilerGenerated] + private ConnectionType ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private TimeSpan? ??; + + [CompilerGenerated] + private TimeSpan? ??; + + private DateTime ??; + + [CompilerGenerated] + private ConnectionResult ??; + + [CompilerGenerated] + private ? ??; + + [CompilerGenerated] + private VolumeAnalysisStorage ??; + + private UsersTradesStorage ??; + + private Vendor ??; + + private CancellationTokenSource ??; + + [CompilerGenerated] + private readonly ConnectionInfo ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private Limiter ??; + + private readonly ActionBufferedProcessor ??; + + /// + /// Provides access to all business objects which are belong to this connection + /// + public IBusinessObjectsProvider BusinessObjects => ??; + + /// + /// Gets connection Id + /// + public string Id + { + get + { + return Info.ConnectionId; + } + private set + { + Info.ConnectionId = connectionId; + } + } + + /// + /// Gets connection Name + /// + public string Name + { + get + { + return Info.Name; + } + set + { + Info.Name = value; + } + } + + /// + /// Gets connection's vendor name + /// + public string VendorName => Info.VendorName; + + /// + /// Contains list of connection settings. Will be reused on each population time. + /// + public IList Settings + { + get + { + return Info.Settings; + } + set + { + Info.Settings = value; + } + } + + /// + /// Gets connection's state (Connected/Connecting/Fail etc.) + /// + public ConnectionState State + { + get + { + return Info.ConnectionState; + } + private set + { + if (Info.ConnectionState != connectionState) + { + ConnectionState connectionState2 = Info.ConnectionState; + Info.ConnectionState = connectionState; + ?? = ((connectionState == ConnectionState.Connected) ? Core.Instance.TimeUtils.DateTimeUtcNow : default(DateTime)); + ?(connectionState2); + } + } + } + + public string ConnectingProgress + { + get + { + return ??; + } + private set + { + if (!(?? == text)) + { + ?? = text; + ???.Invoke(this, new ConnectionConnectingProgressChangedEventArgs(ConnectingProgress)); + } + } + } + + /// + /// Defines connection type + /// + public ConnectionType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Represents connection ping time + /// + public TimeSpan? PingTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + public TimeSpan? RoundTripTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + /// + /// Messages count that one is waited to process + /// + public int MessagesQueueDepth => ???.QueueDepth ?? 0; + + public TimeSpan Uptime + { + get + { + if (!(?? == default(DateTime))) + { + return Core.Instance.TimeUtils.DateTimeUtcNow - ??; + } + return TimeSpan.Zero; + } + } + + /// + /// Gets a matched available metadata info with the vendor's side + /// + public HistoryMetadata HistoryMetaData => ??.HistoryMetadata?.Copy; + + public TradesHistoryMetadata TradesHistoryMetadata + { + get + { + if (??.UsersTradesCacheMetadata != null) + { + return new TradesHistoryMetadata(??.UsersTradesCacheMetadata); + } + return null; + } + } + + public VolumeAnalysisMetadata VolumeAnalysisMetadata => ??.VolumeAnalysisMetadata?.Copy; + + public IEnumerable NewsFeedSettings => ???.NewsFeedSettings?.Select((SettingItem P_0) => P_0.GetCopy()); + + public ConnectionResult LastConnectionResult + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = connectionResult; + } + } + + internal ? HistoryLoadingManager + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = ?; + } + } + + internal VolumeAnalysisStorage VolumeAnalysisStorage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = volumeAnalysisStorage; + } + } + + internal bool Connected => State == ConnectionState.Connected; + + public ConnectionInfo Info + { + [CompilerGenerated] + get + { + return ??; + } + } + + public int TotalSubscriptionsCount => BusinessObjects.Symbols.Sum((Symbol P_0) => P_0.TotalSubscriptionsCount); + + public DateTime ServerTime => ???.ServerTime ?? Core.Instance.TimeUtils.DateTimeUtcNow; + + [NotPublished] + public Limiter Limitation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = limiter; + } + } + + /// + /// Will be triggered when changed. + /// + public event EventHandler StateChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + /// + /// Will be triggered when changed. + /// + public event EventHandler ConnectingProgressChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler NewRequest + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler NewPerformedRequest + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + internal Connection(ConnectionInfo P_0) + { + ?? = P_0; + Type = ConnectionType.General; + if (string.IsNullOrEmpty(P_0.ConnectionId)) + { + Id = Guid.NewGuid().ToString(); + } + State = ConnectionState.Disconnected; + ?? = new ActionBufferedProcessor(); + } + + /// + /// Establishes a connection to a specified vendor + /// + /// + public ConnectionResult Connect() + { + LastConnectionResult = new ConnectionResult(); + IProgress progress = new Progress(delegate(string P_0) + { + ConnectingProgress = P_0; + }); + if (State == ConnectionState.Connected) + { + return LastConnectionResult; + } + if (State == ConnectionState.Connecting) + { + LastConnectionResult.State = ConnectionState.Connecting; + LastConnectionResult.Message = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return LastConnectionResult; + } + if (State == ConnectionState.Disconnecting) + { + LastConnectionResult.State = ConnectionState.Connecting; + LastConnectionResult.Message = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return LastConnectionResult; + } + ?? = new CancellationTokenSource(); + CancellationToken ?? = ??.Token; + ?? = (Info.SyncMsgProcessing ? new ?(Id) : new ?(Id)); + progress.Report(null); + State = ConnectionState.Connecting; + ??.?(); + VendorInfo vendorInfo = Core.Instance.Vendors[VendorName]; + ?? = vendorInfo.?(); + ??.NewMessage += ?; + try + { + ??.ThrowIfCancellationRequested(); + vendorInfo.?(); + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?(??); + LastConnectionResult = ??.Connect(new ConnectRequestParameters + { + ConnectionSettings = Settings, + BrowserFactory = Core.Instance.BrowserFactory, + ConnectionId = Id, + CancellationToken = ??, + ConnectingProgress = progress + }); + if (LastConnectionResult.UpdatedSettings != null) + { + Settings = LastConnectionResult.UpdatedSettings; + } + ??.ThrowIfCancellationRequested(); + if (LastConnectionResult.State == ConnectionState.Fail) + { + State = ConnectionState.Disconnecting; + ?(); + State = ConnectionState.Disconnected; + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + LastConnectionResult.Message); + return LastConnectionResult; + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + IList sessions = ??.GetSessions(??); + if (sessions != null) + { + foreach (MessageSessionsContainer item in sessions) + { + ?(item); + } + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + IList exchanges = ??.GetExchanges(??); + if (exchanges != null) + { + foreach (MessageExchange item2 in exchanges) + { + ?(item2); + } + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + IList symbolGroups = ??.GetSymbolGroups(??); + if (symbolGroups != null) + { + foreach (MessageSymbolGroup item3 in symbolGroups) + { + ?(item3); + } + } + ??.ThrowIfCancellationRequested(); + ??.HistoryMetadata = ??.GetHistoryMetadata(??); + ??.HistoryMetadata.AllowedPeriodsHistoryAggregationTime = ??.HistoryMetadata.AllowedPeriodsHistoryAggregationTime.OrderByDescending((Period P_0) => P_0.Ticks).ToArray(); + ??.VolumeAnalysisMetadata = ??.GetVolumeAnalysisMetadata(); + ??.NewsFeedSettings = ??.GetNewsProviderSettings(??); + ??.UsersTradesCacheMetadata = ??.GetTradesMetadata(); + ??.LimitationMetadata = ??.GetLimitationMetadata(); + if (??.LimitationMetadata?.Limits != null) + { + Limitation = new Limiter(??.LimitationMetadata); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (OrderType allowedOrderType in ??.GetAllowedOrderTypes(??)) + { + allowedOrderType.ConnectionId = Id; + ??.OrderTypesCache.?(allowedOrderType.Id, allowedOrderType); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageAsset asset in ??.GetAssets(??)) + { + ?(asset); + } + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + ?(??.GetSymbolTypes(??)); + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageAccount account in ??.GetAccounts(??)) + { + ?(account); + } + ??.ThrowIfCancellationRequested(); + foreach (MessageCryptoAssetBalances cryptoAssetBalance in ??.GetCryptoAssetBalances(??)) + { + ?(cryptoAssetBalance); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageOptionSerie item4 in ??.GetAllOptionSeries(??)) + { + ?(item4); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageSymbol symbol in ??.GetSymbols(??)) + { + ?(symbol); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageRule rule in ??.GetRules(??)) + { + ?(rule); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageOpenPosition position in ??.GetPositions(??)) + { + ?(position); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageClosedPosition closedPosition in ??.GetClosedPositions(??)) + { + ?(closedPosition); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageReportType reportsMetaDatum in ??.GetReportsMetaData(??)) + { + ?(reportsMetaDatum); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageOpenOrder pendingOrder in ??.GetPendingOrders(??)) + { + ?(pendingOrder); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageAccountOperation accountOperation in ??.GetAccountOperations(??)) + { + ?(accountOperation); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + foreach (MessageTradingSignal tradingSignal in ??.GetTradingSignals(??)) + { + ?(tradingSignal); + } + ??.ThrowIfCancellationRequested(); + progress.Report(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + ??.WaitAllMessagesProcess(??); + progress.Report(null); + ??.ThrowIfCancellationRequested(); + ??.OnConnected(??); + ??.ThrowIfCancellationRequested(); + ? ? = new ? + { + AllowLocalStorage = ??.HistoryMetadata.UseHistoryLocalCache, + DegreeOfParallelism = ??.HistoryMetadata.DegreeOfParallelism, + LoadHistoryDelegate = ? + }; + if (?.AllowLocalStorage) + { + ?.LocalStorageConnectionString = Path.Combine(Const.HISTORY_PATH, (Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + Id + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()).EncodeFilePathPart(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + HistoryLoadingManager = ?.?(?); + if (?.AllowLocalStorage) + { + VolumeAnalysisStorage = VolumeAnalysisStorage.Create(Path.Combine(Const.VOLUME_ANALYSIS_PATH, (Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + Id + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()).EncodeFilePathPart(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + if (??.UsersTradesCacheMetadata.AllowLocalStorage) + { + ?? = UsersTradesStorage.Create(Path.Combine(Const.USER_TRADES_CACHE_PATH, (Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + Id + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()).EncodeFilePathPart(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), Id); + if (??.UsersTradesCacheMetadata.LoadTradesFromCurrentTradingDate) + { + DateTime ?? = Core.Instance.TimeUtils.DateTimeUtcNow; + Task.Factory.StartNew(delegate + { + try + { + GetTrades(new TradesHistoryRequestParameters + { + From = ??.AddDays(-2.0), + To = ??, + CancellationToken = ?? + }); + } + catch (Exception ex3) + { + Core.Instance.Loggers.Log(ex3); + } + }, ??); + } + } + ??.?? = true; + ???.Start(); + State = ConnectionState.Connected; + } + catch (OperationCanceledException) + { + LastConnectionResult.State = ConnectionState.Fail; + LastConnectionResult.Message = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + LastConnectionResult.Cancelled = true; + State = ConnectionState.Disconnecting; + ?(); + State = ConnectionState.Disconnected; + } + catch (Exception exception) + { + LastConnectionResult.State = ConnectionState.Fail; + LastConnectionResult.Message = exception.GetFullMessageRecursive(); + State = ConnectionState.Fail; + Core.Instance.Loggers.Log(LastConnectionResult.Message, LoggingLevel.Verbose); + ?(); + State = ConnectionState.Disconnected; + } + finally + { + vendorInfo.?(); + } + ConnectionResult lastConnectionResult = LastConnectionResult; + if (lastConnectionResult != null && lastConnectionResult.State == ConnectionState.Connected) + { + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + else + { + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + LastConnectionResult?.Message); + } + if (Type == ConnectionType.General && State == ConnectionState.Connected && Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Id).Status != TradingOperationStatus.Allowed) + { + try + { + if ((Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) == null) + { + Connection[] array = (from P_0 in Core.Instance.Connections.All + where P_0 != this + where P_0.State == ConnectionState.Connected || P_0.State == ConnectionState.Connecting + where P_0.Type == ConnectionType.General + where Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), P_0.Id).Status != TradingOperationStatus.Allowed + select P_0).ToArray(); + if (array.Any()) + { + Connection[] array2 = array; + foreach (Connection connection in array2) + { + if (connection.LastConnectionResult != null) + { + connection.LastConnectionResult.State = ConnectionState.Fail; + connection.LastConnectionResult.Message = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + connection.Disconnect(); + } + MessageDealTicket messageDealTicket = new MessageDealTicket(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?(messageDealTicket); + } + } + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + } + return LastConnectionResult; + } + + private void ?(CancellationToken P_0) + { + IList settings = Settings; + if (!(settings.GetItemByPath(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemGroup { Value: IList value }) || !(value.FirstOrDefault((SettingItem settingItem) => settingItem is SettingItemOAuth) is SettingItemOAuth settingItemOAuth)) + { + return; + } + OidcClientOptions copy = settingItemOAuth.OidcOptions.GetCopy(); + if (copy == null) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (settingItemOAuth.UpdateIdentityAuthorityUrl != null) + { + copy.Authority = settingItemOAuth.UpdateIdentityAuthorityUrl(settings, P_0); + } + if (string.IsNullOrEmpty(copy.Authority) && copy.ProviderInformation == null) + { + return; + } + int value2 = 55650; + try + { + value2 = TcpIpHelper.GetRandomUnusedPort; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + copy.Browser = new ?(settingItemOAuth.AllowOpenNewWindow, value2) + { + ?? = Core.Instance.OAuthBrowserCreator + }; + if (string.IsNullOrEmpty(copy.RedirectUri)) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value2); + string postLogoutRedirectUri = (copy.RedirectUri = defaultInterpolatedStringHandler.ToStringAndClear()); + copy.PostLogoutRedirectUri = postLogoutRedirectUri; + } + OidcClient oidcClient = new OidcClient(copy); + LoginRequest loginRequest = new LoginRequest + { + BrowserDisplayMode = DisplayMode.Visible, + BrowserTimeout = 300, + BackChannelExtraParameters = settingItemOAuth.BackChannelExtraParameters + }; + OAuthResult oAuthResult = settingItemOAuth.Value as OAuthResult; + Result result = null; + if (oAuthResult != null && !string.IsNullOrEmpty(oAuthResult.RefreshToken) && oAuthResult.UseSavedTokens) + { + RefreshTokenResult refreshTokenResult = null; + if (VendorName.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + UriBuilder uriBuilder = new UriBuilder(copy.ProviderInformation.TokenEndpoint); + NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(string.Empty); + nameValueCollection.Add(new NameValueCollection + { + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + copy.ClientId + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + copy.ClientSecret + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + oAuthResult.RefreshToken + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + } + }); + uriBuilder.Query = nameValueCollection.ToString(); + using HttpClient httpClient = new HttpClient(); + TokenResponse result2 = ProtocolResponse.FromHttpResponseAsync(httpClient.Send(new HttpRequestMessage(HttpMethod.Get, uriBuilder.Uri), P_0)).Result; + if (result2 != null && !result2.IsError) + { + refreshTokenResult = new RefreshTokenResult(); + try + { + Type? typeFromHandle = typeof(RefreshTokenResult); + typeFromHandle.GetProperty(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.SetValue(refreshTokenResult, result2.AccessToken); + typeFromHandle.GetProperty(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.SetValue(refreshTokenResult, result2.RefreshToken); + typeFromHandle.GetProperty(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.SetValue(refreshTokenResult, result2.ExpiresIn); + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + } + else + { + refreshTokenResult = oidcClient.RefreshTokenAsync(oAuthResult.RefreshToken, null, null, P_0).Result; + } + result = refreshTokenResult; + oAuthResult.RequestRefreshResult = refreshTokenResult; + } + else if (VendorName.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + result = new LoginResult(); + BrowserOptions options = new BrowserOptions(new RequestUrl(copy.ProviderInformation.AuthorizeEndpoint).CreateAuthorizeUrl(copy.ClientId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), redirectUri: copy.RedirectUri, scope: copy.Scope), copy.RedirectUri) + { + Timeout = TimeSpan.FromSeconds(loginRequest.BrowserTimeout), + DisplayMode = loginRequest.BrowserDisplayMode + }; + BrowserResult result3 = copy.Browser.InvokeAsync(options, P_0).Result; + if (result3.IsError) + { + throw new Exception(result3.Error); + } + NameValueCollection nameValueCollection2 = HttpUtility.ParseQueryString(result3.Response); + if (!nameValueCollection2.AllKeys.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + using HttpClient httpClient2 = new HttpClient(); + new TokenClient(httpClient2, new TokenClientOptions + { + Address = copy.ProviderInformation.TokenEndpoint, + ClientId = copy.ClientId, + ClientSecret = copy.ClientSecret + }); + string value3 = nameValueCollection2[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()]; + UriBuilder uriBuilder2 = new UriBuilder(copy.ProviderInformation.TokenEndpoint); + NameValueCollection nameValueCollection3 = HttpUtility.ParseQueryString(string.Empty); + nameValueCollection3.Add(new NameValueCollection + { + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + copy.ClientId + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + copy.ClientSecret + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + copy.RedirectUri + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + value3 + } + }); + uriBuilder2.Query = nameValueCollection3.ToString(); + TokenResponse result4 = ProtocolResponse.FromHttpResponseAsync(httpClient2.Send(new HttpRequestMessage(HttpMethod.Get, uriBuilder2.Uri), P_0)).Result; + if (result4.IsError) + { + result.Error = result4.Error; + } + oAuthResult.TokenResponce = result4; + } + else + { + if (oAuthResult != null && !string.IsNullOrEmpty(oAuthResult.IdentityToken)) + { + LogoutRequest request = new LogoutRequest + { + IdTokenHint = oAuthResult.IdentityToken + }; + oidcClient.LogoutAsync(request, P_0).Wait(P_0); + Task.Delay(700, P_0).Wait(P_0); + } + result = (oAuthResult.RequestTokenResult = oidcClient.LoginAsync(loginRequest, P_0).Result); + } + Settings = new List + { + new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new List { settingItemOAuth }) + }; + if (!result.IsError) + { + return; + } + if (result.Error == BrowserResultType.UserCancel.ToString()) + { + throw new OperationCanceledException(); + } + throw new Exception(result.Error); + } + + /// + /// Closes a connection. + /// + public void Disconnect() + { + if (State == ConnectionState.Connecting) + { + ??.Cancel(); + } + else if (State == ConnectionState.Connected) + { + ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + State = ConnectionState.Disconnecting; + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?(); + State = ConnectionState.Disconnected; + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + private void ?() + { + ???.Stop(); + if (?? != null) + { + try + { + ??.Disconnect(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + ??.NewMessage -= ?; + ?? = null; + } + ???.Stop(); + if (HistoryLoadingManager != null) + { + HistoryLoadingManager.Dispose(); + HistoryLoadingManager = null; + } + if (VolumeAnalysisStorage != null) + { + VolumeAnalysisStorage.Dispose(); + VolumeAnalysisStorage = null; + } + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + if (Limitation != null) + { + Limitation.Dispose(); + Limitation = null; + } + } + + internal void ?() + { + if (?? == null || State != ConnectionState.Connected) + { + return; + } + PingResult pingResult; + try + { + pingResult = ??.Ping(); + if (State != ConnectionState.Connected) + { + return; + } + } + catch (Exception ex) + { + pingResult = new PingResult + { + State = PingEnum.Disconnected + }; + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + if (pingResult != null && pingResult.State == PingEnum.Connected) + { + PingTime = pingResult.PingTime; + RoundTripTime = pingResult.RoundTripTime; + } + else + { + ?(); + State = (pingResult.StopReconnecting ? ConnectionState.Disconnected : ConnectionState.ConnectionLost); + Core.Instance.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (pingResult.StopReconnecting ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : string.Empty)); + } + } + + public void SendCustomRequest(RequestParameters parameters) + { + try + { + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(parameters.CancellationToken, ??.Token); + parameters.CancellationToken = cancellationTokenSource.Token; + ?(parameters); + ??.SendCustomRequest(parameters); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + finally + { + ?(parameters, (object)null); + } + } + + internal void ?(Symbol P_0, SubscribeQuoteType P_1) + { + if (?? != null) + { + SubscribeQuotesParameters ?? = new SubscribeQuotesParameters(P_0.Id, P_1); + ??.Push(delegate + { + ??.SubscribeSymbol(??); + }); + } + } + + internal void ?(Symbol P_0, SubscribeQuoteType P_1) + { + if (?? != null) + { + SubscribeQuotesParameters ?? = new SubscribeQuotesParameters(P_0.Id, P_1); + ??.Push(delegate + { + ??.UnSubscribeSymbol(??); + }); + } + } + + internal TradingOperationResult ?(PlaceOrderRequestParameters P_0) + { + TradingOperationResult tradingOperationResult = null; + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + try + { + if (!Connected) + { + long requestId = placeOrderRequestParameters.RequestId; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(State); + tradingOperationResult = TradingOperationResult.CreateError(requestId, defaultInterpolatedStringHandler.ToStringAndClear()); + return tradingOperationResult; + } + AllowedResult allowedResult = TradingOperations.IsAllowed(TradingOperation.PlaceOrder, new TradingOperationParameters + { + Account = placeOrderRequestParameters.Account, + Symbol = placeOrderRequestParameters.Symbol + }); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + tradingOperationResult = TradingOperationResult.CreateError(placeOrderRequestParameters.RequestId, allowedResult.Reason); + return tradingOperationResult; + } + if (placeOrderRequestParameters.OrderType == null) + { + tradingOperationResult = TradingOperationResult.CreateError(placeOrderRequestParameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return tradingOperationResult; + } + if (placeOrderRequestParameters.TimeInForce == TimeInForce.Default) + { + placeOrderRequestParameters.TimeInForce = placeOrderRequestParameters.OrderType.AllowedTifs.FirstOrDefault(); + } + ?((RequestParameters)placeOrderRequestParameters); + Core.Instance.Loggers.Log(placeOrderRequestParameters, LoggingLevel.Trading, Name); + tradingOperationResult = ??.PlaceOrder(placeOrderRequestParameters); + } + catch (Exception ex) + { + tradingOperationResult = TradingOperationResult.CreateError(placeOrderRequestParameters.RequestId, ex.Message); + } + finally + { + Core.Instance.Loggers.Log(tradingOperationResult, LoggingLevel.Trading, Name); + ?(placeOrderRequestParameters, tradingOperationResult); + } + return tradingOperationResult; + } + + internal TradingOperationResult ?(PlaceMultiOrderOrderRequestParameters P_0) + { + TradingOperationResult tradingOperationResult = null; + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + PlaceMultiOrderOrderRequestParameters placeMultiOrderOrderRequestParameters = new PlaceMultiOrderOrderRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + try + { + if (!Connected) + { + long requestId = placeMultiOrderOrderRequestParameters.RequestId; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(State); + tradingOperationResult = TradingOperationResult.CreateError(requestId, defaultInterpolatedStringHandler.ToStringAndClear()); + return tradingOperationResult; + } + if (placeMultiOrderOrderRequestParameters.OrderParameters == null || !placeMultiOrderOrderRequestParameters.OrderParameters.Any()) + { + tradingOperationResult = TradingOperationResult.CreateError(placeMultiOrderOrderRequestParameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return tradingOperationResult; + } + if (placeMultiOrderOrderRequestParameters.OrderParameters.Select((PlaceOrderRequestParameters placeOrderRequestParameters2) => placeOrderRequestParameters2.Symbol.ConnectionId).Distinct().Count() > 1) + { + tradingOperationResult = TradingOperationResult.CreateError(placeMultiOrderOrderRequestParameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return tradingOperationResult; + } + if (placeMultiOrderOrderRequestParameters.GroupOrderType == GroupOrderType.OCO && Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id).Status != TradingOperationStatus.Allowed) + { + tradingOperationResult = TradingOperationResult.CreateError(placeMultiOrderOrderRequestParameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return tradingOperationResult; + } + PlaceOrderRequestParameters[] orderParameters = placeMultiOrderOrderRequestParameters.OrderParameters; + foreach (PlaceOrderRequestParameters placeOrderRequestParameters in orderParameters) + { + AllowedResult allowedResult = TradingOperations.IsAllowed(TradingOperation.PlaceOrder, new TradingOperationParameters + { + Account = placeOrderRequestParameters.Account, + Symbol = placeOrderRequestParameters.Symbol + }); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + tradingOperationResult = TradingOperationResult.CreateError(placeMultiOrderOrderRequestParameters.RequestId, allowedResult.Reason); + return tradingOperationResult; + } + } + ?((RequestParameters)placeMultiOrderOrderRequestParameters); + Core.Instance.Loggers.Log(placeMultiOrderOrderRequestParameters, LoggingLevel.Trading, Name); + tradingOperationResult = ??.PlaceMultiOrder(placeMultiOrderOrderRequestParameters); + } + catch (Exception ex) + { + tradingOperationResult = TradingOperationResult.CreateError(placeMultiOrderOrderRequestParameters.RequestId, ex.Message); + } + finally + { + Core.Instance.Loggers.Log(tradingOperationResult, LoggingLevel.Trading, Name); + ?(placeMultiOrderOrderRequestParameters, tradingOperationResult); + } + return tradingOperationResult; + } + + internal TradingOperationResult ?(ModifyOrderRequestParameters P_0) + { + TradingOperationResult tradingOperationResult = null; + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + ModifyOrderRequestParameters modifyOrderRequestParameters = new ModifyOrderRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + try + { + if (!Connected) + { + long requestId = modifyOrderRequestParameters.RequestId; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(State); + tradingOperationResult = TradingOperationResult.CreateError(requestId, defaultInterpolatedStringHandler.ToStringAndClear()); + return tradingOperationResult; + } + AllowedResult allowedResult = TradingOperations.IsAllowed(TradingOperation.ModifyOrder, new TradingOperationParameters + { + Account = modifyOrderRequestParameters.Account, + Symbol = modifyOrderRequestParameters.Symbol + }); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + tradingOperationResult = TradingOperationResult.CreateError(modifyOrderRequestParameters.RequestId, allowedResult.Reason); + return tradingOperationResult; + } + if (modifyOrderRequestParameters.TimeInForce == TimeInForce.Default) + { + modifyOrderRequestParameters.TimeInForce = modifyOrderRequestParameters.OrderType.AllowedTifs.FirstOrDefault(); + } + ?((RequestParameters)modifyOrderRequestParameters); + Core.Instance.Loggers.Log(modifyOrderRequestParameters, LoggingLevel.Trading, Name); + tradingOperationResult = ??.ModifyOrder(modifyOrderRequestParameters); + } + catch (Exception ex) + { + tradingOperationResult = TradingOperationResult.CreateError(modifyOrderRequestParameters.RequestId, ex.Message); + } + finally + { + Core.Instance.Loggers.Log(tradingOperationResult, LoggingLevel.Trading, Name); + ?(modifyOrderRequestParameters, tradingOperationResult); + } + return tradingOperationResult; + } + + internal TradingOperationResult ?(ClosePositionRequestParameters P_0) + { + TradingOperationResult tradingOperationResult = null; + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + ClosePositionRequestParameters closePositionRequestParameters = new ClosePositionRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + try + { + if (!Connected) + { + long requestId = closePositionRequestParameters.RequestId; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(State); + tradingOperationResult = TradingOperationResult.CreateError(requestId, defaultInterpolatedStringHandler.ToStringAndClear()); + return tradingOperationResult; + } + AllowedResult allowedResult = TradingOperations.IsAllowed(TradingOperation.ClosePosition, new TradingOperationParameters + { + Position = closePositionRequestParameters.Position + }); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + tradingOperationResult = TradingOperationResult.CreateError(closePositionRequestParameters.RequestId, allowedResult.Reason); + return tradingOperationResult; + } + ?((RequestParameters)closePositionRequestParameters); + Core.Instance.Loggers.Log(closePositionRequestParameters, LoggingLevel.Trading, Name); + tradingOperationResult = ??.ClosePosition(closePositionRequestParameters); + } + catch (Exception ex) + { + tradingOperationResult = TradingOperationResult.CreateError(closePositionRequestParameters.RequestId, ex.Message); + } + finally + { + Core.Instance.Loggers.Log(tradingOperationResult, LoggingLevel.Trading, Name); + ?(closePositionRequestParameters, tradingOperationResult); + } + return tradingOperationResult; + } + + internal TradingOperationResult ?(CancelOrderRequestParameters P_0) + { + TradingOperationResult tradingOperationResult = null; + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + CancelOrderRequestParameters cancelOrderRequestParameters = new CancelOrderRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + try + { + if (!Connected) + { + long requestId = cancelOrderRequestParameters.RequestId; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(State); + tradingOperationResult = TradingOperationResult.CreateError(requestId, defaultInterpolatedStringHandler.ToStringAndClear()); + return tradingOperationResult; + } + AllowedResult allowedResult = TradingOperations.IsAllowed(TradingOperation.CancelOrder, new TradingOperationParameters + { + Order = cancelOrderRequestParameters.Order + }); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + tradingOperationResult = TradingOperationResult.CreateError(cancelOrderRequestParameters.RequestId, allowedResult.Reason); + return tradingOperationResult; + } + ?((RequestParameters)cancelOrderRequestParameters); + Core.Instance.Loggers.Log(cancelOrderRequestParameters, LoggingLevel.Trading, Name); + tradingOperationResult = ??.CancelOrder(cancelOrderRequestParameters); + return tradingOperationResult; + } + catch (Exception ex) + { + tradingOperationResult = TradingOperationResult.CreateError(P_0.RequestId, ex.Message); + return tradingOperationResult; + } + finally + { + Core.Instance.Loggers.Log(tradingOperationResult, LoggingLevel.Trading, Name); + ?(cancelOrderRequestParameters, tradingOperationResult); + } + } + + internal MarginInfo ?(OrderRequestParameters P_0) + { + MarginInfo result = null; + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return result; + } + try + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + P_0.CancellationToken = cancellationTokenSource.Token; + result = ??.GetMarginInfo(P_0); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + return result; + } + + internal Symbol ?(GetSymbolRequestParameters P_0, NonFixedListDownload P_1 = NonFixedListDownload.Download) + { + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return null; + } + return ?(P_0, P_1); + } + + internal Symbol ?(GetSymbolRequestParameters P_0, NonFixedListDownload P_1 = NonFixedListDownload.Download) + { + Symbol symbol = null; + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + return symbol; + } + if (??.SymbolsCache.?(P_0.SymbolId, out symbol)) + { + return symbol; + } + if (!??.AllowNonFixedList || P_1 == NonFixedListDownload.IgnoreDownload) + { + return symbol; + } + ? ? = ??.GetSymbolRequestCache.?(P_0); + if (? != null && ?.Finished) + { + return ?.Result; + } + try + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + GetSymbolRequestParameters getSymbolRequestParameters = new GetSymbolRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + MessageSymbol nonFixedSymbol = ??.GetNonFixedSymbol(getSymbolRequestParameters); + if (nonFixedSymbol == null) + { + return symbol; + } + ??.Push(nonFixedSymbol); + CancellationTokenSource cancellationTokenSource2 = new CancellationTokenSource(TimeSpan.FromSeconds(15.0)); + using CancellationTokenSource cancellationTokenSource3 = CancellationTokenSource.CreateLinkedTokenSource(getSymbolRequestParameters.CancellationToken, cancellationTokenSource2.Token); + while (!cancellationTokenSource3.IsCancellationRequested) + { + if (??.SymbolsCache.?(nonFixedSymbol.Id, out symbol)) + { + return symbol; + } + Thread.Sleep(100); + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.SymbolId, LoggingLevel.Verbose); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + finally + { + if (!P_0.CancellationToken.IsCancellationRequested) + { + ??.GetSymbolRequestCache.?(P_0, symbol); + } + } + return symbol; + } + + internal IList ?(SearchSymbolsRequestParameters P_0) + { + List list = new List(); + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return null; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + SearchSymbolsRequestParameters searchSymbolsRequestParameters = new SearchSymbolsRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + searchSymbolsRequestParameters.SymbolTypes = searchSymbolsRequestParameters.SymbolTypes.Intersect(BusinessObjects.SymbolTypes).ToList(); + if (string.IsNullOrEmpty(searchSymbolsRequestParameters.FilterName) || !??.AllowNonFixedList) + { + return ?(searchSymbolsRequestParameters); + } + ?> ? = ??.SearchSymbolsRequestCache.?(searchSymbolsRequestParameters); + if (? != null && ?.Finished) + { + return new List(?.Result); + } + try + { + IList list2 = ??.SearchSymbols(new SearchSymbolsRequestParameters(searchSymbolsRequestParameters)); + if (list2 == null || list2.Count == 0) + { + return list; + } + foreach (MessageSymbolInfo item in list2) + { + if (item != null) + { + list.Add(??.?(item)); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + finally + { + if (!searchSymbolsRequestParameters.CancellationToken.IsCancellationRequested) + { + ??.SearchSymbolsRequestCache.?(searchSymbolsRequestParameters, new List(list)); + } + } + return list; + } + + internal IList ?(GetFutureContractsRequestParameters P_0) + { + IList list = new List(); + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return null; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + GetFutureContractsRequestParameters getFutureContractsRequestParameters = new GetFutureContractsRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + if (!??.AllowNonFixedList) + { + return ?(getFutureContractsRequestParameters, false); + } + ?> ? = ??.GetFutureContractsRequestCache.?(getFutureContractsRequestParameters); + if (? != null && ?.Finished) + { + return new List(?.Result); + } + try + { + IList futureContracts = ??.GetFutureContracts(new GetFutureContractsRequestParameters(getFutureContractsRequestParameters)); + if (futureContracts == null || futureContracts.Count == 0) + { + return list; + } + foreach (MessageSymbolInfo item in futureContracts) + { + if (item != null) + { + list.Add(??.?(item)); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + finally + { + if (!getFutureContractsRequestParameters.CancellationToken.IsCancellationRequested) + { + ??.GetFutureContractsRequestCache.?(getFutureContractsRequestParameters, new List(list)); + } + } + return list; + } + + internal IList ?(GetOptionSeriesRequestParameters P_0) + { + List list = new List(); + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return list; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + GetOptionSeriesRequestParameters getOptionSeriesRequestParameters = new GetOptionSeriesRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + if (!??.AllowNonFixedList) + { + return ?(getOptionSeriesRequestParameters); + } + ?> ? = ??.GetOptionSeriesRequestCache.?(getOptionSeriesRequestParameters); + if (? != null && ?.Finished) + { + return new List(?.Result); + } + try + { + IList optionSeries = ??.GetOptionSeries(new GetOptionSeriesRequestParameters(getOptionSeriesRequestParameters)); + if (optionSeries == null) + { + return list; + } + foreach (MessageOptionSerie item in optionSeries) + { + if (item != null) + { + list.Add(??.?(item)); + } + } + list = list.OrderBy((OptionSerie optionSerie) => optionSerie.ExpirationDate).ToList(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + finally + { + if (!getOptionSeriesRequestParameters.CancellationToken.IsCancellationRequested) + { + ??.GetOptionSeriesRequestCache.?(getOptionSeriesRequestParameters, new List(list)); + } + } + return list; + } + + internal IList ?(GetStrikesRequestParameters P_0) + { + List list = new List(); + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return null; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + GetStrikesRequestParameters getStrikesRequestParameters = new GetStrikesRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + if (!??.AllowNonFixedList) + { + return ??.Symbols.Where((Symbol symbol) => symbol.OptionSerie != null && symbol.OptionSerie.Id == P_0.SerieId).ToList(); + } + ?> ? = ??.GetStrikesRequestCache.?(getStrikesRequestParameters); + if (? != null && ?.Finished) + { + return new List(?.Result); + } + try + { + IList strikes = ??.GetStrikes(new GetStrikesRequestParameters(getStrikesRequestParameters)); + if (strikes == null) + { + return list; + } + foreach (MessageSymbolInfo item in strikes) + { + if (item != null) + { + list.Add(??.?(item)); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + finally + { + if (!getStrikesRequestParameters.CancellationToken.IsCancellationRequested) + { + ??.GetStrikesRequestCache.?(getStrikesRequestParameters, new List(list)); + } + } + return list; + } + + private IList ?(SearchSymbolsRequestParameters P_0) + { + IEnumerable source = ??.Symbols; + IList ?? = P_0.ExchangeIds; + if (?? != null && ??.Any()) + { + source = source.Where((Symbol symbol) => ??.Contains(symbol.ExchangeId)); + } + IList ?? = P_0.SymbolTypes; + if (?? != null && ??.Any()) + { + source = source.Where((Symbol symbol) => ??.Contains(symbol.SymbolType)); + } + string filterName = P_0.FilterName; + if (string.IsNullOrEmpty(filterName)) + { + return source.ToList(); + } + string[] ?? = filterName.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + return source.Where((Symbol symbol) => ?(??, symbol, P_0.GetSynonyms)).ToList(); + } + + private IList ?(GetFutureContractsRequestParameters P_0, bool P_1 = false) + { + List list = new List(); + ICollection collection; + if (!P_1) + { + ICollection symbols = ??.Symbols; + collection = symbols; + } + else + { + collection = ??.SymbolsInfoCache.Values; + } + foreach (Symbol item in collection) + { + if (item.SymbolType != SymbolType.Futures && item.SymbolType != SymbolType.Forward) + { + continue; + } + if (!string.IsNullOrEmpty(P_0.UnderlierId)) + { + if (item.Underlier != null && item.Underlier.Id == P_0.UnderlierId) + { + list.Add(item); + } + } + else if (item.Root == P_0.Root) + { + list.Add(item); + } + } + return list; + } + + private IList ?(GetOptionSeriesRequestParameters P_0) + { + if (??.OptionSeriesCache.?(P_0.UnderlierId, out var result)) + { + return result; + } + return new List(); + } + + private static bool ?(string[] P_0, Symbol P_1, Func P_2) + { + bool result = true; + foreach (string text in P_0) + { + bool num = P_1.Name.Contains(text, StringComparison.InvariantCultureIgnoreCase); + bool flag = !string.IsNullOrEmpty(P_1.Description) && P_1.Description.Contains(text, StringComparison.InvariantCultureIgnoreCase); + bool flag2 = text.Length > 2 && P_1.Name.Contains(text.Insert(3, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), StringComparison.InvariantCultureIgnoreCase); + bool flag3 = text.Length > 3 && text[3] == '/' && P_1.Name.Contains(text.Remove(3, 1), StringComparison.InvariantCultureIgnoreCase); + bool flag4 = false; + bool flag5 = false; + bool flag6 = false; + if (P_2 != null) + { + string text2 = P_2(text); + if (!string.IsNullOrEmpty(text2)) + { + flag4 = P_1.Name.Contains(text2, StringComparison.InvariantCultureIgnoreCase); + flag5 = text2.Length > 2 && P_1.Name.Contains(text2.Insert(3, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), StringComparison.InvariantCultureIgnoreCase); + flag6 = text2.Length > 3 && text2[3] == '/' && P_1.Name.Contains(text2.Remove(3, 1), StringComparison.InvariantCultureIgnoreCase); + } + } + if (!num && !flag && !flag2 && !flag3 && !flag4 && !flag5 && !flag6) + { + result = false; + break; + } + } + return result; + } + + internal Order ?(string P_0) + { + if (State != ConnectionState.Connected) + { + return null; + } + if (?? == null) + { + return null; + } + if (??.OrdersCache.?(P_0, out var result)) + { + return result; + } + return null; + } + + internal PnL ?(PnLRequestParameters P_0) + { + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return null; + } + try + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + PnL pnL = ??.CalculatePnL(new PnLRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }); + if (pnL == null) + { + return pnL; + } + if (pnL.GrossPnL != null) + { + pnL.GrossPnL.ConnectionId = Id; + } + if (pnL.NetPnL != null) + { + pnL.NetPnL.ConnectionId = Id; + } + if (pnL.Fee != null) + { + pnL.Fee.ConnectionId = Id; + } + return pnL; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + return null; + } + + internal Position ?(string P_0) + { + if (State != ConnectionState.Connected) + { + return null; + } + if (?? == null) + { + return null; + } + if (??.PositionsCache.?(P_0, out var result)) + { + return result; + } + return null; + } + + private IList ?(HistoryRequestParameters P_0) + { + IList list = new List(); + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return list; + } + try + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(20, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.Aggregation); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.FromTime); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.ToTime); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.LoadingHistory, Name); + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + list = ??.LoadHistory(new HistoryRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }); + stopwatch.Stop(); + bool flag = list != null; + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 6); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.Aggregation); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.FromTime); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.ToTime); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(flag ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list?.Count ?? 0); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(stopwatch.Elapsed.TotalSeconds, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.LoadingHistory, Name); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + return list; + } + + [Obfuscation(Exclude = true)] + internal VolumeAnalysisInterval LoadVolumeAnalysis(VolumeAnalysisByPeriodRequestParameters requestParameters) + { + if (!Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return null; + } + try + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(requestParameters.CancellationToken, ??.Token); + VolumeAnalysisByPeriodRequestParameters volumeAnalysisByPeriodRequestParameters = new VolumeAnalysisByPeriodRequestParameters(requestParameters) + { + CancellationToken = cancellationTokenSource.Token + }; + VendorVolumeAnalysisByPeriodResponse vendorVolumeAnalysisByPeriodResponse = ??.LoadVolumeAnalysis(volumeAnalysisByPeriodRequestParameters); + if (vendorVolumeAnalysisByPeriodResponse == null) + { + return null; + } + return new VolumeAnalysisInterval + { + Interval = vendorVolumeAnalysisByPeriodResponse.ActualDataInterval, + Description = volumeAnalysisByPeriodRequestParameters.ToDescription(), + VolumeAnalysis = vendorVolumeAnalysisByPeriodResponse.Data + }; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + return null; + } + + public IEnumerable GetNews(GetNewsRequestParameters requestParameters) + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(requestParameters.CancellationToken, ??.Token); + IEnumerable news = ??.GetNews(new GetNewsRequestParameters(requestParameters) + { + CancellationToken = cancellationTokenSource.Token + }); + if (news == null) + { + return Array.Empty(); + } + if (!news.Any()) + { + return Array.Empty(); + } + List list = new List(); + foreach (MessageNewsHeadline item in news) + { + if (item != null) + { + if (requestParameters.CancellationToken.IsCancellationRequested) + { + break; + } + NewsArticle newsArticle = new NewsArticle(Id); + newsArticle.?(item); + list.Add(newsArticle); + } + } + return list.ToArray(); + } + + public string GetNewsArticleContent(GetNewsArticleContentRequestParameters requestParameters) + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(requestParameters.CancellationToken, ??.Token); + return ??.GetNewsArticleContent(new GetNewsArticleContentRequestParameters(requestParameters) + { + CancellationToken = cancellationTokenSource.Token + }); + } + + public void SubscribeNewsUpdates(SubscribeNewsRequestParameters subscribeNewsRequestParameters, Action updateAction) + { + if (updateAction == null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + int hashCode = updateAction.GetHashCode(); + if (!??.NewsSubscribersCache.TryGetValue(hashCode, out var value)) + { + value = new HashSet>(); + ??.NewsSubscribersCache[hashCode] = value; + } + int count = value.Count; + value.Add(updateAction); + if (value.Count > count) + { + using (CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(subscribeNewsRequestParameters.CancellationToken, ??.Token)) + { + subscribeNewsRequestParameters.SubscribeId = hashCode.ToString(); + subscribeNewsRequestParameters.CancellationToken = cancellationTokenSource.Token; + ??.SubscribeNewsUpdates(subscribeNewsRequestParameters); + } + } + } + + public void UnsubscribeNewsUpdates(SubscribeNewsRequestParameters subscribeNewsRequestParameters, Action updateAction) + { + if (updateAction == null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + int hashCode = updateAction.GetHashCode(); + if (!??.NewsSubscribersCache.TryGetValue(hashCode, out var value)) + { + return; + } + int count = value.Count; + value.Remove(updateAction); + if (value.Count > count) + { + using (CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(subscribeNewsRequestParameters.CancellationToken, ??.Token)) + { + subscribeNewsRequestParameters.SubscribeId = hashCode.ToString(); + subscribeNewsRequestParameters.CancellationToken = cancellationTokenSource.Token; + ??.UnsubscribeNewsUpdates(subscribeNewsRequestParameters); + } + } + } + + [Obsolete("Use Core.Instance.GetTrades() instead")] + public IList GetTrades(TradesHistoryRequestParameters parameters) + { + parameters.Progress?.Report(0f); + if (parameters.To > Core.Instance.TimeUtils.DateTimeUtcNow) + { + parameters.To = Core.Instance.TimeUtils.DateTimeUtcNow; + } + if (parameters.ForceReload && !TradesHistoryMetadata.AllowReloadFromServer) + { + parameters.ForceReload = false; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(parameters.CancellationToken, ??.Token); + CancellationToken token = cancellationTokenSource.Token; + List> list2; + IList list = ?(parameters, out list2); + foreach (Interval item in list2) + { + if (token.IsCancellationRequested) + { + break; + } + TradesHistoryRequestParameters tradesHistoryRequestParameters = new TradesHistoryRequestParameters + { + From = item.From, + To = item.To, + SymbolId = parameters.SymbolId, + ForceReload = parameters.ForceReload, + CancellationToken = token, + Progress = parameters.Progress + }; + IList list3 = null; + try + { + list3 = ??.GetTrades(tradesHistoryRequestParameters); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + if (token.IsCancellationRequested) + { + break; + } + if (list3 != null) + { + UserTradesInterval userTradesInterval = ?(tradesHistoryRequestParameters, list3); + list.Add(userTradesInterval); + if (string.IsNullOrEmpty(parameters.SymbolId) || !??.UsersTradesCacheMetadata.AllowSingleSymbolLoading) + { + ???.Save(userTradesInterval); + } + } + } + if (token.IsCancellationRequested) + { + return Array.Empty(); + } + MessageTrade[] array = (from P_0 in list.OrderBy((UserTradesInterval P_0) => P_0.Interval.From).SelectMany((UserTradesInterval P_0) => P_0.Trades) + where string.IsNullOrEmpty(parameters.SymbolId) || P_0.SymbolId == parameters.SymbolId + select P_0).ToArray(); + if (!array.Any()) + { + return Array.Empty(); + } + return ?(array, token); + } + + internal void ?(TradesHistoryRequestParameters P_0, AccountTradesLoadingCallback P_1) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + P_0.Progress?.Report(0f); + if (P_0.To > Core.Instance.TimeUtils.DateTimeUtcNow) + { + P_0.To = Core.Instance.TimeUtils.DateTimeUtcNow; + } + CancellationTokenSource ?? = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + CancellationToken ?? = ??.Token; + List> list; + IList source = ?(P_0, out list); + P_1.InvokeSafely(?(source.SelectMany((UserTradesInterval userTradesInterval) => userTradesInterval.Trades).ToList(), ??), !list.Any()); + foreach (Interval ?? in list) + { + if (??.IsCancellationRequested) + { + break; + } + TradesHistoryRequestParameters ?? = new TradesHistoryRequestParameters + { + From = ??.From, + To = ??.To, + SymbolId = P_0.SymbolId, + ForceReload = P_0.ForceReload, + CancellationToken = ??, + Progress = P_0.Progress + }; + List ?? = new List(); + ??.GetTrades(??, delegate(IList list2, bool flag) + { + try + { + if (!??.IsCancellationRequested) + { + if (list2 == null) + { + if (flag) + { + P_1.InvokeSafely(new List(), flag); + } + } + else + { + list2 = ?(??, list2).Trades.ToList(); + ??.AddRange(list2); + List list3 = ?(list2, ??).ToList(); + P_1.InvokeSafely(list3, flag); + if (flag && string.IsNullOrEmpty(P_0.SymbolId) && !??.UsersTradesCacheMetadata.AllowSingleSymbolLoading) + { + ???.Save(new UserTradesInterval + { + Interval = ??, + Trades = ?? + }); + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + if (flag) + { + ??.Dispose(); + } + } + }); + } + } + + private IList ?(TradesHistoryRequestParameters P_0, out List> P_1) + { + List list = new List(); + P_1 = new List>(); + if (!P_0.ForceReload && ?? != null) + { + IList collection = ??.Load(P_0.Interval, out P_1); + list.AddRange(collection); + } + else + { + P_1.Add(P_0.Interval); + } + if (!(?? == default(DateTime)) && !P_0.ForceReload) + { + UsersTradesStorage usersTradesStorage = ??; + if (usersTradesStorage != null && usersTradesStorage.IsRealtimeCollectingAllowed) + { + for (int i = 0; i < P_1.Count; i++) + { + Interval interval = P_1[i]; + if (!(interval.To <= ??)) + { + if (interval.From >= ??) + { + P_1.RemoveAt(i--); + } + else + { + P_1[i] = new Interval(interval.From, ??); + } + } + } + return list; + } + } + return list; + } + + private UserTradesInterval ?(TradesHistoryRequestParameters P_0, IList P_1) + { + List trades = P_1.Where((MessageTrade messageTrade) => P_0.Interval.Contains(messageTrade.DateTime)).ToList(); + return new UserTradesInterval + { + Trades = trades, + Interval = new Interval(P_0.From, P_0.To) + }; + } + + private Trade[] ?(IList P_0, CancellationToken P_1) + { + List list = new List(); + foreach (MessageTrade item in P_0) + { + if (item != null) + { + if (P_1.IsCancellationRequested) + { + break; + } + ?(new GetSymbolRequestParameters + { + SymbolId = item.SymbolId, + CancellationToken = P_1 + }); + Trade trade = new Trade(Id); + trade.?(item); + list.Add(trade); + } + } + return list.ToArray(); + } + + public IList GetOrdersHistory(OrdersHistoryRequestParameters parameters) + { + parameters.Progress?.Report(0f); + if (parameters.To > Core.Instance.TimeUtils.DateTimeUtcNow) + { + parameters.To = Core.Instance.TimeUtils.DateTimeUtcNow; + } + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(parameters.CancellationToken, ??.Token); + parameters.CancellationToken = cancellationTokenSource.Token; + IList list = null; + try + { + list = ??.GetOrdersHistory(parameters); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + if (parameters.CancellationToken.IsCancellationRequested) + { + return Array.Empty(); + } + if (list == null) + { + return Array.Empty(); + } + if (!list.Any()) + { + return Array.Empty(); + } + List list2 = new List(); + foreach (MessageOrderHistory item in list) + { + if (item != null) + { + if (parameters.CancellationToken.IsCancellationRequested) + { + break; + } + ?(new GetSymbolRequestParameters + { + SymbolId = item.SymbolId, + CancellationToken = parameters.CancellationToken + }); + OrderHistory orderHistory = new OrderHistory(Id); + orderHistory.?(item); + list2.Add(orderHistory); + } + } + return list2.ToArray(); + } + + internal Report ?(ReportRequestParameters P_0) + { + using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(P_0.CancellationToken, ??.Token); + ReportRequestParameters reportRequestParameters = new ReportRequestParameters(P_0) + { + CancellationToken = cancellationTokenSource.Token + }; + Report report = ??.GenerateReport(reportRequestParameters); + foreach (ReportRow row in report.Rows) + { + foreach (ReportCell cell in row.Cells) + { + if (cell.formattingDescription != null) + { + cell.formattingDescription.ConnectionId = Id; + } + } + } + return report; + } + + private void ?(object P_0, VendorEventArgs P_1) + { + ?(P_1.Message); + } + + private void ?(Message P_0) + { + if (P_0 != null) + { + ??.Push(P_0); + } + } + + private void ?(ConnectionState P_0) + { + try + { + ???.Invoke(this, new ConnectionStateChangedEventArgs(P_0, State, LastConnectionResult.Clone() as ConnectionResult)); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + private void ?(RequestParameters P_0) + { + RequestEventArgs e = new RequestEventArgs(P_0); + ???.InvokeSafely(this, e); + Core.Instance.?(this, e); + } + + private void ?(RequestParameters P_0, object P_1) + { + ???.InvokeSafely(this, new PerformedRequestEventArgs(P_0, P_1)); + Core.Instance.?(P_0, P_1); + } + + private void ?(string P_0) + { + try + { + int num = ??.Orders.Length; + int num2 = ??.Positions.Length; + if (num <= 0 && num2 <= 0) + { + return; + } + string value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler; + if (num > 0) + { + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(19, 2); + defaultInterpolatedStringHandler.AppendFormatted(num); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(string.Join(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (from order in ??.Orders + group order by order.Symbol into grouping + select grouping.Key).ToList())); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + value = defaultInterpolatedStringHandler.ToStringAndClear(); + } + string value2 = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + if (num2 > 0) + { + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 2); + defaultInterpolatedStringHandler.AppendFormatted(num2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(string.Join(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (from position in ??.Positions + group position by position.Symbol into grouping + select grouping.Key).ToList())); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + value2 = defaultInterpolatedStringHandler.ToStringAndClear(); + } + LoggerManager loggers = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 4); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Trading); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obfuscation(Exclude = true)] + private void SubscribeOnMessage(Action handler) + { + if (?? != null) + { + ??.?(handler); + } + } + + public int CompareTo(object obj) + { + if (obj is Connection connection) + { + return string.Compare(Name, connection.Name, StringComparison.Ordinal); + } + return 0; + } + + public override string ToString() + { + return Name; + } + } + public delegate void AccountTradesLoadingCallback(IList trades, bool isFinished); +} +namespace ? +{ + internal class ? : BufferedProcessor, ?, IBusinessObjectsProvider + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(AdditionalInfoItem P_0) + { + return P_0.FormattingDescription != null; + } + + internal IFormattingDescription ?(AdditionalInfoItem P_0) + { + return P_0.FormattingDescription; + } + + internal bool ?(AdditionalInfoItem P_0) + { + return P_0.FormattingDescription != null; + } + + internal IFormattingDescription ?(AdditionalInfoItem P_0) + { + return P_0.FormattingDescription; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ? ??; + + public Message ??; + + public INeedSymbolToPocess ??; + + internal void ?() + { + Symbol symbol = Core.Instance.Connections[??.??].?(new GetSymbolRequestParameters + { + SymbolId = ??.SymbolId + }); + if (symbol == null || symbol.Id != ??.SymbolId) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(50, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.GetType()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Error); + } + else + { + ??.Push(??); + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public MessageOptionSerie ??; + + internal bool ?(OptionSerie P_0) + { + return P_0.Id == ??.Id; + } + } + + private readonly string ??; + + [CompilerGenerated] + private HistoryMetadata ??; + + [CompilerGenerated] + private VolumeAnalysisMetadata ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private TradesHistoryMetadata ??; + + [CompilerGenerated] + private LimitationMetadata ??; + + internal readonly Dictionary ??; + + [CompilerGenerated] + private readonly Dictionary ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ?> ??; + + [CompilerGenerated] + private readonly Dictionary ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ConcurrentDictionary>> ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private SymbolType[] ??; + + internal bool ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ?> ??; + + [CompilerGenerated] + private readonly ?> ??; + + [CompilerGenerated] + private readonly ?> ??; + + [CompilerGenerated] + private readonly ?> ??; + + internal HistoryMetadata HistoryMetadata + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = historyMetadata; + } + } + + internal VolumeAnalysisMetadata VolumeAnalysisMetadata + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = volumeAnalysisMetadata; + } + } + + internal IEnumerable NewsFeedSettings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = enumerable; + } + } + + internal TradesHistoryMetadata UsersTradesCacheMetadata + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = tradesHistoryMetadata; + } + } + + internal LimitationMetadata LimitationMetadata + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = limitationMetadata; + } + } + + internal Dictionary SymbolGroupsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? AccountsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? SymbolsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? SymbolsInfoCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? OrdersCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? PositionsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? ClosedPositionsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? CorporateActionCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? ReportTypeCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? OrderTypesCache + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = ?2; + } + } + + internal ? ExchangesCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? RulesCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ?> OptionSeriesCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal Dictionary TradingSessions + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? DeliveredAssetsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? AccountOperationsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ConcurrentDictionary>> NewsSubscribersCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? TradingSignalsCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol[] Symbols => SymbolsCache.?(); + + public SymbolType[] SymbolTypes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + public Account[] Accounts => AccountsCache.?(); + + public Asset[] Assets => ??.Values.ToArray(); + + public Exchange[] Exchanges => ExchangesCache.Values.ToArray(); + + public Order[] Orders => OrdersCache.?(); + + public OrderType[] OrderTypes => OrderTypesCache.?(); + + public Position[] Positions => PositionsCache.?(); + + public ClosedPosition[] ClosedPositions => ClosedPositionsCache.?(); + + public CorporateAction[] CorporateActions => CorporateActionCache.?(); + + public ReportType[] ReportTypes => ReportTypeCache.?(); + + public DeliveredAsset[] DeliveredAssets => DeliveredAssetsCache.?(); + + public AccountOperation[] AccountOperations => AccountOperationsCache.?(); + + public TradingSignal[] TradingSignals => TradingSignalsCache.?(); + + int ?.PriorityIndex => 0; + + ? ?.Rules => RulesCache; + + internal ? GetSymbolRequestCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ?> SearchSymbolsRequestCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ?> GetFutureContractsRequestCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ?> GetOptionSeriesRequestCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ?> GetStrikesRequestCache + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ?(string P_0) + { + ?? = P_0; + ?? = new ?(); + ?? = new ?(); + ?? = new ?(); + ?? = new Dictionary(); + ?? = new ?(); + ?? = new ?(); + ?? = new ?(); + ?? = new ?(); + ?? = new ?(); + OrderTypesCache = new ?(); + ?? = new ?(); + ?? = new ?>(); + ?? = new Dictionary(); + SymbolTypes = new SymbolType[0]; + ?? = new ?(); + ?? = new Dictionary(); + ?? = new ?(); + ?? = new ?(); + ?? = new ConcurrentDictionary>>(); + ?? = new ?(); + ?? = new ?(); + ?? = new ?>(); + ?? = new ?>(); + ?? = new ?>(); + ?? = new ?>(); + } + + internal void ?() + { + Core.Instance.RulesManager.Defaults.ForEach(delegate(Rule P_0) + { + RulesCache.?(P_0.Name, P_0); + }); + Start(); + } + + protected internal override void Clear() + { + List list = new List(); + list.AddRange(AccountsCache); + AccountsCache.?(); + list.AddRange(SymbolsCache); + SymbolsCache.?(); + SymbolsInfoCache.?(); + SymbolTypes = new SymbolType[0]; + OrdersCache.?(); + PositionsCache.?(); + ClosedPositionsCache.?(); + CorporateActionCache.?(); + ReportTypeCache.?(); + ??.Clear(); + OrderTypesCache.?(); + ExchangesCache.?(); + RulesCache.?(); + AccountOperationsCache.?(); + TradingSignalsCache.?(); + GetSymbolRequestCache.Dispose(); + SearchSymbolsRequestCache.Dispose(); + GetFutureContractsRequestCache.Dispose(); + GetOptionSeriesRequestCache.Dispose(); + GetStrikesRequestCache.Dispose(); + foreach (BusinessObject item in list) + { + item.State = BusinessObjectState.Fake; + } + base.Clear(); + } + + [Obfuscation(Exclude = true)] + protected override void Process(Message message) + { + if (message == null) + { + return; + } + try + { + INeedSymbolToPocess ?? = message as INeedSymbolToPocess; + if (?? != null && !string.IsNullOrEmpty(??.SymbolId) && !SymbolsCache.?(??.SymbolId)) + { + Task.Factory.StartNew(delegate + { + Symbol symbol = Core.Instance.Connections[??].?(new GetSymbolRequestParameters + { + SymbolId = ??.SymbolId + }); + if (symbol == null || symbol.Id != ??.SymbolId) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(50, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(message.GetType()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Error); + } + else + { + Push(message); + } + }); + return; + } + switch (message.Type) + { + case MessageType.Account: + case MessageType.CryptoAccount: + ?(message as MessageAccount); + break; + case MessageType.Symbol: + ?(message as MessageSymbol); + break; + case MessageType.SymbolInfo: + ?(message as MessageSymbolInfo); + break; + case MessageType.Quote: + case MessageType.Level2: + case MessageType.Last: + case MessageType.DayBar: + case MessageType.DOM: + case MessageType.Mark: + ?(message as MessageQuote); + break; + case MessageType.Asset: + ?(message as MessageAsset); + break; + case MessageType.CryptoAssetBalances: + ?(message as MessageCryptoAssetBalances); + break; + case MessageType.OpenOrder: + ?(message as MessageOpenOrder); + break; + case MessageType.CloseOrder: + ?(message as MessageCloseOrder); + break; + case MessageType.OpenPosition: + ?(message as MessageOpenPosition); + break; + case MessageType.ClosedPosition: + ?(message as MessageClosedPosition); + break; + case MessageType.ClosePosition: + ?(message as MessageClosePosition); + break; + case MessageType.Trade: + ?(message as MessageTrade); + break; + case MessageType.CorporateAction: + ?(message as MessageCorporateAction); + break; + case MessageType.ReportMetadata: + ?(message as MessageReportType); + break; + case MessageType.Exchange: + ?(message as MessageExchange); + break; + case MessageType.SymbolTypes: + ?(message as MessageSymbolTypes); + break; + case MessageType.OrderHistory: + ?(message as MessageOrderHistory); + break; + case MessageType.Rule: + ?(message as MessageRule); + break; + case MessageType.DealTicket: + ?(message as MessageDealTicket); + break; + case MessageType.SymbolGroup: + ?(message as MessageSymbolGroup); + break; + case MessageType.OptionSerie: + ?(message as MessageOptionSerie); + break; + case MessageType.Session: + ?(message as MessageSessionsContainer); + break; + case MessageType.OpenDeliveredAsset: + ?(message as MessageOpenDeliveredAsset); + break; + case MessageType.CloseDeliveredAsset: + ?(message as MessageCloseDeliveredAsset); + break; + case MessageType.AccountOperation: + ?(message as MessageAccountOperation); + break; + case MessageType.NewsHeadline: + ?(message as MessageNewsHeadline); + break; + case MessageType.TradingSignal: + ?(message as MessageTradingSignal); + break; + case MessageType.RemoveTradingSignal: + ?(message as MessageRemoveTradingSignal); + break; + case MessageType.Custom: + ?(message as CustomMessage); + break; + } + } + finally + { + ???.Invoke(message); + } + } + + private void ?(MessageSymbolGroup P_0) + { + if (P_0 != null) + { + if (!SymbolGroupsCache.TryGetValue(P_0.Id, out var value)) + { + value = new SymbolGroup(??); + value.?(P_0); + SymbolGroupsCache.Add(value.Id, value); + } + else + { + value.?(P_0); + } + } + } + + private void ?(MessageSymbolTypes P_0) + { + if (P_0 != null) + { + SymbolTypes = P_0.SymbolTypes?.ToArray() ?? new SymbolType[0]; + } + } + + private void ?(MessageExchange P_0) + { + if (P_0 != null) + { + if (!ExchangesCache.?(P_0.Id, out var exchange)) + { + exchange = new Exchange(??); + exchange.?(P_0); + ExchangesCache[exchange.Id] = exchange; + } + else + { + exchange.?(P_0); + } + } + } + + private void ?(MessageAsset P_0) + { + if (P_0 != null) + { + if (!??.TryGetValue(P_0.Id, out var value)) + { + value = new Asset(??); + value.?(P_0); + ??[value.Id] = value; + } + else + { + value.?(P_0); + } + } + } + + private void ?(MessageAccount P_0) + { + if (P_0 == null) + { + return; + } + IEnumerable enumerable = (from additionalInfoItem in P_0.AccountAdditionalInfo?.Where((AdditionalInfoItem additionalInfoItem) => additionalInfoItem.FormattingDescription != null) + select additionalInfoItem.FormattingDescription); + if (enumerable != null) + { + foreach (IFormattingDescription item in enumerable) + { + item.ConnectionId = ??; + } + } + if (!AccountsCache.?(P_0.AccountId, out var account)) + { + account = ((!(P_0 is MessageCryptoAccount)) ? new Account(??) : new CryptoAccount(??)); + account.?(P_0); + AccountsCache.?(account.Id, account); + Core.Instance.?(account); + } + else + { + account.?(P_0); + } + } + + private void ?(MessageSymbol P_0) + { + if (P_0 == null) + { + return; + } + IEnumerable enumerable = (from additionalInfoItem in P_0.SymbolAdditionalInfo?.Where((AdditionalInfoItem additionalInfoItem) => additionalInfoItem.FormattingDescription != null) + select additionalInfoItem.FormattingDescription); + if (enumerable != null) + { + foreach (IFormattingDescription item in enumerable) + { + item.ConnectionId = ??; + } + } + Symbol symbol = SymbolsCache[P_0.Id]; + if (symbol == null) + { + lock (SymbolsInfoCache) + { + if (SymbolsInfoCache.?(P_0.Id, out symbol)) + { + SymbolsInfoCache.?(P_0.Id); + } + else + { + symbol = new Symbol(??); + } + } + symbol.?(P_0); + SymbolsCache.?(symbol.Id, symbol); + Core.Instance.?(symbol); + } + else + { + symbol.?(P_0); + } + } + + internal Symbol ?(MessageSymbolInfo P_0) + { + if (P_0 == null) + { + return null; + } + if (SymbolsCache.?(P_0.Id, out var symbol)) + { + return symbol; + } + lock (SymbolsInfoCache) + { + symbol = SymbolsInfoCache[P_0.Id]; + } + if (symbol == null) + { + symbol = new Symbol(??); + symbol.?(P_0); + try + { + lock (SymbolsInfoCache) + { + SymbolsInfoCache.?(symbol.Id, symbol); + } + } + catch (ArgumentException ex) + { + Core.Instance.Loggers.Log(ex); + } + } + else + { + symbol.?(P_0); + } + return symbol; + } + + private void ?(MessageQuote P_0) + { + if (P_0 != null) + { + SymbolsCache[P_0.SymbolId]?.?(P_0); + SymbolsInfoCache[P_0.SymbolId]?.?(P_0); + } + } + + private void ?(MessageOpenOrder P_0) + { + if (P_0 == null) + { + return; + } + if (string.IsNullOrEmpty(P_0.AccountId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.PositionId, LoggingLevel.Error); + return; + } + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.PositionId, LoggingLevel.Error); + return; + } + if (!OrdersCache.?(P_0.OrderId, out var order)) + { + order = new Order(??); + order.?(P_0); + OrdersCache.?(order.Id, order); + } + else + { + order.?(P_0); + } + Core.Instance.?(order); + } + + private void ?(MessageCloseOrder P_0) + { + if (P_0 != null && OrdersCache.?(P_0.OrderId, out var order)) + { + OrdersCache.?(order.Id); + order.State = BusinessObjectState.Fake; + Core.Instance.?(order); + } + } + + private void ?(MessageOpenPosition P_0) + { + if (P_0 == null) + { + return; + } + if (string.IsNullOrEmpty(P_0.AccountId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.PositionId, LoggingLevel.Error); + return; + } + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.PositionId, LoggingLevel.Error); + return; + } + if (!PositionsCache.?(P_0.PositionId, out var position)) + { + position = new Position(??); + position.?(P_0); + PositionsCache.?(position.Id, position); + } + else + { + position.?(P_0); + } + Core.Instance.?(position); + } + + private void ?(MessageClosedPosition P_0) + { + if (P_0 == null) + { + return; + } + if (string.IsNullOrEmpty(P_0.AccountId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.PositionId, LoggingLevel.Error); + return; + } + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.PositionId, LoggingLevel.Error); + return; + } + if (!ClosedPositionsCache.?(P_0.PositionId, out var closedPosition)) + { + closedPosition = new ClosedPosition(??); + closedPosition.?(P_0); + ClosedPositionsCache.?(closedPosition.Id, closedPosition); + } + else + { + closedPosition.?(P_0); + } + Core.Instance.?(closedPosition); + } + + private void ?(MessageClosePosition P_0) + { + if (P_0 != null) + { + ClosedPosition closedPosition; + if (PositionsCache.?(P_0.PositionId, out var position)) + { + PositionsCache.?(position.Id); + position.State = BusinessObjectState.Fake; + Core.Instance.?(position); + } + else if (ClosedPositionsCache.?(P_0.PositionId, out closedPosition)) + { + ClosedPositionsCache.?(closedPosition.Id); + closedPosition.State = BusinessObjectState.Fake; + Core.Instance.?(closedPosition); + } + } + } + + private void ?(MessageTrade P_0) + { + if (P_0 != null) + { + Trade trade = new Trade(??); + trade.?(P_0); + Core.Instance.?(trade); + } + } + + private void ?(MessageCorporateAction P_0) + { + if (P_0 != null) + { + if (!CorporateActionCache.?(P_0.CorporateActionId, out var corporateAction)) + { + corporateAction = new CorporateAction(??); + corporateAction.?(P_0); + CorporateActionCache.?(corporateAction.Id, corporateAction); + Core.Instance.?(corporateAction); + } + else + { + corporateAction.?(P_0); + } + } + } + + private void ?(MessageReportType P_0) + { + if (P_0 != null) + { + ReportType reportType = new ReportType(??); + reportType.?(P_0); + ReportTypeCache.?(P_0.Id, reportType); + } + } + + private void ?(MessageOrderHistory P_0) + { + if (P_0 != null) + { + OrderHistory orderHistory = new OrderHistory(??); + orderHistory.?(P_0); + Core.Instance.?(orderHistory); + } + } + + private void ?(MessageRule P_0) + { + if (P_0 == null) + { + return; + } + ? ?2 = null; + if (P_0.OrderTypeId != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + if (OrderTypesCache.?(P_0.OrderTypeId, out var orderType)) + { + ?2 = orderType; + } + } + else if (P_0.SymbolId != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + if (SymbolsCache.?(P_0.SymbolId, out var symbol)) + { + ?2 = symbol; + } + else if (SymbolsInfoCache.?(P_0.SymbolId, out symbol)) + { + ?2 = symbol; + } + } + else if (P_0.AccountId != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + if (AccountsCache.?(P_0.AccountId, out var account)) + { + ?2 = account; + } + } + else + { + ?2 = this; + } + if (?2 != null) + { + if (?2.Rules.?(P_0.Name, out var rule)) + { + rule.?(P_0); + } + else if (P_0 is LicenceMessageRule || !RulesManager.?.Contains(P_0.Name)) + { + rule = Rule.?(P_0); + ?2.Rules.?(rule.Name, rule); + } + } + } + + private void ?(MessageDealTicket P_0) + { + if (P_0 != null) + { + DealticketConnection dealticketConnection = new DealticketConnection(??, P_0); + Core.Instance.Loggers.Log(dealticketConnection, LoggingLevel.Trading, Core.Instance.Connections[((IConnectionBindedObject)dealticketConnection)?.ConnectionId]?.Name); + Core.Instance.?(dealticketConnection); + } + } + + private void ?(MessageCryptoAssetBalances P_0) + { + if (P_0 == null) + { + return; + } + Account account; + if (string.IsNullOrEmpty(P_0.AccountId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + } + else if (string.IsNullOrEmpty(P_0.AssetId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + } + else if (AccountsCache.?(P_0.AccountId, out account)) + { + if (account is CryptoAccount cryptoAccount) + { + cryptoAccount.?(P_0); + return; + } + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(32, 3); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.AccountId); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Error); + } + else + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.AccountId, LoggingLevel.Error); + } + } + + internal OptionSerie ?(MessageOptionSerie P_0) + { + if (P_0 == null) + { + return null; + } + if (!OptionSeriesCache.?(P_0.UnderlierId, out var list)) + { + OptionSeriesCache.?(P_0.UnderlierId, list = new List()); + } + OptionSerie optionSerie = list.FirstOrDefault((OptionSerie optionSerie2) => optionSerie2.Id == P_0.Id); + if (optionSerie == null) + { + optionSerie = new OptionSerie(??); + list.Add(optionSerie); + } + optionSerie.?(P_0); + return optionSerie; + } + + private void ?(MessageSessionsContainer P_0) + { + if (P_0 != null) + { + if (!TradingSessions.TryGetValue(P_0.Id, out var value)) + { + value = new SessionsContainer(??); + value.UpdateByMessage(P_0); + TradingSessions.Add(value.Id, value); + } + else + { + value.UpdateByMessage(P_0); + } + } + } + + private void ?(MessageOpenDeliveredAsset P_0) + { + if (P_0 == null) + { + return; + } + if (string.IsNullOrEmpty(P_0.AccountId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.Id, LoggingLevel.Error); + return; + } + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.Id, LoggingLevel.Error); + return; + } + if (!DeliveredAssetsCache.?(P_0.Id, out var deliveredAsset)) + { + deliveredAsset = new DeliveredAsset(??); + deliveredAsset.?(P_0); + DeliveredAssetsCache.?(deliveredAsset.Id, deliveredAsset); + } + else + { + deliveredAsset.?(P_0); + } + Core.Instance.?(deliveredAsset); + } + + private void ?(MessageCloseDeliveredAsset P_0) + { + if (P_0 != null && DeliveredAssetsCache.?(P_0.Id, out var deliveredAsset)) + { + DeliveredAssetsCache.?(deliveredAsset.Id); + Core.Instance.?(deliveredAsset); + } + } + + private void ?(MessageAccountOperation P_0) + { + if (P_0 != null) + { + if (!AccountOperationsCache.?(P_0.Name, out var accountOperation)) + { + AccountOperationsCache.?(P_0.Name, accountOperation = new AccountOperation(??)); + } + accountOperation.?(P_0); + } + } + + private void ?(MessageNewsHeadline P_0) + { + if (P_0 == null || string.IsNullOrEmpty(P_0.SubscribeId) || !int.TryParse(P_0.SubscribeId, out var result) || !NewsSubscribersCache.TryGetValue(result, out var value)) + { + return; + } + foreach (Action item in value) + { + NewsArticle newsArticle = new NewsArticle(??); + newsArticle.?(P_0); + item(newsArticle); + } + } + + private void ?(MessageTradingSignal P_0) + { + if (P_0 != null) + { + if (!TradingSignalsCache.?(P_0.Id, out var tradingSignal)) + { + tradingSignal = new TradingSignal(??); + tradingSignal.?(P_0); + TradingSignalsCache.?(tradingSignal.Id, tradingSignal); + Core.Instance.?(tradingSignal, EntityLifecycle.Created); + } + else + { + tradingSignal.?(P_0); + Core.Instance.?(tradingSignal, EntityLifecycle.Changed); + } + } + } + + private void ?(MessageRemoveTradingSignal P_0) + { + if (P_0 != null && TradingSignalsCache.?(P_0.TradingSignalId, out var tradingSignal)) + { + Core.Instance.?(tradingSignal, EntityLifecycle.Removed); + } + } + + private void ?(CustomMessage P_0) + { + if (P_0 != null) + { + P_0.ConnectionId = ??; + Core.Instance.CustomMessageProcessor.?(P_0); + } + } + + [SpecialName] + [CompilerGenerated] + internal void ?(Action P_0) + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value = (Action)Delegate.Combine(action2, P_0); + action = Interlocked.CompareExchange(ref ??, value, action2); + } + while ((object)action != action2); + } + + [SpecialName] + [CompilerGenerated] + internal void ?(Action P_0) + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value = (Action)Delegate.Remove(action2, P_0); + action = Interlocked.CompareExchange(ref ??, value, action2); + } + while ((object)action != action2); + } + + [CompilerGenerated] + private void ?(Rule P_0) + { + RulesCache.?(P_0.Name, P_0); + } + } + internal sealed class ? : ? + { + internal ?(string P_0) + : base(P_0) + { + } + + public override void Push(Message subject) + { + Process(subject); + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public class ConnectionConnectingProgressChangedEventArgs + { + [CompilerGenerated] + private string ?; + + public string Progress + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = text; + } + } + + internal ConnectionConnectingProgressChangedEventArgs(string P_0) + { + Progress = P_0; + } + } + public class ConnectionDependency + { + [CompilerGenerated] + private ConnectionDependencyBehavior ?; + + private string[] ?; + + public static ConnectionDependency NoDependency => new ConnectionDependency + { + Behavior = ConnectionDependencyBehavior.NoDependency + }; + + public static ConnectionDependency TotalDependency => new ConnectionDependency + { + Behavior = ConnectionDependencyBehavior.TotalDependency + }; + + public ConnectionDependencyBehavior Behavior + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public string[] DependentConnectionsIds + { + get + { + return ?; + } + set + { + ? = value ?? new string[0]; + } + } + } + /// + /// Server connection status + /// + public enum ConnectionState + { + Connected, + Connecting, + Disconnected, + Disconnecting, + ConnectionLost, + Fail + } + /// + /// Specifies connection using type. + /// + public enum ConnectionType + { + General, + TradingSimulator, + HistoryPlayer, + Backtester, + Technical + } + /// + /// Specifies how connection was created: by default or by user + /// + public enum ConnectionCreationType + { + Default, + Custom, + Technical + } + public enum ConnectionDependencyBehavior + { + NoDependency, + PartialDependency, + TotalDependency + } + public enum ConnectionStateObserverPriority + { + Low = 10, + Normal = 20, + High = 30 + } + /// + /// Represents all needed parameters for the connection constructing process. + /// + [Published] + public sealed class ConnectionInfo : ICustomizable, IRenamable, IComparable, IComparable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SettingItem ?(SettingItem P_0) + { + return P_0.GetCopy(); + } + } + + internal const string ?? = "ConnectionId"; + + private const string ?? = "Name"; + + internal const string ?? = "Group"; + + private const string ?? = "VendorName"; + + private const string ?? = "IsFavourite"; + + private const string ?? = "ConnectionState"; + + private const string ?? = "CreationType"; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private ConnectionState ??; + + [CompilerGenerated] + private IList ??; + + [CompilerGenerated] + private IList ??; + + [CompilerGenerated] + private ConnectionCreationType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private string ??; + + private VendorInfo ??; + + [CompilerGenerated] + private bool ??; + + /// + /// Gets a user friendly name of the connection + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + /// + /// Gets connection group + /// + public string Group + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets vendor's name + /// + public string VendorName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Gets connection Id + /// + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + /// + /// Favorites one will be displayed in Control center toolbar + /// + public bool IsFavourite + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets ConnectionState + /// + public ConnectionState ConnectionState + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = connectionState; + } + } + + /// + /// Gets vendor's settings + /// + public IList VendorSettings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = list; + } + } + + internal IList ConnectionSettings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = list; + } + } + + /// + /// Specifies how connection was created: by default or by user + /// + public ConnectionCreationType CreationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = connectionCreationType; + } + } + + public string ConnectionLogoPath + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public bool AllowCreateCustomConnections + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = flag; + } + } + + public List Links + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = list; + } + } + + public string Copyrights + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public VendorInfo VendorInfo + { + get + { + return ??; + } + internal set + { + if (vendorInfo == null) + { + return; + } + ?? = vendorInfo; + List list = new List(??.ConnectionParameters); + if (ConnectionSettings != null) + { + list.MergeWith(ConnectionSettings.Select((SettingItem P_0) => P_0.GetCopy()).ToList()); + } + VendorSettings = list; + } + } + + /// + /// realization + /// + public IList Settings + { + get + { + int value = (int)((ConnectionState != ConnectionState.Connecting) ? ((ConnectionState == ConnectionState.Disconnecting) ? ConnectionState.Disconnected : ((ConnectionState != ConnectionState.ConnectionLost) ? ConnectionState : ConnectionState.Connected)) : ConnectionState.Connected); + List list = new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ConnectionId) + { + VisibilityMode = VisibilityMode.Hidden + }, + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Group) + { + VisibilityMode = VisibilityMode.Hidden + }, + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), VendorName) + { + VisibilityMode = VisibilityMode.Hidden + }, + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsFavourite) + { + VisibilityMode = VisibilityMode.Hidden + }, + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value) + { + VisibilityMode = VisibilityMode.Hidden + }, + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)CreationType) + { + VisibilityMode = VisibilityMode.Hidden + } + }; + if (VendorSettings != null) + { + for (int i = 0; i < VendorSettings.Count; i++) + { + list.Add(VendorSettings[i].GetCopy()); + } + } + return list; + } + set + { + if (value == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + foreach (SettingItem item in value) + { + try + { + string name = item.Name; + if (name != null) + { + switch (name.Length) + { + case 12: + switch (name[1]) + { + case 'o': + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + ConnectionId = item.Value as string; + goto end_IL_0021; + case 'r': + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + CreationType = (ConnectionCreationType)(int)item.Value; + goto end_IL_0021; + } + break; + case 4: + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + Name = item.Value as string; + goto end_IL_0021; + case 10: + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + VendorName = item.Value as string; + ?(); + goto end_IL_0021; + case 5: + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + Group = item.Value as string; + goto end_IL_0021; + case 11: + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + IsFavourite = (bool)item.Value; + goto end_IL_0021; + case 15: + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + ConnectionState connectionState = (ConnectionState)(int)item.Value; + if (connectionState == ConnectionState.Disconnecting) + { + connectionState = ConnectionState.Disconnected; + } + ConnectionState = connectionState; + goto end_IL_0021; + } + } + } + VendorSettings?.UpdateItemValue(item.Name, item.Value); + end_IL_0021:; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + if (string.IsNullOrEmpty(ConnectionLogoPath) && CreationType == ConnectionCreationType.Custom) + { + ?(); + } + } + } + + public bool SyncMsgProcessing + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + string IRenamable.Name + { + get + { + return Name; + } + set + { + Core.Instance.Connections.RenameConnectionInfo(this, newName); + } + } + + /// + /// Creates connection info instance + /// + /// + internal ConnectionInfo(string P_0) + { + Name = P_0; + ConnectionState = ConnectionState.Disconnected; + ConnectionId = string.Empty; + } + + internal ConnectionInfo(string P_0, string P_1) + : this(P_0, P_1, P_1, ConnectionCreationType.Custom) + { + } + + /// + /// Creates connection info instance. + /// + /// + /// + /// + /// + internal ConnectionInfo(string P_0, string P_1, string P_2, ConnectionCreationType P_3 = ConnectionCreationType.Default) + : this(P_0) + { + Group = P_1 ?? P_2; + VendorName = P_2; + CreationType = P_3; + ConnectionId = ?(); + if (CreationType == ConnectionCreationType.Custom) + { + ?(); + ?(); + } + else if (CreationType == ConnectionCreationType.Technical) + { + ?(); + } + } + + private string ?() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4); + defaultInterpolatedStringHandler.AppendFormatted(VendorName); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Group); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(CreationType); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((CreationType == ConnectionCreationType.Default) ? Name : Guid.NewGuid().ToShortString()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private void ?() + { + ConnectionInfo connectionInfo = Core.Instance.Connections.ConnectionsInfo.FirstOrDefault((ConnectionInfo P_0) => P_0.CreationType == ConnectionCreationType.Default && P_0.Group == Group); + if (connectionInfo != null) + { + ConnectionLogoPath = connectionInfo.ConnectionLogoPath; + } + } + + private void ?() + { + if (VendorInfo == null) + { + VendorInfo vendorInfo = Core.Instance.Vendors.Vendors.FirstOrDefault((VendorInfo P_0) => P_0.MetaData.VendorName == VendorName); + ConnectionInfo connectionInfo = vendorInfo?.DefaultConnections.FirstOrDefault((ConnectionInfo P_0) => P_0.Group == Group); + if (connectionInfo != null) + { + ConnectionSettings = connectionInfo.ConnectionSettings; + } + VendorInfo = vendorInfo; + } + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(26, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(VendorName); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(IsFavourite); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override bool Equals(object obj) + { + if (obj is ConnectionInfo connectionInfo) + { + return ConnectionId == connectionInfo.ConnectionId; + } + return false; + } + + public override int GetHashCode() + { + return -463474436 + EqualityComparer.Default.GetHashCode(ConnectionId); + } + + private bool ?(string P_0, ref string P_1) + { + return true; + } + + bool IRenamable.IsNameAllowed(string P_0, ref string P_1) + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(P_0, ref P_1); + } + + public int CompareTo(object obj) + { + return CompareTo(obj as ConnectionInfo); + } + + public int CompareTo(ConnectionInfo other) + { + if (this == other) + { + return 0; + } + if (other == null) + { + return 1; + } + return string.Compare(ConnectionId, other.ConnectionId, StringComparison.Ordinal); + } + + [CompilerGenerated] + private bool ?(ConnectionInfo P_0) + { + if (P_0.CreationType == ConnectionCreationType.Default) + { + return P_0.Group == Group; + } + return false; + } + + [CompilerGenerated] + private bool ?(VendorInfo P_0) + { + return P_0.MetaData.VendorName == VendorName; + } + + [CompilerGenerated] + private bool ?(ConnectionInfo P_0) + { + return P_0.Group == Group; + } + } + public sealed class ConnectionInfoLink + { + [CompilerGenerated] + private string ?; + + [CompilerGenerated] + private string ?; + + public string Text + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public string URL + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + } + public sealed class ConnectionsManager : ICustomizable, IDisposable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func> ??; + + public static Func ??; + + internal bool ?(Connection P_0) + { + return P_0.Connected; + } + + internal IEnumerable ?(VendorInfo P_0) + { + return P_0.DefaultConnections; + } + + internal bool ?(ConnectionInfo P_0) + { + return P_0.AllowCreateCustomConnections; + } + } + + [CompilerGenerated] + private sealed class ? + { + public string ??; + + public string ??; + + internal bool ?(ConnectionInfo P_0) + { + if (P_0.CreationType == ConnectionCreationType.Default && P_0.VendorName == ??) + { + return P_0.Group == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ConnectionInfo ??; + + internal bool ?(ConnectionInfo P_0) + { + if (P_0.CreationType == ConnectionCreationType.Default && P_0.VendorName == ??.VendorName) + { + return P_0.Group == ??.Group; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ? ??; + + public ConnectionsManager ??; + + internal void ?() + { + ??.?(??.Connection); + } + + internal Task ?(Task t) + { + return ??.CurrentTask = null; + } + } + + private const int ?? = 10000; + + private readonly ? ??; + + private readonly object ??; + + private readonly ? ??; + + private Timer ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + private bool ??; + + private readonly List ??; + + private readonly object ??; + + private readonly Dictionary ??; + + private int ??; + + internal static readonly ? ?? = new ?(); + + public Connection[] All => ??.Values.ToArray(); + + public Connection[] Connected => (from P_0 in ??.Values.ToList() + where P_0.Connected + select P_0).ToArray(); + + public ConnectionInfo[] ConnectionsInfo => ??.Values.ToArray(); + + public Connection this[string id] + { + get + { + if (string.IsNullOrEmpty(id)) + { + return null; + } + return ??[id]; + } + } + + public IList Settings + { + get + { + List list = new List(); + ConnectionInfo[] connectionsInfo = Core.Instance.Connections.ConnectionsInfo; + foreach (ConnectionInfo connectionInfo in connectionsInfo) + { + try + { + list.Add(new SettingItemGroup(connectionInfo.Name, connectionInfo.Settings)); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, connectionInfo.Name); + } + } + return list; + } + set + { + foreach (SettingItem item in value) + { + ??.?(item); + ConnectionInfo connectionInfo = new ConnectionInfo(item.Name) + { + Settings = (item.Value as IList) + }; + if (connectionInfo.VendorInfo != null) + { + AddConnectionInfo(connectionInfo); + } + } + } + } + + public event Action ConnectionAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ConnectionRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event EventHandler ConnectionStateChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler ConnectionConnectingProgressChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event Action PingUpdated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ConnectionInfoAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ConnectionInfoRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ConnectionInfoRenamed + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public ConnectionsManager() + { + ?? = ?.?(); + ?? = new ?(); + ?? = new Dictionary(); + ?? = new object(); + ?? = new List(); + ?? = new object(); + } + + internal ConnectionsManager(List P_0) + : this() + { + foreach (Connection item in P_0) + { + ??.?(item.Id, item); + } + } + + public void Initialize() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + foreach (ConnectionInfo item in Core.Instance.Vendors.Vendors.SelectMany((VendorInfo P_0) => P_0.DefaultConnections)) + { + ??[item.ConnectionId] = item; + } + ?(); + Core.Instance.?(?); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + public Connection CreateConnection(ConnectionInfo info) + { + lock (??) + { + if (??.?(info.ConnectionId, out var result)) + { + return result; + } + result = new Connection(info); + ??.?(result.Id, result); + ?(result); + return result; + } + } + + public void RemoveConnection(Connection connection) + { + if (connection == null) + { + return; + } + lock (??) + { + ??.Remove(connection.Id); + if (??.?(connection.Id)) + { + connection.Disconnect(); + ??.?(connection.Id); + ?(connection); + } + } + } + + public ConnectionInfo CreateCustomConnectionInfo(string name, string vendorName, string group = null) + { + if (name == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (vendorName == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (group == null) + { + group = vendorName; + } + List list = ConnectionsInfo.Where((ConnectionInfo P_0) => P_0.CreationType == ConnectionCreationType.Default && P_0.VendorName == vendorName && P_0.Group == group).ToList(); + if (list.Count == 0) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + vendorName + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + group); + } + if (!list.Any((ConnectionInfo P_0) => P_0.AllowCreateCustomConnections)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + vendorName + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + group); + } + return new ConnectionInfo(name, group, vendorName, ConnectionCreationType.Custom) + { + Links = list[0].Links + }; + } + + public ConnectionInfo CreateTechnicalConnectionInfo(string name, string vendorName, string id = null) + { + if (name == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (vendorName == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ConnectionInfo connectionInfo = new ConnectionInfo(name, vendorName, vendorName, ConnectionCreationType.Technical); + if (!string.IsNullOrEmpty(id)) + { + connectionInfo.ConnectionId = id; + } + return connectionInfo; + } + + public void AddConnectionInfo(ConnectionInfo connectionInfo) + { + if (connectionInfo == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (connectionInfo.CreationType == ConnectionCreationType.Technical) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (??.?(connectionInfo.ConnectionId, out var connectionInfo2)) + { + connectionInfo2.Settings = connectionInfo.Settings; + return; + } + ??[connectionInfo.ConnectionId] = connectionInfo; + List list = ConnectionsInfo.Where((ConnectionInfo P_0) => P_0.CreationType == ConnectionCreationType.Default && P_0.VendorName == connectionInfo.VendorName && P_0.Group == connectionInfo.Group).ToList(); + if (list.Count > 0) + { + connectionInfo.Links = list[0].Links; + connectionInfo.Copyrights = list[0].Copyrights; + } + ??.InvokeSafely(connectionInfo); + } + + public void RemoveConnectionInfo(ConnectionInfo connectionInfo) + { + if (connectionInfo == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (??.?(connectionInfo.ConnectionId)) + { + ??.?(connectionInfo.ConnectionId); + if (??.?(connectionInfo.ConnectionId, out var connection)) + { + RemoveConnection(connection); + } + ??.InvokeSafely(connectionInfo); + } + } + + public void RenameConnectionInfo(ConnectionInfo connectionInfo, string newName) + { + if (connectionInfo == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(newName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!(connectionInfo.Name == newName)) + { + connectionInfo.Name = newName; + ??.InvokeSafely(connectionInfo); + } + } + + private void ?(Connection P_0) + { + P_0.StateChanged += ?; + P_0.ConnectingProgressChanged += ?; + ??.InvokeSafely(P_0); + } + + private void ?(Connection P_0) + { + P_0.StateChanged -= ?; + P_0.ConnectingProgressChanged -= ?; + ??.InvokeSafely(P_0); + } + + private void ?(object P_0, ConnectionStateChangedEventArgs P_1) + { + if (!(P_0 is Connection connection)) + { + return; + } + lock (??) + { + if (P_1.NewState == ConnectionState.ConnectionLost && !??.ContainsKey(connection.Id)) + { + ??.Add(connection.Id, new ?(connection)); + } + } + List list = null; + lock (??) + { + list = new List(??); + } + foreach (ConnectionStateObserver item in list) + { + item.?(P_0, P_1); + } + ??.InvokeSafely(P_0, P_1); + } + + private void ?(object P_0, ConnectionConnectingProgressChangedEventArgs P_1) + { + if (P_0 is Connection) + { + ???.Invoke(P_0, P_1); + } + } + + public void Dispose() + { + ?(); + if (?? != null) + { + List list = new List(??.Values); + foreach (Connection item in list) + { + item.Disconnect(); + } + ??.?(); + list.Clear(); + } + Core.Instance.?(?); + } + + internal void ?(ConnectionStateObserver P_0) + { + lock (??) + { + ??.Add(P_0); + ??.Sort(); + } + } + + internal void ?(ConnectionStateObserver P_0) + { + lock (??) + { + ??.Remove(P_0); + } + } + + private void ?() + { + try + { + if (?? == null) + { + ?? = new Timer(?); + ??.Change(0, 10000); + } + } + catch + { + } + } + + private void ?() + { + try + { + if (?? != null) + { + ??.Change(-1, -1); + ??.Dispose(); + ?? = null; + } + } + catch (Exception) + { + } + } + + private void ?(object P_0) + { + if (??) + { + return; + } + try + { + ?? = true; + Connection[] all = All; + for (int i = 0; i < all.Length; i++) + { + all[i].?(); + } + ???.Invoke(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?? = false; + } + } + + private void ?() + { + if (?? < 10) + { + ??++; + return; + } + List list = new List(); + lock (??) + { + list.AddRange(??.Values); + } + foreach (? ?? in list) + { + if (??.CurrentTask != null || ??.Connection.State == ConnectionState.Connecting) + { + continue; + } + ??.ReconnectDelay -= 1.0; + if (??.ReconnectDelay <= 0.0) + { + ??.CurrentTask = Task.Run(delegate + { + ?(??.Connection); + }).ContinueWith((Task t) => ??.CurrentTask = null); + } + } + ?? = 0; + } + + private void ?(Connection P_0) + { + ? value; + lock (??) + { + if (!??.TryGetValue(P_0.Id, out value)) + { + return; + } + } + value.ReconnectAttempts++; + ConnectionResult connectionResult = P_0.Connect(); + if (P_0.State == ConnectionState.Connected || connectionResult.Cancelled) + { + lock (??) + { + ??.Remove(P_0.Id); + return; + } + } + if (connectionResult.State == ConnectionState.Fail) + { + value.ReconnectDelay = 5.0; + } + } + } + public class ConnectionStateChangedEventArgs : EventArgs + { + [CompilerGenerated] + private ConnectionState ?; + + [CompilerGenerated] + private ConnectionState ?; + + [CompilerGenerated] + private ConnectionResult ?; + + public ConnectionState PreviousState + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = connectionState; + } + } + + public ConnectionState NewState + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = connectionState; + } + } + + public ConnectionResult LastConnectionResult + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = connectionResult; + } + } + + internal ConnectionStateChangedEventArgs(ConnectionState P_0, ConnectionState P_1, ConnectionResult P_2) + { + PreviousState = P_0; + NewState = P_1; + LastConnectionResult = P_2; + } + } + public sealed class ConnectionStateObserver : IDisposable, IComparable + { + private IConnectionStateDependent ?; + + private readonly ConnectionStateObserverPriority ?; + + private readonly ConnectionState[] ?; + + public ConnectionStateObserver(IConnectionStateDependent dependencyObject, ConnectionStateObserverPriority priority = ConnectionStateObserverPriority.Normal, params ConnectionState[] monitoringStates) + { + ? = dependencyObject; + ? = priority; + ? = monitoringStates; + Core.Instance.Connections.?(this); + } + + internal void ?(object P_0, ConnectionStateChangedEventArgs P_1) + { + if (!?.Contains(P_1.NewState) || !(P_0 is Connection connection)) + { + return; + } + try + { + ConnectionDependency connectionDependency = ??.GetConnectionStateDependency(); + if ((connectionDependency == null || connectionDependency.Behavior != ConnectionDependencyBehavior.NoDependency) && ((connectionDependency != null && connectionDependency.Behavior == ConnectionDependencyBehavior.TotalDependency) || connectionDependency?.DependentConnectionsIds?.Contains(connection.Id) == true)) + { + ??.OnConnectionStateChanged(connection, P_1); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public void Dispose() + { + Core.Instance.Connections.?(this); + ? = null; + } + + public int CompareTo(ConnectionStateObserver other) + { + return -1 * ?.CompareTo(other.?); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 2); + defaultInterpolatedStringHandler.AppendFormatted(?); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(?); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } +} +namespace ? +{ + internal class ? + { + [CompilerGenerated] + private int ?; + + [CompilerGenerated] + private double ?; + + [CompilerGenerated] + private Connection ?; + + [CompilerGenerated] + private Task ?; + + public int ReconnectAttempts + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = num; + } + } + + public double ReconnectDelay + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = num; + } + } + + public Connection Connection + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = connection; + } + } + + public Task CurrentTask + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = task; + } + } + + public ?(Connection P_0) + { + Connection = P_0; + } + } + internal class ? : IDisposable where ? : CachedRequestParameters + { + [CompilerGenerated] + private Dictionary> ?; + + private Dictionary> RequestsCache + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = dictionary; + } + } + + public ?() + { + RequestsCache = new Dictionary>(); + } + + public ? ?(? P_0) + { + int cacheKey = P_0.GetCacheKey(); + ? value; + lock (RequestsCache) + { + if (!RequestsCache.TryGetValue(cacheKey, out value)) + { + value = new ?(); + RequestsCache[cacheKey] = value; + } + else if (value.Finished) + { + return value; + } + } + Monitor.Enter(value); + if (value.Finished) + { + Monitor.Exit(value); + } + return value; + } + + public void ?(? P_0, ? P_1) + { + int cacheKey = P_0.GetCacheKey(); + ? value; + bool finished; + lock (RequestsCache) + { + if (!RequestsCache.TryGetValue(cacheKey, out value)) + { + value = (RequestsCache[cacheKey] = new ?(P_1)); + return; + } + finished = value.Finished; + value.Result = P_1; + value.Finished = true; + } + if (!finished) + { + try + { + Monitor.Exit(value); + } + catch + { + } + } + } + + public void Dispose() + { + RequestsCache.Clear(); + } + } + internal class ? + { + [CompilerGenerated] + private bool ?; + + [CompilerGenerated] + private ? ?; + + public bool Finished + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = flag; + } + } + + public ? Result + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = val; + } + } + + internal ?() + { + Result = default(?); + } + + internal ?(? P_0) + { + Result = P_0; + Finished = true; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// The main entry point in the API. Core keeps access to all business logic entities and their properties: + /// connections, accounts, symbols, positions, orders, etc. Some of them can be reached through using managers or directly via specified collections. + /// You can always access the Core object via static Core.Instance property. + /// + [Published] + public class Core : IDisposable, IBusinessObjectsProvider + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func> ??; + + public static Func ??; + + public static Func ??; + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.Symbols; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.SymbolTypes; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.Accounts; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.Assets; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.Exchanges; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.Orders; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.OrderTypes; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.Positions; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.ClosedPositions; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.CorporateActions; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.ReportTypes; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.AccountOperations; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.TradingSignals; + } + + internal bool ?(Connection P_0) + { + return P_0.Connected; + } + + internal bool ?(Connection P_0) + { + return P_0.Connected; + } + + internal bool ?(Connection P_0) + { + return P_0.Connected; + } + + internal bool ?(Connection P_0) + { + return P_0.Connected; + } + + internal string ?(PlaceOrderRequestParameters P_0) + { + return P_0.ConnectionId; + } + + internal IEnumerable ?(Connection P_0) + { + return P_0.BusinessObjects.DeliveredAssets; + } + + internal bool ?(Connection P_0) + { + if (P_0 != null) + { + string vendorName = P_0.VendorName; + if (vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return true; + } + } + return false; + } + + internal bool ?(Connection P_0) + { + if (P_0 != null) + { + string vendorName = P_0.VendorName; + if (vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return true; + } + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public BusinessObjectInfo ??; + + internal bool ?(Account P_0) + { + return P_0.Id == ??.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public GetSymbolRequestParameters ??; + + internal bool ?(Synthetic P_0) + { + return P_0.Id == ??.SymbolId; + } + + internal bool ?(HistoricalSymbol P_0) + { + return P_0.Id == ??.SymbolId; + } + } + + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(OrderType P_0) + { + return P_0.Id == ??; + } + + internal bool ?(OrderType P_0) + { + return P_0.Id == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(Connection P_0) + { + return P_0.Id == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ModifyOrderRequestParameters ??; + + internal bool ?(Connection P_0) + { + return P_0.Id == ??.ConnectionId; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ClosePositionRequestParameters ??; + + internal bool ?(Connection P_0) + { + return P_0.Id == ??.ConnectionId; + } + } + + [CompilerGenerated] + private sealed class ? + { + public CancelOrderRequestParameters ??; + + internal bool ?(Connection P_0) + { + return P_0.Id == ??.ConnectionId; + } + } + + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(Connection P_0) + { + return P_0.Id == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public HistoricalSymbol ??; + + internal bool ?(HistoricalSymbol P_0) + { + return P_0.Id == ??.Id; + } + } + + private static Core ??; + + [CompilerGenerated] + private readonly ConnectionsManager ??; + + [CompilerGenerated] + private readonly LoggerManager ??; + + [CompilerGenerated] + private readonly LicencesManager ??; + + [CompilerGenerated] + private readonly VendorManager ??; + + [CompilerGenerated] + private readonly HistoryAggregationManager ??; + + [CompilerGenerated] + private readonly VolumeAnalysisManager ??; + + [CompilerGenerated] + private readonly IndicatorManager ??; + + [CompilerGenerated] + private readonly StrategyManager ??; + + [CompilerGenerated] + private readonly OrderPlacingStrategiesManager ??; + + [CompilerGenerated] + private readonly MessengersManager ??; + + [CompilerGenerated] + private readonly LocalOrdersManager ??; + + [CompilerGenerated] + private readonly RulesManager ??; + + [CompilerGenerated] + private readonly SymbolsMappingManager ??; + + [CompilerGenerated] + private readonly CustomSessionsManager ??; + + [CompilerGenerated] + private readonly TimeUtils ??; + + [CompilerGenerated] + private readonly MailUtils ??; + + [CompilerGenerated] + private readonly TradingProtector ??; + + [CompilerGenerated] + private IBrandingInformation ??; + + private TradingStatus ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private ? ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private CustomAccountPropertiesProvider ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private AdvancedTradingOperations ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private readonly SymbolsListManager ??; + + private readonly List ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private readonly List ?? = new List(); + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + private Timer ??; + + [CompilerGenerated] + private IBrowserFactory ??; + + [CompilerGenerated] + private IOAuthBrowserCreator ??; + + [CompilerGenerated] + private Func ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + /// + /// Gets a singleton instance of . API entry point + /// + public static Core Instance + { + get + { + lock (typeof(Core)) + { + if (?? == null) + { + ?? = new Core(); + } + } + return ??; + } + } + + /// + /// Gets an access to all created connections and manages them + /// + public ConnectionsManager Connections + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets an access to the system logging mechanism + /// + public LoggerManager Loggers + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Obtains licence rules for the current user + /// + [NotPublished] + public LicencesManager Licences + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets an access to all available trading data vendors and creates them + /// + [NotPublished] + public VendorManager Vendors + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets an access to the all available aggregation types + /// + [NotPublished] + public HistoryAggregationManager HistoryAggregations + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Access to Volume Analysis calculations + /// + public VolumeAnalysisManager VolumeAnalysis + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets an access to the all available indicators and creates them + /// + public IndicatorManager Indicators + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets an access to the all available trading strategies and manages them + /// + public StrategyManager Strategies + { + [CompilerGenerated] + get + { + return ??; + } + } + + public OrderPlacingStrategiesManager OrderPlacingStrategies + { + [CompilerGenerated] + get + { + return ??; + } + } + + public MessengersManager Messengers + { + [CompilerGenerated] + get + { + return ??; + } + } + + public LocalOrdersManager LocalOrders + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets a permissions checking mechanism + /// + [NotPublished] + public RulesManager RulesManager + { + [CompilerGenerated] + get + { + return ??; + } + } + + public SymbolsMappingManager SymbolsMapping + { + [CompilerGenerated] + get + { + return ??; + } + } + + public CustomSessionsManager CustomSessions + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets a time based conversion and synchronization mechanism + /// + public TimeUtils TimeUtils + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets SMTP mail service for sending emails + /// + public MailUtils MailUtils + { + [CompilerGenerated] + get + { + return ??; + } + } + + public TradingProtector TradingProtection + { + [CompilerGenerated] + get + { + return ??; + } + } + + public IBrandingInformation BrandingInformation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = brandingInformation; + } + } + + public Version CurrentVersion => new Version(GetType().Assembly.GetName().Version.ToString(3)); + + /// + /// Represents current trading status + /// + public TradingStatus TradingStatus + { + get + { + return ??; + } + set + { + ?? = value; + ???.Invoke(value); + } + } + + internal ? CustomMessageProcessor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = ?; + } + } + + private bool AlreadyInitialized + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + + public CustomAccountPropertiesProvider CustomAccountPropertiesProvider + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = customAccountPropertiesProvider; + } + } + + /// + /// Gets all available s from open connections + /// + public Symbol[] Symbols => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.Symbols).ToArray(); + + /// + /// Gets all available s from open connections + /// + public SymbolType[] SymbolTypes => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.SymbolTypes).Distinct().ToArray(); + + /// + /// Gets all available s from open connections + /// + public Account[] Accounts => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.Accounts).ToArray(); + + /// + /// Gets all available s from open connections + /// + public Asset[] Assets => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.Assets).ToArray(); + + /// + /// Gets all available s from open connections + /// + public Exchange[] Exchanges => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.Exchanges).ToArray(); + + /// + /// Gets all available s from open connections + /// + public Order[] Orders => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.Orders).ToArray(); + + /// + /// Gets all available s from open connections + /// + public OrderType[] OrderTypes => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.OrderTypes).ToArray(); + + /// + /// Gets all available s from open connections + /// + public Position[] Positions => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.Positions).ToArray(); + + /// + /// Gets all available s from open connections + /// + public ClosedPosition[] ClosedPositions => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.ClosedPositions).ToArray(); + + /// + /// Gets all available s from open connections + /// + public CorporateAction[] CorporateActions => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.CorporateActions).ToArray(); + + /// + /// Gets all available s from open connections. Otherwise returns empty list + /// > + public ReportType[] ReportTypes => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.ReportTypes).ToArray(); + + public AccountOperation[] AccountOperations => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.AccountOperations).ToArray(); + + /// + /// Gets all available s from open connections. Otherwise returns empty list + /// > + public TradingSignal[] TradingSignals => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.TradingSignals).ToArray(); + + public AdvancedTradingOperations AdvancedTradingOperations + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = advancedTradingOperations; + } + } + + public DeliveredAsset[] DeliveredAssets => Connections.Connected.SelectMany((Connection P_0) => P_0.BusinessObjects.DeliveredAssets).ToArray(); + + /// + /// Gets all previously configured s + /// + [NotPublished] + public SymbolList[] SymbolList => SymbolListManager.Items; + + /// + /// Gets an access to s and manages them + /// + [NotPublished] + public SymbolsListManager SymbolListManager + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Represent all available Historical Symbols + /// + [NotPublished] + public List HistoricalSymbols => new List(??); + + /// + /// Represent all available Synthetic items + /// + [NotPublished] + public List Synthetics + { + [CompilerGenerated] + get + { + return ??; + } + } + + [NotPublished] + public IBrowserFactory BrowserFactory + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [NotPublished] + public IOAuthBrowserCreator OAuthBrowserCreator + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Will be triggered when changed + /// + public event Action OnTradingStatusChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new added to the core + /// + public event Action AccountAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new added to the core + /// + public event Action SymbolAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new placed + /// + public event Action OrderAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when canceled + /// + public event Action OrderRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new opened + /// + public event Action PositionAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when closed + /// + public event Action PositionRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new added + /// + public event Action ClosedPositionAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when removed + /// + public event Action ClosedPositionRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new occured + /// + public event Action TradeAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new occured + /// + public event Action CorporateActionAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new added + /// + public event Action OrdersHistoryAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action DeliveredAssetAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action DeliveredAssetRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when new received + /// + public event Action DealTicketReceived + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + [NotPublished] + public event Action HistoricalSymbolAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + [NotPublished] + public event Action HistoricalSymbolRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + [NotPublished] + public event Action HistoricalSymbolUpdated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when custom symbol added + /// + [NotPublished] + public event Action SyntheticAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when custom symbol removed + /// + [NotPublished] + public event Action SyntheticRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when custom symbol updated + /// + [NotPublished] + public event Action SyntheticUpdated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Will be triggered when created/chenged/removed + /// + public event EventHandler TradingSignalUpdate + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event Action OnAlert + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action OnRequestOTP + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Func OnAskUserConfirmationForTradingWithRunningEmulator + { + [CompilerGenerated] + add + { + Func func = ??; + Func func2; + do + { + func2 = func; + Func value2 = (Func)Delegate.Combine(func2, value); + func = Interlocked.CompareExchange(ref ??, value2, func2); + } + while ((object)func != func2); + } + [CompilerGenerated] + remove + { + Func func = ??; + Func func2; + do + { + func2 = func; + Func value2 = (Func)Delegate.Remove(func2, value); + func = Interlocked.CompareExchange(ref ??, value2, func2); + } + while ((object)func != func2); + } + } + + public event EventHandler NewRequest + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler NewPerformedRequest + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + private Core() + { + global::?.?.?(GetType().Assembly.Location); + ?? = new ConnectionsManager(); + ?? = new LoggerManager(); + ?? = new LicencesManager(); + ?? = new VendorManager(); + ?? = new HistoryAggregationManager(); + ?? = new VolumeAnalysisManager(); + ?? = new IndicatorManager(); + ?? = new StrategyManager(); + ?? = new OrderPlacingStrategiesManager(); + ?? = new SymbolsListManager(); + ?? = new RulesManager(); + ?? = new SymbolsMappingManager(); + ?? = new CustomSessionsManager(); + ?? = new MessengersManager(); + ?? = new LocalOrdersManager(); + ?? = new TimeUtils(); + ?? = new MailUtils(); + ?? = new TradingProtector(); + ?? = new List(); + CustomAccountPropertiesProvider = new CustomAccountPropertiesProvider(); + } + + /// + /// Starts a initialization process which initializes given Managers, and Utils. And provides a subscribing on events. + /// + [NotPublished] + public void Initialize() + { + lock (??) + { + if (AlreadyInitialized) + { + return; + } + AlreadyInitialized = true; + } + CustomMessageProcessor = new ?(); + ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + Loggers.?(); + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + TimeUtils.?(); + Licences.?(); + Vendors.?(); + HistoryAggregations.?(); + VolumeAnalysis.?(); + Indicators.?(); + Strategies.?(); + OrderPlacingStrategies.?(); + Connections.Initialize(); + SymbolsMapping.?(); + Messengers.?(); + SymbolListManager.?(); + LocalOrders.Initialize(); + AdvancedTradingOperations = new AdvancedTradingOperations(); + ?(); + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + /// + /// Disposes all previously initialized modules and unsubscribe from events + /// + [NotPublished] + public void Dispose() + { + lock (??) + { + if (!AlreadyInitialized) + { + return; + } + Licences.Dispose(); + Vendors.?(); + HistoryAggregations.?(); + VolumeAnalysis.?(); + Indicators.Dispose(); + Strategies.Dispose(); + OrderPlacingStrategies.Dispose(); + Messengers.Dispose(); + Connections.Dispose(); + TimeUtils.?(); + MailUtils.?(); + Loggers.Dispose(); + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + AlreadyInitialized = false; + lock (typeof(Core)) + { + ?? = null; + } + } + } + + /// + /// Gets an instance of exist Account or creates a new one with given info parameter + /// + /// + /// + public Account GetAccount(BusinessObjectInfo accountInfo) + { + if (accountInfo == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Account account = Connections[accountInfo.ConnectionId]?.BusinessObjects?.Accounts?.FirstOrDefault((Account P_0) => P_0.Id == accountInfo.Id); + if (account != null) + { + return account; + } + if (accountInfo is ? { IsCrypto: not false }) + { + return new CryptoAccount(accountInfo); + } + return new Account(accountInfo); + } + + internal void ?(Account P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(Symbol P_0) + { + ??.InvokeSafely(P_0); + } + + /// + /// Returns all s from open connections which satisfy given request parameters, otherwise returns empty list + /// + /// + /// + [NotPublished] + public IList SearchSymbols(SearchSymbolsRequestParameters requestParameters) + { + List list = new List(); + if (string.IsNullOrEmpty(requestParameters.ConnectionId)) + { + Connection[] connected = Connections.Connected; + for (int i = 0; i < connected.Length; i++) + { + IList list2 = connected[i].?(requestParameters); + if (list2 != null) + { + list.AddRange(list2); + } + } + } + else + { + IList list3 = Connections[requestParameters.ConnectionId]?.?(requestParameters); + if (list3 != null) + { + list.AddRange(list3); + } + } + return list; + } + + /// + /// Retrieves any by given request parameters. Otherwise returns null + /// + /// + /// Must be specified if open connections total is more than one. Will search only in Synthetic symbols list if id is equal to + /// + /// + public Symbol GetSymbol(GetSymbolRequestParameters requestParameters, string connectionId = null, NonFixedListDownload downloadSymbol = NonFixedListDownload.Download) + { + if (connectionId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return Synthetics.Find((Synthetic P_0) => P_0.Id == requestParameters.SymbolId); + } + if (connectionId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return HistoricalSymbols.Find((HistoricalSymbol P_0) => P_0.Id == requestParameters.SymbolId); + } + if (!string.IsNullOrEmpty(connectionId)) + { + return Connections[connectionId]?.?(requestParameters, downloadSymbol); + } + if (Connections.All.Count((Connection P_0) => P_0.Connected) > 1) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Connections.All.FirstOrDefault((Connection P_0) => P_0.Connected)?.?(requestParameters, downloadSymbol); + } + + /// + /// Gets an instance of exist symbol or creates a new one with given info parameter + /// + /// + /// + public Symbol GetSymbol(BusinessObjectInfo symbolInfo) + { + if (symbolInfo == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + GetSymbolRequestParameters requestParameters = new GetSymbolRequestParameters + { + SymbolId = symbolInfo.Id + }; + return GetSymbol(requestParameters, symbolInfo.ConnectionId) ?? new Symbol(symbolInfo); + } + + [NotPublished] + public IList GetFutureContracts(Symbol underlier) + { + return GetFutureContracts(new GetFutureContractsRequestParameters + { + ConnectionId = underlier.ConnectionId, + ExchangeId = underlier.Exchange.Id, + UnderlierId = underlier.Id + }); + } + + [NotPublished] + public IList GetFutureContracts(string root, string exchangeId, string connectionId = null) + { + return GetFutureContracts(new GetFutureContractsRequestParameters + { + ConnectionId = connectionId, + Root = root, + ExchangeId = exchangeId + }); + } + + [NotPublished] + public IList GetFutureContracts(GetFutureContractsRequestParameters requestParameters) + { + if (requestParameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(requestParameters.Root) && string.IsNullOrEmpty(requestParameters.UnderlierId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!string.IsNullOrEmpty(requestParameters.ConnectionId)) + { + return Connections[requestParameters.ConnectionId]?.?(requestParameters); + } + if (Connections.All.Count((Connection P_0) => P_0.Connected) > 1) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Connections.All.FirstOrDefault()?.?(requestParameters); + } + + [NotPublished] + public virtual IList GetOptionSeries(Symbol underlier) + { + return GetOptionSeries(new GetOptionSeriesRequestParameters(underlier)); + } + + [NotPublished] + public virtual IList GetOptionSeries(GetOptionSeriesRequestParameters requestParameters) + { + if (requestParameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(requestParameters.ConnectionId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(requestParameters.UnderlierId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Connections[requestParameters.ConnectionId]?.?(requestParameters); + } + + [NotPublished] + public virtual IList GetStrikes(OptionSerie serie) + { + return GetStrikes(new GetStrikesRequestParameters(serie)); + } + + [NotPublished] + public virtual IList GetStrikes(GetStrikesRequestParameters requestParameters) + { + if (requestParameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(requestParameters.ConnectionId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(requestParameters.UnderlierId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(requestParameters.SerieId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Connections[requestParameters.ConnectionId]?.?(requestParameters); + } + + internal void ?(Order P_0) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.ToString()); + ??.InvokeSafely(P_0); + } + + internal void ?(Order P_0) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.ToString()); + ??.InvokeSafely(P_0); + } + + /// + /// Gets instance by given Id string. Otherwise returns null + /// + /// + /// Must be specified if open connections total is more than one + /// + public OrderType GetOrderType(string orderTypeId, string connectionId = null) + { + if (string.IsNullOrEmpty(orderTypeId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!string.IsNullOrEmpty(connectionId)) + { + return Connections[connectionId]?.BusinessObjects?.OrderTypes?.FirstOrDefault((OrderType P_0) => P_0.Id == orderTypeId); + } + Connection[] array = Connections.All.Where((Connection P_0) => P_0.Connected).ToArray(); + if (array.Length > 1) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return array.First().BusinessObjects.OrderTypes.SingleOrDefault((OrderType P_0) => P_0.Id == orderTypeId); + } + + /// + /// Gets instance by given Id string. Otherwise returns null + /// + /// + /// Must be specified if open connections total is more than one + /// + public Order GetOrderById(string orderId, string connectionId = null) + { + Connection connection = Connections[connectionId]; + if (connection != null) + { + return connection.?(orderId); + } + Connection[] all = Connections.All; + for (int i = 0; i < all.Length; i++) + { + Order order = all[i].?(orderId); + if (order != null) + { + return order; + } + } + return null; + } + + internal void ?(Position P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(Position P_0) + { + ??.InvokeSafely(P_0); + } + + /// + /// Gets instance by given Id string. Otherwise returns null + /// + /// + /// Must be specified if open connections total is more than one + /// + public Position GetPositionById(string positionId, string connectionId = null) + { + Connection connection = Connections[connectionId]; + if (connection != null) + { + return connection.?(positionId); + } + Connection[] all = Connections.All; + for (int i = 0; i < all.Length; i++) + { + Position position = all[i].?(positionId); + if (position != null) + { + return position; + } + } + return null; + } + + /// + /// Gets Profit'n'Loss with given request parameters from open connection. Otherwise returns null + /// + /// + /// + public PnL CalculatePnL(PnLRequestParameters parameters) + { + string ?? = parameters.Account?.ConnectionId ?? parameters.Symbol.ConnectionId; + Connection connection = Connections.All.FirstOrDefault((Connection P_0) => P_0.Id == ??); + if (connection == null) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + return null; + } + if (!connection.Connected) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + return null; + } + return connection.?(parameters); + } + + internal void ?(ClosedPosition P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(ClosedPosition P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(Trade P_0) + { + Order orderById = GetOrderById(P_0.OrderId, P_0.ConnectionId); + LoggerManager loggers = Loggers; + string text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 2); + defaultInterpolatedStringHandler.AppendFormatted(P_0); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((orderById == null) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : $"{orderById}"); + loggers.Log(text, defaultInterpolatedStringHandler.ToStringAndClear()); + ??.InvokeSafely(P_0); + } + + /// + /// Gets collection of by given parameters + /// + /// + /// + /// + public IList GetTrades(TradesHistoryRequestParameters parameters, string connectionId = null) + { + if (parameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(connectionId)) + { + List list = new List(); + Connection[] all = Connections.All; + for (int i = 0; i < all.Length; i++) + { + IList trades = all[i].GetTrades(new TradesHistoryRequestParameters(parameters)); + if (trades != null) + { + list.AddRange(trades); + } + } + return list; + } + return Connections[connectionId]?.GetTrades(parameters) ?? new List(); + } + + /// + /// Gets collection of by given parameters and callback + /// + /// + /// + /// + /// + public void GetTrades(TradesHistoryRequestParameters parameters, AccountTradesLoadingCallback callback, string connectionId = null) + { + if (parameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (callback == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(connectionId)) + { + Connection[] all = Connections.All; + for (int i = 0; i < all.Length; i++) + { + all[i].?(new TradesHistoryRequestParameters(parameters), callback); + } + } + Connections[connectionId]?.?(parameters, callback); + } + + internal void ?(CorporateAction P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(OrderHistory P_0) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.ToString()); + ??.InvokeSafely(P_0); + } + + /// + /// Gets collection of by given parameters + /// + /// + /// + /// + public IList GetOrdersHistory(OrdersHistoryRequestParameters parameters, string connectionId = null) + { + if (parameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(connectionId)) + { + List list = new List(); + Connection[] all = Connections.All; + for (int i = 0; i < all.Length; i++) + { + IList ordersHistory = all[i].GetOrdersHistory(parameters); + if (ordersHistory != null) + { + list.AddRange(ordersHistory); + } + } + return list; + } + return Connections[connectionId]?.GetOrdersHistory(parameters) ?? new List(); + } + + public TradingOperationResult PlaceOrder(Symbol symbol, Account account, Side side, TimeInForce timeInForce = TimeInForce.Day, double quantity = 1.0, double price = -1.0, double triggerPrice = -1.0, double trailOffset = -1.0) + { + if (symbol == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (account == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters + { + Symbol = symbol, + Account = account, + Side = side, + Quantity = quantity, + TimeInForce = timeInForce + }; + if (price > 0.0 && triggerPrice <= 0.0 && trailOffset <= 0.0) + { + placeOrderRequestParameters.OrderTypeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + placeOrderRequestParameters.Price = price; + } + else if (triggerPrice > 0.0 && price <= 0.0 && trailOffset <= 0.0) + { + placeOrderRequestParameters.OrderTypeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + placeOrderRequestParameters.TriggerPrice = triggerPrice; + } + else if (price > 0.0 && triggerPrice > 0.0 && trailOffset <= 0.0) + { + placeOrderRequestParameters.OrderTypeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + placeOrderRequestParameters.Price = price; + placeOrderRequestParameters.TriggerPrice = triggerPrice; + } + else if (trailOffset > 0.0 && price <= 0.0 && triggerPrice <= 0.0) + { + placeOrderRequestParameters.OrderTypeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + placeOrderRequestParameters.TrailOffset = trailOffset; + } + else + { + placeOrderRequestParameters.OrderTypeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return PlaceOrder(placeOrderRequestParameters); + } + + /// + /// Places with given request parameters + /// + /// + /// + public TradingOperationResult PlaceOrder(PlaceOrderRequestParameters request) + { + if (request == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!?(request.Symbol?.Connection, request.RequestId, out var result)) + { + return result; + } + if (!?(request.Symbol?.Connection, request.RequestId, out result)) + { + return result; + } + return request.Symbol?.?(request); + } + + /// + /// Places multiple s with given request parameters + /// + /// + /// + /// + public void PlaceOrders(ICollection requests, GroupOrderType groupOrderType = GroupOrderType.None) + { + if (requests == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (requests.Count == 1) + { + PlaceOrder(requests.Single()); + return; + } + foreach (IGrouping item in from P_0 in requests + group P_0 by P_0.ConnectionId) + { + Connection connection = Connections[item.Key]; + if (RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), connection.Id).Status == TradingOperationStatus.Allowed) + { + PlaceMultiOrderOrderRequestParameters placeMultiOrderOrderRequestParameters = new PlaceMultiOrderOrderRequestParameters + { + GroupOrderType = groupOrderType, + OrderParameters = item.ToArray() + }; + if (?(connection, placeMultiOrderOrderRequestParameters.RequestId, out var tradingOperationResult) && ?(connection, placeMultiOrderOrderRequestParameters.RequestId, out tradingOperationResult)) + { + connection.?(placeMultiOrderOrderRequestParameters); + } + } + else if (groupOrderType == GroupOrderType.None) + { + PlaceOrderRequestParameters[] array = item.ToArray(); + foreach (PlaceOrderRequestParameters request in array) + { + PlaceOrder(request); + } + } + } + } + + public TradingOperationResult ModifyOrder(Order order, TimeInForce timeInForce = TimeInForce.Default, double quantity = 1.0, double price = -1.0, double triggerPrice = -1.0, double trailOffset = -1.0) + { + if (order == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ModifyOrderRequestParameters modifyOrderRequestParameters = new ModifyOrderRequestParameters(order); + if (timeInForce != TimeInForce.Default) + { + modifyOrderRequestParameters.TimeInForce = timeInForce; + } + if (quantity > 0.0) + { + modifyOrderRequestParameters.Quantity = quantity; + } + if (price > 0.0) + { + modifyOrderRequestParameters.Price = price; + } + if (triggerPrice > 0.0) + { + modifyOrderRequestParameters.TriggerPrice = triggerPrice; + } + if (trailOffset > 0.0) + { + modifyOrderRequestParameters.TrailOffset = trailOffset; + } + return ModifyOrder(modifyOrderRequestParameters); + } + + /// + /// Modifies by given request parameters + /// + /// + /// + public TradingOperationResult ModifyOrder(ModifyOrderRequestParameters request) + { + if (request == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (LocalOrders.TryHandleTradingOperationRequest(request, out var result)) + { + return result; + } + Connection connection = Connections.All.FirstOrDefault((Connection P_0) => P_0.Id == request.ConnectionId); + if (connection == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!?(connection, request.RequestId, out result)) + { + return result; + } + return connection.?(request); + } + + public TradingOperationResult ClosePosition(Position position, double closeQuantity = -1.0) + { + if (position == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ClosePositionRequestParameters request = new ClosePositionRequestParameters + { + Position = position, + CloseQuantity = ((closeQuantity > 0.0) ? closeQuantity : position.Quantity) + }; + return ClosePosition(request); + } + + /// + /// Closes with given request parameters + /// + /// + /// + public TradingOperationResult ClosePosition(ClosePositionRequestParameters request) + { + if (request == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Connection connection = Connections.All.FirstOrDefault((Connection P_0) => P_0.Id == request.ConnectionId); + if (connection == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!?(Connections[request.ConnectionId], request.RequestId, out var result)) + { + return result; + } + return connection.?(request); + } + + [Obsolete("Use CancelOrder(IOrder order) instead")] + public TradingOperationResult CancelOrder(Order order, string sendingSource = null) + { + if (order == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + CancelOrderRequestParameters request = new CancelOrderRequestParameters + { + Order = order, + SendingSource = sendingSource + }; + return CancelOrder(request); + } + + public TradingOperationResult CancelOrder(IOrder order, string sendingSource = null) + { + if (order == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + CancelOrderRequestParameters request = new CancelOrderRequestParameters + { + Order = order, + SendingSource = sendingSource + }; + return CancelOrder(request); + } + + /// + /// Cancels with given request parameters + /// + /// + /// + public TradingOperationResult CancelOrder(CancelOrderRequestParameters request) + { + if (request == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (LocalOrders.TryHandleTradingOperationRequest(request, out var result)) + { + return result; + } + Connection connection = Connections.All.FirstOrDefault((Connection P_0) => P_0.Id == request.ConnectionId); + if (connection == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!?(connection, request.RequestId, out result)) + { + return result; + } + return connection.?(request); + } + + /// + /// Returns with given request parameters from open connection + /// + /// + /// + public Report GetReport(ReportRequestParameters requestParameters) + { + Connection connection = requestParameters.ReportType.Connection; + if (connection == null) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + return null; + } + if (!connection.Connected) + { + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + return null; + } + return connection.?(requestParameters); + } + + internal void ?(DeliveredAsset P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(DeliveredAsset P_0) + { + ??.InvokeSafely(P_0); + } + + internal void ?(DealTicket P_0) + { + ??.InvokeSafely(P_0); + } + + [NotPublished] + public void PushDealTicket(string header, string description, DealTicketType type) + { + ??.InvokeSafely(new DealTicket(header, description, type)); + } + + [NotPublished] + public void PushDealTicket(DealTicket dealTicket) + { + ??.InvokeSafely(dealTicket); + } + + /// + /// Sends custom request if connection with given Id is open + /// + /// + /// + public void SendCustomRequest(string connectionId, RequestParameters parameters) + { + Connections.Connected.FirstOrDefault((Connection P_0) => P_0.Id == connectionId)?.SendCustomRequest(parameters); + } + + /// + /// Subscribe on custom messages + /// + /// custom message handler + /// custom messages Id + public void SubscribeToCustomMessages(Action handler, params int[] messagesTypes) + { + CustomMessageProcessor.?(handler, messagesTypes); + } + + /// + /// Unsubscribe from custom messages + /// + /// custom message handler + /// custom messages Id + public void UnsubscribeFromCustomMessages(Action handler, params int[] messagesTypes) + { + CustomMessageProcessor.?(handler, messagesTypes); + } + + /// + /// Adds if given parameters are valid + /// + /// + /// + [NotPublished] + public void AddSymbolList(string symbolsListName, IEnumerable symbols) + { + if (string.IsNullOrEmpty(symbolsListName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (symbols == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SymbolListManager.?(symbolsListName, symbols); + } + + /// + /// Replaces exist list by new list in if given parameters are valid + /// + /// + /// + [NotPublished] + public void ReplaceSymbolList(string symbolsListName, IList symbols) + { + if (string.IsNullOrEmpty(symbolsListName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (symbols == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SymbolListManager.?(symbolsListName, symbols); + } + + /// + /// Removes with a given name + /// + /// + [NotPublished] + public void RemoveSymbolList(string symbolsListName) + { + if (string.IsNullOrEmpty(symbolsListName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SymbolListManager.?(symbolsListName); + } + + /// + /// Replaces list name by new given name in if given parameters are valid + /// + /// + /// + [NotPublished] + public void RenameSymbolList(string symbolsListName, string newSymbolsListName) + { + if (string.IsNullOrEmpty(symbolsListName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(newSymbolsListName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SymbolListManager.?(symbolsListName, newSymbolsListName); + } + + [NotPublished] + public void AddHistoricalSymbol(HistoricalSymbol historicalSymbol) + { + if (!??.Contains(historicalSymbol) && !??.Any((HistoricalSymbol P_0) => P_0.Id == historicalSymbol.Id)) + { + ??.Add(historicalSymbol); + historicalSymbol.Updated += ?; + ??.InvokeSafely(historicalSymbol); + } + } + + [NotPublished] + public void RemoveHistoricalSymbol(HistoricalSymbol historicalSymbol) + { + if (??.Contains(historicalSymbol)) + { + ??.Remove(historicalSymbol); + historicalSymbol.Updated -= ?; + ??.InvokeSafely(historicalSymbol); + historicalSymbol.Dispose(); + } + } + + private void ?(Symbol P_0) + { + if (P_0 is HistoricalSymbol historicalSymbol) + { + ??.InvokeSafely(historicalSymbol); + } + } + + /// + /// Adds given Synthetic to the list if it does not contain + /// + /// + [NotPublished] + public void AddSynthetic(Synthetic synthetic) + { + if (!Synthetics.Contains(synthetic)) + { + Synthetics.Add(synthetic); + synthetic.Reinitialized += ?; + ??.InvokeSafely(synthetic); + } + } + + private void ?(Synthetic P_0) + { + ??.InvokeSafely(P_0); + } + + /// + /// Removes given Synthetic from the list if it exists + /// + /// + [NotPublished] + public void RemoveSynthetic(Synthetic synthetic) + { + if (Synthetics.Contains(synthetic)) + { + Synthetics.Remove(synthetic); + synthetic.Reinitialized -= ?; + ??.InvokeSafely(synthetic); + synthetic.Dispose(); + } + } + + internal void ?(TradingSignal P_0, EntityLifecycle P_1) + { + ??.InvokeSafely(this, new TradingSignalEventArgs + { + TradingSignal = P_0, + Lifecycle = P_1 + }); + } + + public void Alert(string text, string symbolName, string connectionName, Action onConfirm, string alertName) + { + Alert(new Alert + { + Text = text, + SymbolName = symbolName, + ConnectionName = connectionName, + ActionOnConfirm = onConfirm, + Name = alertName + }); + } + + public void Alert(string text, string symbolName = "", string connectionName = "", Action onConfirm = null) + { + Alert(text, symbolName, connectionName, onConfirm, null); + } + + public void Alert(Alert alert) + { + ??.InvokeSafely(alert); + } + + public void RequestOTP(OTPHolder otpHolder, string title, string text) + { + ??.InvokeSafely(otpHolder, title, text); + } + + [SpecialName] + [CompilerGenerated] + internal void ?(Action P_0) + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value = (Action)Delegate.Combine(action2, P_0); + action = Interlocked.CompareExchange(ref ??, value, action2); + } + while ((object)action != action2); + } + + [SpecialName] + [CompilerGenerated] + internal void ?(Action P_0) + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value = (Action)Delegate.Remove(action2, P_0); + action = Interlocked.CompareExchange(ref ??, value, action2); + } + while ((object)action != action2); + } + + private void ?() + { + if (?? == null) + { + ?? = new Timer(?); + ??.Change(100, 100); + } + } + + private void ?(object P_0) + { + try + { + ?(); + ??.InvokeSafely(); + TradingProtection.?(); + } + catch (Exception ex) + { + Loggers.Log(ex); + } + } + + private void ?() + { + Position[] positions = Positions; + foreach (Position position in positions) + { + try + { + PnL pnL = CalculatePnL(new PnLRequestParameters + { + Symbol = position.Symbol, + Account = position.Account, + OpenPrice = position.OpenPrice, + ClosePrice = position.CurrentPrice, + Side = position.Side, + Quantity = position.Quantity, + PositionId = position.Id + }); + if (pnL != null) + { + position.?(pnL); + } + } + catch (Exception ex) + { + Instance.Loggers.Log(ex); + } + } + ClosedPosition[] closedPositions = ClosedPositions; + foreach (ClosedPosition closedPosition in closedPositions) + { + try + { + if (closedPosition.GrossPnL != null) + { + continue; + } + PnL pnL2 = CalculatePnL(new PnLRequestParameters + { + Symbol = closedPosition.Symbol, + Account = closedPosition.Account, + OpenPrice = closedPosition.OpenPrice, + ClosePrice = closedPosition.CurrentPrice, + Side = closedPosition.Side, + Quantity = 0.0, + PositionId = closedPosition.Id + }); + if (pnL2 != null) + { + closedPosition.?(pnL2); + ClosedPosition closedPosition2 = closedPosition; + if (closedPosition2.GrossPnL == null) + { + PnLItem pnLItem = (closedPosition2.GrossPnL = new PnLItem()); + } + } + } + catch (Exception ex2) + { + Instance.Loggers.Log(ex2); + } + } + } + + public void InitializeBrandingInformation() + { + IBrandingInformation brandingInformation = new ?(); + try + { + TypeWrapper typeWrapper = AssemblyLoader.LoadTypes(string.Empty, typeof(IBrandingInformation), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).FirstOrDefault(); + if (typeWrapper != null) + { + IBrandingInformation brandingInformation2 = (IBrandingInformation)Activator.CreateInstance(typeWrapper); + if (brandingInformation2 != null) + { + brandingInformation = brandingInformation2; + } + } + } + catch (Exception ex) + { + Instance.Loggers.Log(ex); + } + BrandingInformation = brandingInformation; + } + + public void ForceTimeSync() + { + TimeUtils.TimeSynchronizer.?(); + } + + private bool ?(Connection P_0, long P_1, out TradingOperationResult P_2) + { + P_2 = null; + bool flag; + if (P_0 != null) + { + string vendorName = P_0.VendorName; + if (vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + flag = true; + goto IL_003a; + } + } + flag = false; + goto IL_003a; + IL_003a: + if (flag) + { + return true; + } + if (TradingProtection.IsOperationAllowed()) + { + return true; + } + string text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + PushDealTicket(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), text, DealTicketType.Refuse); + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), text, LoggingLevel.Error); + P_2 = TradingOperationResult.CreateError(P_1, text); + return false; + } + + private bool ?(Connection P_0, long P_1, out TradingOperationResult P_2) + { + P_2 = null; + bool flag; + if (P_0 != null) + { + string vendorName = P_0.VendorName; + if (vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + flag = true; + goto IL_003a; + } + } + flag = false; + goto IL_003a; + IL_003a: + if (flag) + { + return true; + } + if (!Instance.Connections.Connected.Any(delegate(Connection connection) + { + if (connection != null) + { + string vendorName2 = connection.VendorName; + if (vendorName2 == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName2 == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName2 == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return true; + } + } + return false; + })) + { + return true; + } + bool flag2 = false; + if (?? != null) + { + flag2 = ??(Instance.Connections.Connected.FirstOrDefault(delegate(Connection connection) + { + if (connection != null) + { + string vendorName2 = connection.VendorName; + if (vendorName2 == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName2 == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || vendorName2 == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return true; + } + } + return false; + }).Name, P_0.Name); + } + if (flag2) + { + return true; + } + string text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + PushDealTicket(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), text, DealTicketType.Refuse); + Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), text, LoggingLevel.Error); + P_2 = TradingOperationResult.CreateError(P_1, text); + return false; + } + + internal void ?(RequestParameters P_0, object P_1) + { + ???.InvokeSafely(this, new PerformedRequestEventArgs(P_0, P_1)); + } + + internal void ?(Connection P_0, RequestEventArgs P_1) + { + ???.InvokeSafely(P_0, P_1); + } + } + public class CustomHoliday : ICustomizable + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + public bool IsActive + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime Date + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsActive), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name), + new SettingItemDateTime(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Date) + }; + } + set + { + IsActive = value.GetValueOrDefault(IsActive, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Name = value.GetValueOrDefault(Name, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Date = value.GetValueOrDefault(Date, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + } + public class CustomSession : ISession, ICustomizable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal string ?(DayOfWeek P_0) + { + return P_0.ToString(); + } + } + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private SessionType ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + private bool ??; + + [CompilerGenerated] + private DayOfWeek[] ??; + + [CompilerGenerated] + private bool ??; + + public bool IsActive + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SessionType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeSpan OpenTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + public TimeSpan CloseTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + public TimeSpan OpenOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeSpan CloseOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DayOfWeek[] Days + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool IsPrimary + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsActive), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name), + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Type), + new SettingItemLong(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OpenOffset.Ticks), + new SettingItemLong(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CloseOffset.Ticks), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), string.Join(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Days.Select((DayOfWeek P_0) => P_0.ToString()))) + }; + } + set + { + IsActive = value.GetValueOrDefault(IsActive, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Name = value.GetValueOrDefault(Name, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Type = (SessionType)value.GetValueOrDefault((int)Type, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value2)) + { + OpenOffset = TimeSpan.FromTicks(value2); + if (value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value3)) + { + CloseOffset = TimeSpan.FromTicks(value3); + } + } + else + { + ?? = true; + if (value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value4)) + { + OpenTime = TimeSpan.FromTicks(value4); + } + if (value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value5)) + { + CloseTime = TimeSpan.FromTicks(value5); + } + } + if (!value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value6)) + { + return; + } + string[] array = value6.Split(new string[1] { 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() }, StringSplitOptions.RemoveEmptyEntries); + List list = new List(); + string[] array2 = array; + for (int i = 0; i < array2.Length; i++) + { + if (Enum.TryParse(array2[i], ignoreCase: true, out var result)) + { + list.Add(result); + } + } + Days = list.ToArray(); + } + } + + public void RecalculateOpenCloseTime(TimeZoneInfo timeZoneInfo) + { + if (??) + { + OpenOffset = OpenTime.ConvertTimeZone(TimeZoneInfo.Utc, timeZoneInfo); + CloseOffset = CloseTime.ConvertTimeZone(TimeZoneInfo.Utc, timeZoneInfo); + } + else + { + OpenTime = OpenOffset.ConvertTimeZone(timeZoneInfo, TimeZoneInfo.Utc); + CloseTime = CloseOffset.ConvertTimeZone(timeZoneInfo, TimeZoneInfo.Utc); + } + } + } + public class CustomSessionEventArgs : EntityLifecycleEventArgs + { + [CompilerGenerated] + private readonly CustomSessionsAssignment ??; + + [CompilerGenerated] + private readonly CustomSessionsContainer ??; + + public CustomSessionsAssignment Assignment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public CustomSessionsContainer Container + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } + public sealed class CustomSessionsAssignment : IUniqueID, ICustomizable, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public IList Settings + { + get + { + return new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), UniqueId), + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsActive), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ConnectionId), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExchangeId), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SymbolId), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CustomSessionsContainerId) + }; + } + set + { + UniqueId = value.GetValueOrDefault(UniqueId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + IsActive = value.GetValueOrDefault(IsActive, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ConnectionId = value.GetValueOrDefault(ConnectionId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ExchangeId = value.GetValueOrDefault(ExchangeId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + SymbolId = value.GetValueOrDefault(SymbolId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CustomSessionsContainerId = value.GetValueOrDefault(CustomSessionsContainerId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public string UniqueId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public bool IsActive + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string ExchangeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string CustomSessionsContainerId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public ExchangeComplexIdentifier ExchangeComplexId => new ExchangeComplexIdentifier(ConnectionId, ExchangeId); + + public SymbolComplexIdentifier SymbolComplexId => new SymbolComplexIdentifier(ConnectionId, ExchangeId, SymbolId); + + public Connection Connection => Core.Instance.Connections[ConnectionId]; + + public Exchange Exchange => Core.Instance.Exchanges.FirstOrDefault(delegate(Exchange P_0) + { + ExchangeComplexIdentifier complexId = P_0.ComplexId; + ExchangeComplexIdentifier? obj = this?.ExchangeComplexId; + return complexId == obj; + }); + + public Symbol Symbol + { + get + { + try + { + if (string.IsNullOrEmpty(SymbolId)) + { + return null; + } + return Core.Instance.GetSymbol(new GetSymbolRequestParameters + { + SymbolId = SymbolId + }, ConnectionId); + } + catch + { + return null; + } + } + } + + public CustomSessionsContainer SessionsContainer => Core.Instance.CustomSessions[CustomSessionsContainerId]; + + public CustomSessionsAssignment(string containerId, string connectionId = null, string exchangeId = null, string symbolId = null) + : this() + { + IsActive = true; + CustomSessionsContainerId = containerId; + ConnectionId = connectionId; + ExchangeId = exchangeId; + SymbolId = symbolId; + } + + public CustomSessionsAssignment(CustomSessionsAssignment origin) + : this() + { + IsActive = origin.IsActive; + ConnectionId = origin.ConnectionId; + ExchangeId = origin.ExchangeId; + SymbolId = origin.SymbolId; + CustomSessionsContainerId = origin.CustomSessionsContainerId; + } + + internal CustomSessionsAssignment() + { + UniqueId = Guid.NewGuid().ToShortString(); + } + + internal void ?(CustomSessionsAssignment P_0) + { + IsActive = P_0.IsActive; + ConnectionId = P_0.ConnectionId; + ExchangeId = P_0.ExchangeId; + SymbolId = P_0.SymbolId; + CustomSessionsContainerId = P_0.CustomSessionsContainerId; + } + + public bool Equals(CustomSessionsAssignment other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (ConnectionId == other.ConnectionId && ExchangeId == other.ExchangeId && SymbolId == other.SymbolId) + { + return CustomSessionsContainerId == other.CustomSessionsContainerId; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((CustomSessionsAssignment)obj); + } + + public override int GetHashCode() + { + return (((((((ConnectionId != null) ? ConnectionId.GetHashCode() : 0) * 397) ^ ((ExchangeId != null) ? ExchangeId.GetHashCode() : 0)) * 397) ^ ((SymbolId != null) ? SymbolId.GetHashCode() : 0)) * 397) ^ ((CustomSessionsContainerId != null) ? CustomSessionsContainerId.GetHashCode() : 0); + } + + [CompilerGenerated] + private bool ?(Exchange P_0) + { + ExchangeComplexIdentifier complexId = P_0.ComplexId; + ExchangeComplexIdentifier? obj = this?.ExchangeComplexId; + return complexId == obj; + } + } + public class CustomSessionsAssignmentManager : IEnumerable, IEnumerable, ICustomizable + { + private class ? : IComparer + { + public int Compare(CustomSessionsAssignment x, CustomSessionsAssignment y) + { + if (x == null && y != null) + { + return 1; + } + if (x != null && y == null) + { + return -1; + } + if (x == y) + { + return 0; + } + if (!string.IsNullOrEmpty(x.SymbolId)) + { + return -1; + } + if (!string.IsNullOrEmpty(y.SymbolId)) + { + return 1; + } + if (!string.IsNullOrEmpty(x.ExchangeId)) + { + return -1; + } + if (!string.IsNullOrEmpty(y.ExchangeId)) + { + return 1; + } + return 0; + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SettingItemGroup ?(CustomSessionsAssignment P_0) + { + return new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(CustomSessionsAssignment P_0) + { + if (P_0.IsActive) + { + if (!(P_0.SymbolComplexId == ??.ComplexId)) + { + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + ExchangeComplexIdentifier exchangeComplexId = P_0.ExchangeComplexId; + ExchangeComplexIdentifier? obj = ??.Exchange?.ComplexId; + if (exchangeComplexId == obj) + { + goto IL_00ab; + } + } + if (!string.IsNullOrEmpty(P_0.ExchangeId) || !(P_0.ConnectionId == ??.ConnectionId)) + { + return string.IsNullOrEmpty(P_0.ConnectionId); + } + } + goto IL_00ab; + } + return false; + IL_00ab: + return true; + } + } + + [CompilerGenerated] + private EventHandler ??; + + private readonly IDictionary ??; + + private readonly ? ??; + + public IList Settings + { + get + { + return this.Select((CustomSessionsAssignment P_0) => new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings)).Cast().ToList(); + } + set + { + foreach (SettingItem item in value) + { + if (item.Value is IList settings) + { + CustomSessionsAssignment assignment = new CustomSessionsAssignment + { + Settings = settings + }; + Add(assignment); + } + } + } + } + + public event EventHandler Updated + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public CustomSessionsAssignmentManager() + { + ?? = new Dictionary(); + ?? = new ?(); + } + + public void Add(CustomSessionsAssignment assignment) + { + ??.Add(assignment.UniqueId, assignment); + ?(assignment, EntityLifecycle.Created); + } + + public void Edit(string assignmentId, CustomSessionsAssignment newAssignment) + { + if (??.TryGetValue(assignmentId, out var value)) + { + value.?(newAssignment); + ?(value, EntityLifecycle.Changed); + } + } + + public void Delete(string assignmentId) + { + if (??.TryGetValue(assignmentId, out var value)) + { + ??.Remove(assignmentId); + ?(value, EntityLifecycle.Removed); + } + } + + public bool TryGetSessionsContainer(Symbol symbol, out CustomSessionsContainer container) + { + container = null; + List list = this.ToList(); + list.Sort(??); + container = list.FirstOrDefault(delegate(CustomSessionsAssignment P_0) + { + if (!P_0.IsActive) + { + return false; + } + if (!(P_0.SymbolComplexId == symbol.ComplexId)) + { + if (string.IsNullOrEmpty(P_0.SymbolId)) + { + ExchangeComplexIdentifier exchangeComplexId = P_0.ExchangeComplexId; + ExchangeComplexIdentifier? obj = symbol.Exchange?.ComplexId; + if (exchangeComplexId == obj) + { + goto IL_00ab; + } + } + if (!string.IsNullOrEmpty(P_0.ExchangeId) || !(P_0.ConnectionId == symbol.ConnectionId)) + { + return string.IsNullOrEmpty(P_0.ConnectionId); + } + } + goto IL_00ab; + IL_00ab: + return true; + })?.SessionsContainer; + return container != null; + } + + private void ?(CustomSessionsAssignment P_0, EntityLifecycle P_1) + { + ???.InvokeSafely(this, new CustomSessionEventArgs + { + Assignment = P_0, + Lifecycle = P_1 + }); + } + + public IEnumerator GetEnumerator() + { + return ??.Values.GetEnumerator(); + } + + private IEnumerator ?() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } + public class CustomSessionsContainer : ISessionsContainer, ICustomizable, IComparable, IComparable, IMessageBuilder + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func, SessionsSet> ??; + + internal bool ?(CustomSession P_0) + { + return P_0.IsActive; + } + + internal SettingItemGroup ?(CustomSession P_0) + { + return new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings); + } + + internal SettingItemGroup ?(CustomHoliday P_0) + { + return new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings); + } + + internal HolidayInfo ?(CustomHoliday P_0) + { + return new HolidayInfo + { + Name = P_0.Name, + Date = P_0.Date + }; + } + + internal int ?(CustomSession P_0) + { + return ((IStructuralEquatable)P_0.Days.Select((DayOfWeek result) => (int)result).ToArray()).GetHashCode((IEqualityComparer)EqualityComparer.Default); + } + + internal int ?(DayOfWeek P_0) + { + return (int)P_0; + } + + internal SessionsSet ?(IGrouping P_0) + { + return new SessionsSet + { + Days = P_0.FirstOrDefault().Days, + Sessions = P_0.Select((CustomSession customSession) => new Session(customSession.Name, customSession.OpenTime, customSession.CloseTime, customSession.Type)).ToArray() + }; + } + + internal Session ?(CustomSession P_0) + { + return new Session(P_0.Name, P_0.OpenTime, P_0.CloseTime, P_0.Type); + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + public DayOfWeek ??; + + internal bool ?(CustomHoliday P_0) + { + return P_0.Date.Date == ??.Date; + } + + internal bool ?(CustomSession P_0) + { + if (P_0.IsActive) + { + return P_0.Days.Contains(??); + } + return false; + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private TimeZone ??; + + [CompilerGenerated] + private CustomSession[] ??; + + [CompilerGenerated] + private CustomHoliday[] ??; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public TimeZone TimeZone + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeZone; + } + } + + public CustomSession[] Sessions + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + public ISession[] ActiveSessions => Sessions.Where((CustomSession P_0) => P_0.IsActive).Cast().ToArray(); + + public CustomHoliday[] Holidays + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + TimeZoneInfo ISessionsContainer.TimeZone + { + get + { + if (!TimeZone.IsEmpty) + { + return TimeZone.TimeZoneInfo; + } + return null; + } + } + + public IList Settings + { + get + { + List list = new List(); + list.AddRange(new SettingItem[4] + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id), + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name), + new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TimeZone.TimeZoneInfo.Id), + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TimeZone.Type) + }), + new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Sessions.Select((CustomSession P_0) => new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings)).Cast().ToList()) + }); + if (Holidays != null) + { + list.Add(new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Holidays?.Select((CustomHoliday P_0) => new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings)).Cast().ToList())); + } + return list; + } + set + { + Id = value.GetValueOrDefault(Id, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Name = value.GetValueOrDefault(Name, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (value.TryGetValue>(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value2)) + { + TimeZoneType value3 = value2.GetValue(new string[1] { 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() }); + TimeZoneInfo timeZoneInfo = null; + if (value3 != TimeZoneType.Local) + { + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(value2.GetValue(new string[1] { 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() })); + } + TimeZone = new TimeZone(value3, timeZoneInfo); + } + if (value.TryGetValue>(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value4)) + { + List list = new List(); + foreach (SettingItem item2 in value4) + { + if (item2.Value is IList settings) + { + CustomSession customSession = new CustomSession + { + Settings = settings + }; + customSession.RecalculateOpenCloseTime(TimeZone.TimeZoneInfo); + list.Add(customSession); + } + } + Sessions = list.ToArray(); + } + if (!value.TryGetValue>(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value5)) + { + return; + } + List list2 = new List(); + foreach (SettingItem item3 in value5) + { + if (item3.Value is IList settings2) + { + CustomHoliday item = new CustomHoliday + { + Settings = settings2 + }; + list2.Add(item); + } + } + Holidays = list2.ToArray(); + } + } + + internal CustomSessionsContainer() + { + } + + public CustomSessionsContainer(string name, TimeZone? timeZone = null, CustomSession[] sessions = null, CustomHoliday[] holidays = null) + { + Id = Guid.NewGuid().ToShortString(); + Name = name; + TimeZone = timeZone ?? Core.Instance.TimeUtils.SelectedTimeZone; + Sessions = sessions ?? Array.Empty(); + Holidays = holidays ?? Array.Empty(); + } + + internal void ?(CustomSessionsContainer P_0) + { + Name = P_0.Name; + TimeZone = P_0.TimeZone; + Sessions = P_0.Sessions ?? Array.Empty(); + Holidays = P_0.Holidays ?? Array.Empty(); + } + + public ISession[] GetSessionsForDate(DateTime dateTime) + { + DateTime ?? = TimeZoneInfo.ConvertTimeFromUtc(dateTime, TimeZone.TimeZoneInfo); + if (Holidays?.FirstOrDefault((CustomHoliday P_0) => P_0.Date.Date == ??.Date) != null) + { + return Array.Empty(); + } + DayOfWeek ?? = ??.DayOfWeek; + return Sessions.Where((CustomSession P_0) => P_0.IsActive && P_0.Days.Contains(??)).Cast().ToArray(); + } + + public int CompareTo(CustomSessionsContainer other) + { + return string.Compare(Name, other.Name, StringComparison.Ordinal); + } + + public int CompareTo(object obj) + { + if (!(obj is CustomSessionsContainer other)) + { + return 0; + } + return CompareTo(other); + } + + public override string ToString() + { + return Name; + } + + public MessageSessionsContainer BuildMessage() + { + return new MessageSessionsContainer + { + Id = Id, + Name = Name, + Description = string.Empty, + Holidays = Holidays?.Select((CustomHoliday P_0) => new HolidayInfo + { + Name = P_0.Name, + Date = P_0.Date + }).ToArray(), + SessionsSets = (from P_0 in Sessions?.GroupBy((CustomSession P_0) => ((IStructuralEquatable)P_0.Days.Select((DayOfWeek result) => (int)result).ToArray()).GetHashCode((IEqualityComparer)EqualityComparer.Default)) + select new SessionsSet + { + Days = P_0.FirstOrDefault().Days, + Sessions = P_0.Select((CustomSession customSession) => new Session(customSession.Name, customSession.OpenTime, customSession.CloseTime, customSession.Type)).ToArray() + }).ToArray() + }; + } + } + public class CustomSessionsManager : IEnumerable, IEnumerable, ICustomizable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SettingItemGroup ?(CustomSessionsContainer P_0) + { + return new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings); + } + } + + [CompilerGenerated] + private readonly CustomSessionsAssignmentManager ??; + + [CompilerGenerated] + private EventHandler ??; + + private readonly IDictionary ??; + + public CustomSessionsAssignmentManager Assignments + { + [CompilerGenerated] + get + { + return ??; + } + } + + public CustomSessionsContainer this[string id] + { + get + { + if (!string.IsNullOrEmpty(id) && ??.TryGetValue(id, out var value)) + { + return value; + } + return null; + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), this.Select((CustomSessionsContainer P_0) => new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Settings)).Cast().ToList()), + new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Assignments.Settings) + }; + } + set + { + if (value.TryGetValue>(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value2)) + { + ??.Clear(); + foreach (SettingItem item in value2) + { + if (item.Value is IList settings) + { + CustomSessionsContainer customSessionsContainer = new CustomSessionsContainer + { + Settings = settings + }; + ??.Add(customSessionsContainer.Id, customSessionsContainer); + } + } + } + if (value.TryGetValue>(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value3)) + { + Assignments.Settings = value3; + } + } + } + + public event EventHandler Updated + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + internal CustomSessionsManager() + { + ?? = new CustomSessionsAssignmentManager(); + ?? = new Dictionary(); + } + + public void Add(CustomSessionsContainer container) + { + ??.Add(container.Id, container); + ?(container, EntityLifecycle.Created); + } + + public void Edit(string containerId, CustomSessionsContainer newContainer) + { + if (??.TryGetValue(containerId, out var value)) + { + value.?(newContainer); + ?(value, EntityLifecycle.Changed); + } + } + + public void Delete(string containerId) + { + if (??.TryGetValue(containerId, out var value)) + { + ??.Remove(containerId); + ?(value, EntityLifecycle.Removed); + } + } + + private void ?(CustomSessionsContainer P_0, EntityLifecycle P_1) + { + ???.InvokeSafely(this, new CustomSessionEventArgs + { + Container = P_0, + Lifecycle = P_1 + }); + } + + public IEnumerator GetEnumerator() + { + return ??.Values.GetEnumerator(); + } + + private IEnumerator ?() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } + public enum TimeScaleType + { + Linear, + NonLinear + } + public enum BarCreationBehavior + { + Realtime, + Deferred + } + [Published] + public abstract class HistoryAggregation : ICustomizable, ICloneable, IComparable, IEquatable + { + public const string TICK = "Tick"; + + public const string TICK_BARS = "Tick bars"; + + public const string TIME = "Time"; + + public const string RENKO = "Renko"; + + public const string HEIKIN_ASHI = "Heikin Ashi"; + + public const string RANGE_BARS = "Range bars"; + + public const string POINTS_AND_FIGURES = "Points & Figures"; + + public const string KAGI = "Kagi"; + + public const string LINE_BREAK = "Line Break"; + + public const string VOLUME = "Volume"; + + public const string REVERSAL = "Reversal"; + + public const string POWER_TRADES = "Power Trades"; + + public const string VWAP = "VWAP"; + + public const string LEVEL2 = "Level2"; + + public const string DOM_BY_TICKS_COUNT = "DOM by ticks count"; + + public const string DOM_BY_TIME = "DOM by time"; + + public const string DOM_AGGREGATED = "Aggregated DOM"; + + public const string DELTA_BARS = "Delta bars"; + + public const string TICK_LAST_AGGREGATED = "Aggregated ticks (Last)"; + + public const string PRICE_CHANGES_COUNT_BARS = "Price changes count bars"; + + public const string TIME_STATISTICS = "Time statistics"; + + public const string VOLUME_PROFILE = "Volume profile"; + + public const string SETTINGS_AGGREGATION_PERIOD = "Period"; + + public const string SETTINGS_AGGREGATION_HISTORY_TYPE = "History type"; + + [CompilerGenerated] + private Type ??; + + private static readonly ListEqualityComparer ?? = new ListEqualityComparer(EqualityComparer.Default); + + public abstract string Name { get; } + + public virtual string Title => Name; + + [NotPublished] + public virtual TimeScaleType TimeScaleType => TimeScaleType.NonLinear; + + [NotPublished] + public virtual BarCreationBehavior BarCreationBehavior => BarCreationBehavior.Realtime; + + public virtual bool IsWaitingFirstQuoteRequired => false; + + public virtual IList Settings + { + get + { + return new List(); + } + set + { + } + } + + internal Type HistoryProcessorType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = type; + } + } + + public virtual Period DefaultRange => Period.DAY1; + + [NotPublished] + [Obsolete("This property is retained for compatibility - will be removed in the future. Use casting to a specific type of aggregation and refer to the properties of the aggregation directly")] + public abstract Period GetPeriod { get; } + + [NotPublished] + [Obsolete("This property is retained for compatibility - will be removed in the future. Use casting to a specific type of aggregation and refer to the properties of the aggregation directly")] + public abstract HistoryType GetHistoryType { get; } + + protected HistoryAggregation() + { + } + + protected HistoryAggregation(HistoryAggregation _) + { + } + + [NotPublished] + public abstract object Clone(); + + [NotPublished] + public int CompareTo(object obj) + { + return (obj as HistoryAggregation).Name.CompareTo(Name); + } + + /// + /// Override to change string representation of aggregation + /// + [NotPublished] + public override string ToString() + { + return Name; + } + + [NotPublished] + public virtual string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTime(dt); + } + + public abstract HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata); + + public bool Equals(HistoryAggregation other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Name == other.Name) + { + return ??.Equals(Settings, other.Settings); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((HistoryAggregation)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, ??.GetHashCode(Settings)); + } + } + [Published] + public interface IHistoryAggregationHistoryTypeSupport + { + HistoryType HistoryType { get; set; } + } + public sealed class HistoryAggregationDeltaBars : HistoryAggregation + { + public const string SETTINGS_AGGREGATION_VOLUME_VALUE = "Delta value"; + + [CompilerGenerated] + private int ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int DeltaValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public override IList Settings + { + get + { + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), DeltaValue) + { + Minimum = 1, + Increment = 1, + SortIndex = 10 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + DeltaValue = (int)item.Value; + } + } + } + } + + public override Period GetPeriod => Period.TICK1; + + public override HistoryType GetHistoryType => HistoryType.Last; + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + public HistoryAggregationDeltaBars(int deltaValue) + { + DeltaValue = deltaValue; + } + + private HistoryAggregationDeltaBars(HistoryAggregationDeltaBars P_0) + : base(P_0) + { + DeltaValue = P_0.DeltaValue; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 2); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(DeltaValue); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationDeltaBars(this); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + return new HistoryAggregationTick(HistoryType.Last); + } + } + public sealed class HistoryAggregationDomAggregated : HistoryAggregation + { + private const string ?? = "Price levels limit"; + + [CompilerGenerated] + private Period ??; + + [CompilerGenerated] + private int ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = period; + } + } + + public int PriceLevelsLimit + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public override IList Settings + { + get + { + return new List + { + new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Period) + { + SortIndex = 10, + Description = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PriceLevelsLimit) + { + SortIndex = 11, + Minimum = 0, + Maximum = 1000 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + PriceLevelsLimit = (int)item.Value; + } + } + else + { + Period = (Period)item.Value; + } + } + } + } + + [NotPublished] + public override Period GetPeriod => Period; + + [NotPublished] + public override HistoryType GetHistoryType + { + get + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public HistoryAggregationDomAggregated(Period period) + { + Period = period; + } + + protected HistoryAggregationDomAggregated(HistoryAggregationDomAggregated aggregation) + : base(aggregation) + { + Period = aggregation.Period; + PriceLevelsLimit = aggregation.PriceLevelsLimit; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationDomAggregated(this); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Period.Format()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PriceLevelsLimit); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (!metadata.AllowedAggregations.Contains(Name)) + { + return null; + } + return this; + } + } + public sealed class HistoryAggregationDomByTime : HistoryAggregation + { + [CompilerGenerated] + private Period ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = period; + } + } + + public override IList Settings + { + get + { + List list = new List(); + list.Add(new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Period) + { + SortIndex = 10, + ExcludedPeriods = new BasePeriod[1], + Description = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + return list; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + Period = (Period)item.Value; + } + } + } + } + + [NotPublished] + public override Period GetPeriod => Period; + + [NotPublished] + public override HistoryType GetHistoryType + { + get + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public HistoryAggregationDomByTime(Period period) + { + Period = period; + } + + protected HistoryAggregationDomByTime(HistoryAggregationDomByTime aggregation) + : base(aggregation) + { + Period = aggregation.Period; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationDomByTime(this); + } + + [NotPublished] + public override string ToString() + { + return Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Period.Format(); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (!metadata.AllowedAggregations.Contains(Name)) + { + return null; + } + return this; + } + } + public sealed class HistoryAggregationDomByUpdatesCount : HistoryAggregation + { + private const string ?? = "Ticks count"; + + [CompilerGenerated] + private int ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int TicksCount + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public override IList Settings + { + get + { + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TicksCount) + { + Minimum = 1, + Increment = 1, + SortIndex = 10 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + TicksCount = (int)item.Value; + } + } + } + } + + [NotPublished] + public override Period GetPeriod => new Period(BasePeriod.Tick, TicksCount); + + [NotPublished] + public override HistoryType GetHistoryType + { + get + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public HistoryAggregationDomByUpdatesCount(int ticksCount) + { + TicksCount = ticksCount; + } + + private HistoryAggregationDomByUpdatesCount(HistoryAggregationDomByUpdatesCount P_0) + : base(P_0) + { + TicksCount = P_0.TicksCount; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationDomByUpdatesCount(this); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TicksCount); + defaultInterpolatedStringHandler.AppendFormatted(Period.BasePeriodToShortString(BasePeriod.Tick)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (!metadata.AllowedAggregations.Contains(Name)) + { + return null; + } + return this; + } + } + [Published] + public sealed class HistoryAggregationHeikenAshi : HistoryAggregation, IHistoryAggregationHistoryTypeSupport + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SelectItem ?(HeikenAshiSource P_0) + { + return new SelectItem(P_0.ToString(), P_0); + } + } + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private HeikenAshiSource ??; + + [CompilerGenerated] + private HistoryType ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HeikenAshiSource Source + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [NotPublished] + public override TimeScaleType TimeScaleType + { + get + { + HeikenAshiSource source = Source; + if (source == HeikenAshiSource.Tick || source == HeikenAshiSource.Volume) + { + return TimeScaleType.NonLinear; + } + return TimeScaleType.Linear; + } + } + + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + List list = (from HeikenAshiSource P_0 in Enum.GetValues(typeof(HeikenAshiSource)) + select new SelectItem(P_0.ToString(), P_0)).ToList(); + List list2 = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 5), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 2) + }; + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Value) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 1 + }, + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => P_0.Value.Equals(Source)), list) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list2.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == (int)HistoryType) ?? list2.FirstOrDefault(), list2) + { + SortIndex = 11 + } + }; + } + set + { + Value = value.GetValueOrDefault(Value, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Source = value.GetValueOrDefault(Source, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + HistoryType = value.GetValueOrDefault(HistoryType, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [NotPublished] + public override Period GetPeriod + { + get + { + if (Source != HeikenAshiSource.Volume) + { + return new Period((BasePeriod)Source, Value); + } + return Period.TICK1; + } + } + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType; + + [NotPublished] + public override Period DefaultRange + { + get + { + if (Source == HeikenAshiSource.Volume || Source == HeikenAshiSource.Tick) + { + return Period.HOUR1; + } + if (Source <= HeikenAshiSource.Minute) + { + return Period.DAY1; + } + if (Source <= HeikenAshiSource.Day) + { + return Period.MONTH1; + } + return new Period(BasePeriod.Year, 10); + } + } + + public HistoryAggregationHeikenAshi(HeikenAshiSource source, int value, HistoryType historyType) + { + Source = source; + Value = value; + HistoryType = historyType; + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return GetPeriod.Format(dt); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Value); + defaultInterpolatedStringHandler.AppendFormatted((Source == HeikenAshiSource.Volume) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() : Period.BasePeriodToShortString((BasePeriod)Source)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected HistoryAggregationHeikenAshi(HistoryAggregationHeikenAshi aggregation) + : base(aggregation) + { + Source = aggregation.Source; + Value = aggregation.Value; + HistoryType = aggregation.HistoryType; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationHeikenAshi(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + return (Source switch + { + HeikenAshiSource.Volume => new HistoryAggregationVolume(Value), + HeikenAshiSource.Tick => new HistoryAggregationTickBars(Value, HistoryType), + _ => new HistoryAggregationTime(new Period((BasePeriod)Source, Value), HistoryType), + }).GetAggregationToDirectDownload(metadata); + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return P_0.Value.Equals(Source); + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)HistoryType; + } + } + public enum HeikenAshiSource + { + [EnumMember] + Tick, + [EnumMember] + Second, + [EnumMember] + Minute, + [EnumMember] + Hour, + [EnumMember] + Day, + [EnumMember] + Week, + [EnumMember] + Month, + [EnumMember] + Year, + [EnumMember] + Volume + } + [Published] + public sealed class HistoryAggregationKagi : HistoryAggregationTime + { + public const string SETTINGS_AGGREGATION_REVERSAL = "Reversal"; + + [CompilerGenerated] + private int ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int Reversal + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [NotPublished] + public override TimeScaleType TimeScaleType => TimeScaleType.NonLinear; + + [NotPublished] + public override BarCreationBehavior BarCreationBehavior => BarCreationBehavior.Deferred; + + public override IList Settings + { + get + { + IList settings = base.Settings; + if (settings.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) is SettingItemPeriod settingItemPeriod) + { + settingItemPeriod.ExcludedPeriods = new BasePeriod[2] + { + BasePeriod.Month, + BasePeriod.Year + }; + } + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Reversal) + { + Minimum = 1, + SortIndex = 20 + }); + return settings; + } + set + { + if (value == null) + { + return; + } + base.Settings = value; + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Reversal = (int)item.Value; + } + } + } + } + + public HistoryAggregationKagi(Period period, HistoryType historyType, int reversal) + : base(period, historyType) + { + Reversal = reversal; + } + + private HistoryAggregationKagi(HistoryAggregationKagi P_0) + : base(P_0) + { + Reversal = P_0.Reversal; + } + + public override object Clone() + { + return new HistoryAggregationKagi(this); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Reversal); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Period.Format()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public sealed class HistoryAggregationLevel2 : HistoryAggregation + { + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + [NotPublished] + public override Period GetPeriod => Period.TICK1; + + [NotPublished] + public override HistoryType GetHistoryType + { + get + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public HistoryAggregationLevel2() + { + } + + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + private HistoryAggregationLevel2(HistoryAggregationLevel2 P_0) + : base(P_0) + { + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationLevel2(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (!metadata.AllowedAggregations.Contains(Name)) + { + return null; + } + return this; + } + } + [Published] + public sealed class HistoryAggregationLineBreak : HistoryAggregationTime + { + public const string SETTINGS_AGGREGATION_LINE_BREAK = "Line break"; + + [CompilerGenerated] + private int ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int LineBreak + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [NotPublished] + public override TimeScaleType TimeScaleType => TimeScaleType.NonLinear; + + public override IList Settings + { + get + { + IList settings = base.Settings; + if (settings.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) is SettingItemPeriod settingItemPeriod) + { + settingItemPeriod.ExcludedPeriods = new BasePeriod[2] + { + BasePeriod.Month, + BasePeriod.Year + }; + } + SettingItemInteger item = new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LineBreak) + { + Minimum = 1, + Maximum = 100, + SortIndex = 20 + }; + settings.Add(item); + return settings; + } + set + { + if (value == null) + { + return; + } + base.Settings = value; + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + LineBreak = (int)item.Value; + } + } + } + } + + public override Period GetPeriod => base.Period; + + public HistoryAggregationLineBreak(Period period, HistoryType historyType, int lineBreak) + : base(period, historyType) + { + LineBreak = lineBreak; + } + + private HistoryAggregationLineBreak(HistoryAggregationLineBreak P_0) + : base(P_0) + { + LineBreak = P_0.LineBreak; + } + + public override object Clone() + { + return new HistoryAggregationLineBreak(this); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(LineBreak); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Period.Format()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public sealed class HistoryAggregationManager + { + private const string ? = "HistoryProcessors"; + + private Dictionary ?; + + public HistoryAggregation[] All => ?.Values.ToArray(); + + public HistoryAggregation this[string aggregatorName] + { + get + { + if (?.TryGetValue(aggregatorName, out var value)) + { + return value; + } + return null; + } + } + + internal HistoryAggregationManager() + { + ? = new Dictionary(); + } + + internal void ?() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), LoggingLevel.Verbose); + List list = AssemblyLoader.LoadTypes(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), typeof(IHistoryProcessor), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), SearchOption.AllDirectories); + if (list == null) + { + return; + } + foreach (TypeWrapper item in list) + { + Type type = item; + try + { + MethodInfo method = type.GetMethod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), BindingFlags.Static | BindingFlags.Public); + if (method == null) + { + Core.Instance.Loggers.Log(type.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), LoggingLevel.Verbose); + continue; + } + if (!(method.Invoke(null, null) is HistoryAggregation historyAggregation)) + { + Core.Instance.Loggers.Log(type.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), LoggingLevel.Verbose); + continue; + } + if (?.ContainsKey(historyAggregation.Name)) + { + Core.Instance.Loggers.Log(type.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), LoggingLevel.Verbose); + continue; + } + historyAggregation.HistoryProcessorType = type; + ?.Add(historyAggregation.Name, historyAggregation); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), LoggingLevel.Verbose); + } + + public IHistoryProcessor CreateHistoryProcessor(HistoryRequestParameters parameter) + { + if (parameter == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (parameter.Aggregation == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + HistoryAggregation historyAggregation = this[parameter.Aggregation.Name]; + if (historyAggregation == null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + parameter.Aggregation.Name); + } + try + { + IHistoryProcessor obj = Activator.CreateInstance(historyAggregation.HistoryProcessorType) as IHistoryProcessor; + obj?.Initialize(parameter.Copy); + return obj; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return null; + } + + internal void ?() + { + if (? != null) + { + ?.Clear(); + ? = null; + } + } + } + [Published] + public sealed class HistoryAggregationPointsAndFigures : HistoryAggregationTime + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private PointsAndFiguresStyle ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int BoxSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public int Reversal + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public PointsAndFiguresStyle Style + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = pointsAndFiguresStyle; + } + } + + public override IList Settings + { + get + { + List list = new List(); + SelectItem value = null; + foreach (PointsAndFiguresStyle value2 in Enum.GetValues(typeof(PointsAndFiguresStyle))) + { + SelectItem selectItem = new SelectItem(loc._(value2.GetDescription(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), (int)value2); + list.Add(selectItem); + if (Style == value2) + { + value = selectItem; + } + } + IList settings = base.Settings; + if (settings.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) is SettingItemPeriod settingItemPeriod) + { + settingItemPeriod.ExcludedPeriods = null; + } + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BoxSize, 10) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 1, + Maximum = int.MaxValue + }); + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Reversal, 20) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 1, + Maximum = int.MaxValue + }); + settings.Add(new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value, list, 30) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }); + return settings; + } + set + { + base.Settings = value; + SettingItem itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null) + { + BoxSize = (int)itemByName.Value; + } + itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null) + { + Reversal = (int)itemByName.Value; + } + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value is SelectItem selectItem) + { + Style = (PointsAndFiguresStyle)(int)(object)selectItem.Value; + } + } + } + + [NotPublished] + public override TimeScaleType TimeScaleType => TimeScaleType.NonLinear; + + [NotPublished] + public override BarCreationBehavior BarCreationBehavior => BarCreationBehavior.Deferred; + + public HistoryAggregationPointsAndFigures(Period period, HistoryType historyType, int boxSize, int reversal, PointsAndFiguresStyle style) + : base(period, historyType) + { + BoxSize = boxSize; + Reversal = reversal; + Style = style; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(9, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Reversal); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(BoxSize); + defaultInterpolatedStringHandler.AppendFormatted((Style == PointsAndFiguresStyle.Classic) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Period.Format()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected HistoryAggregationPointsAndFigures(HistoryAggregationPointsAndFigures aggregation) + : base(aggregation) + { + BoxSize = aggregation.BoxSize; + Reversal = aggregation.Reversal; + Style = aggregation.Style; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationPointsAndFigures(this); + } + } + public sealed class HistoryAggregationPowerTrades : HistoryAggregation + { + [CompilerGenerated] + private readonly HistoryAggregationPowerTradesParameters ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public HistoryAggregationPowerTradesParameters Parameters + { + [CompilerGenerated] + get + { + return ??; + } + } + + public override Period GetPeriod => Period.TICK1; + + public override HistoryType GetHistoryType => HistoryType.Last; + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + public override IList Settings + { + get + { + return Parameters?.Settings ?? new List(); + } + set + { + if (Parameters != null) + { + Parameters.Settings = value; + } + } + } + + public HistoryAggregationPowerTrades() + { + ?? = new HistoryAggregationPowerTradesParameters(); + } + + public HistoryAggregationPowerTrades(HistoryAggregationPowerTradesParameters parameters) + : this() + { + ?? = parameters; + } + + protected HistoryAggregationPowerTrades(HistoryAggregationPowerTrades aggregation) + : base(aggregation) + { + ?? = aggregation.Parameters?.Clone() as HistoryAggregationPowerTradesParameters; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationPowerTrades(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + return new HistoryAggregationTick(HistoryType.Last); + } + } + public sealed class HistoryAggregationPriceChangesCountBars : HistoryAggregation, IHistoryAggregationHistoryTypeSupport + { + private const string ?? = "Ticks count"; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private HistoryType ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int PriceChangesCount + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + List list = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 5), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0) + }; + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PriceChangesCount) + { + Minimum = 1, + Increment = 1, + SortIndex = 10 + }, + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == (int)HistoryType) ?? list.FirstOrDefault(), list) + { + SortIndex = 11 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + HistoryType = (HistoryType)(int)(object)((SelectItem)item.Value).Value; + } + } + else + { + PriceChangesCount = (int)item.Value; + } + } + } + } + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + [NotPublished] + public override Period GetPeriod => Period.TICK1; + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType; + + public HistoryAggregationPriceChangesCountBars(int priceChangesCount, HistoryType historyType) + { + PriceChangesCount = priceChangesCount; + HistoryType = historyType; + } + + public HistoryAggregationPriceChangesCountBars(HistoryAggregationPriceChangesCountBars aggregation) + : base(aggregation) + { + PriceChangesCount = aggregation.PriceChangesCount; + HistoryType = aggregation.HistoryType; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PriceChangesCount); + defaultInterpolatedStringHandler.AppendFormatted(Period.BasePeriodToShortString(BasePeriod.Tick)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + if (PriceChangesCount <= 1) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + return Core.Instance.TimeUtils.GetFormatedDateTime(dt); + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationPriceChangesCountBars(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (!metadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + return null; + } + HistoryType value = ((HistoryType == HistoryType.Ask || HistoryType == HistoryType.Bid) ? HistoryType.BidAsk : HistoryType); + if (!metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(value)) + { + return null; + } + return new HistoryAggregationTick(HistoryType); + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)HistoryType; + } + } + [Published] + public sealed class HistoryAggregationRangeBars : HistoryAggregation, IHistoryAggregationHistoryTypeSupport + { + public const string SETTINGS_AGGREGATION_RANGE_BARS = "Range bars"; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private HistoryType ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int RangeBars + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + List list = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 5), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 2) + }; + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), RangeBars) + { + Minimum = 1, + Increment = 1, + SortIndex = 10, + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == (int)HistoryType) ?? list.FirstOrDefault(), list) + { + SortIndex = 11 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + HistoryType = (HistoryType)(int)(object)((SelectItem)item.Value).Value; + } + } + else + { + RangeBars = (int)item.Value; + } + } + } + } + + public override Period GetPeriod => Period.TICK1; + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType; + + public HistoryAggregationRangeBars(int rangeBars, HistoryType historyType) + { + RangeBars = rangeBars; + HistoryType = historyType; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(RangeBars); + defaultInterpolatedStringHandler.AppendFormatted(Period.BasePeriodToShortString(BasePeriod.Tick)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private HistoryAggregationRangeBars(HistoryAggregationRangeBars P_0) + : base(P_0) + { + RangeBars = P_0.RangeBars; + HistoryType = P_0.HistoryType; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationRangeBars(this); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + HistoryType historyType = ((HistoryType == HistoryType.Ask || HistoryType == HistoryType.Bid) ? HistoryType.BidAsk : HistoryType); + if (!metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(historyType)) + { + return null; + } + return new HistoryAggregationTick(historyType); + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)HistoryType; + } + } + [Published] + public sealed class HistoryAggregationRenko : HistoryAggregationTime + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == 2; + } + + internal bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == 3; + } + } + + public const string SETTINGS_AGGREGATION_RENKO_BRICK_SIZE = "Brick size"; + + public const string SETTINGS_AGGREGATION_RENKO_STYLE = "Style"; + + public const string SETTINGS_AGGREGATION_RENKO_BUILD_CURRENT_BAR = "Build current bar"; + + public const string SETTINGS_AGGREGATION_RENKO_EXTENSION = "Extension, %"; + + public const string SETTINGS_AGGREGATION_RENKO_INVERSION = "Inversion, %"; + + public const string SETTINGS_AGGREGATION_RENKO_SHOW_WICKS = "Show wicks"; + + private const string ?? = "W"; + + private static readonly Dictionary ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private RenkoStyle ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int BrickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public RenkoStyle RenkoStyle + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = renkoStyle; + } + } + + public int Extension + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public int Inversion + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public bool ShowWicks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public bool BuildCurrentBar + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + private protected override IList SupportedHistoryTypes + { + get + { + IList supportedHistoryTypes = base.SupportedHistoryTypes; + supportedHistoryTypes.Add(HistoryType.BidAsk); + return supportedHistoryTypes; + } + } + + public override IList Settings + { + get + { + List list = new List + { + new SelectItem(RenkoStyle.Classic.ToString(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 2), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3) + }; + SettingItemRelationVisibility relation = new SettingItemRelationVisibility(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == 2), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == 3)); + IList settings = base.Settings; + if (settings.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) is SettingItemPeriod settingItemPeriod) + { + settingItemPeriod.ExcludedPeriods = null; + } + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BrickSize) + { + SortIndex = 20, + Minimum = 1, + Maximum = int.MaxValue, + Increment = 1 + }); + settings.Add(new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.GetItemByValue((int)RenkoStyle), list) + { + SortIndex = 30, + Description = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Extension) + { + Minimum = 1, + Maximum = 1000, + SortIndex = 40, + Relation = relation + }); + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Inversion) + { + Minimum = 1, + Maximum = 1000, + SortIndex = 50, + Relation = relation + }); + settings.Add(new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ShowWicks) + { + SortIndex = 60 + }); + settings.Add(new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BuildCurrentBar) + { + SortIndex = 70 + }); + return settings; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item == null) + { + continue; + } + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ShowWicks = (bool)item.Value; + } + } + else + { + BuildCurrentBar = (bool)item.Value; + } + } + else + { + Inversion = (int)item.Value; + } + } + else + { + Extension = (int)item.Value; + } + } + else + { + RenkoStyle = (RenkoStyle)(int)(object)((SelectItem)item.Value).Value; + } + } + else + { + BrickSize = (int)item.Value; + } + } + base.Settings = value; + } + } + + [NotPublished] + public override TimeScaleType TimeScaleType => TimeScaleType.NonLinear; + + [NotPublished] + public override BarCreationBehavior BarCreationBehavior => BarCreationBehavior.Deferred; + + static HistoryAggregationRenko() + { + ?? = new Dictionary + { + { + RenkoStyle.Classic, + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + { + RenkoStyle.HighLow, + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + { + RenkoStyle.AdvancedClassic, + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }, + { + RenkoStyle.AdvancedHighLow, + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + } + }; + } + + public HistoryAggregationRenko(Period period, HistoryType historyType, int brickSize, RenkoStyle renkoStyle, int extension = 100, int inversion = 100, bool showWicks = false, bool buildCurrentBar = true) + : base(period, historyType) + { + BrickSize = brickSize; + RenkoStyle = renkoStyle; + Extension = extension; + Inversion = inversion; + ShowWicks = showWicks; + BuildCurrentBar = buildCurrentBar; + } + + public HistoryAggregation GetBaseAggregation() + { + if (base.Period.BasePeriod == BasePeriod.Tick) + { + if (base.Period.PeriodMultiplier == 1) + { + return new HistoryAggregationTick(base.HistoryType); + } + if (base.Period.PeriodMultiplier > 1) + { + return new HistoryAggregationTickBars(base.Period.PeriodMultiplier, base.HistoryType); + } + } + return new HistoryAggregationTime(base.Period, base.HistoryType); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + HistoryAggregation baseAggregation = GetBaseAggregation(); + if (baseAggregation is HistoryAggregationTime && !metadata.AllowedHistoryTypesHistoryAggregationTime.Contains(base.HistoryType)) + { + return null; + } + return baseAggregation.GetAggregationToDirectDownload(metadata); + } + + private HistoryAggregationRenko(HistoryAggregationRenko P_0) + : base(P_0) + { + BrickSize = P_0.BrickSize; + RenkoStyle = P_0.RenkoStyle; + ShowWicks = P_0.ShowWicks; + BuildCurrentBar = P_0.BuildCurrentBar; + Extension = P_0.Extension; + Inversion = P_0.Inversion; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationRenko(this); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(5, 5); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(BrickSize); + defaultInterpolatedStringHandler.AppendFormatted(??[RenkoStyle]); + defaultInterpolatedStringHandler.AppendFormatted(ShowWicks ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : string.Empty); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Period.Format()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public sealed class HistoryAggregationReversal : HistoryAggregation + { + private const string ?? = "Length"; + + private const string ?? = "Reversal Length"; + + private const string ?? = "Calculation Type"; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private HistoryProcessorReversalCalculationType ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override IList Settings + { + get + { + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Length) + { + Minimum = 0, + Increment = 1, + SortIndex = 10 + }, + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ReversalLength) + { + Minimum = 1, + Increment = 1, + SortIndex = 10 + }, + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)CalculationType, new List + { + new SelectItem(loc._(HistoryProcessorReversalCalculationType.PreviousBar.GetDescription(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), 0), + new SelectItem(loc._(HistoryProcessorReversalCalculationType.Independent.GetDescription(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), 1) + }) + { + SortIndex = 10 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ReversalLength = (int)item.Value; + } + } + else + { + Length = (int)item.Value; + } + } + CalculationType = (HistoryProcessorReversalCalculationType)value.GetValueOrDefault((int)CalculationType, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public int Length + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public int ReversalLength + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public HistoryProcessorReversalCalculationType CalculationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = historyProcessorReversalCalculationType; + } + } + + public override Period GetPeriod => Period.TICK1; + + public override HistoryType GetHistoryType => HistoryType.Last; + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + public HistoryAggregationReversal(int length, int reversalLength, HistoryProcessorReversalCalculationType calculationType) + { + Length = length; + ReversalLength = reversalLength; + CalculationType = calculationType; + } + + private HistoryAggregationReversal(HistoryAggregationReversal P_0) + : base(P_0) + { + Length = P_0.Length; + ReversalLength = P_0.ReversalLength; + CalculationType = P_0.CalculationType; + } + + public HistoryAggregationReversal(int length, int reversalLength) + : this(length, reversalLength, HistoryProcessorReversalCalculationType.PreviousBar) + { + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(9, 4); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Length); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ReversalLength); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(CalculationType.GetDescription()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationReversal(this); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + return new HistoryAggregationTick(HistoryType.Last); + } + } + [Published] + public sealed class HistoryAggregationTick : HistoryAggregation, IHistoryAggregationHistoryTypeSupport + { + [CompilerGenerated] + private HistoryType ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + List list = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 4), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 5) + }; + return new List + { + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == (int)HistoryType) ?? list.FirstOrDefault(), list) + { + SortIndex = 11 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + HistoryType = (HistoryType)(int)(object)((SelectItem)item.Value).Value; + } + } + } + } + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + [NotPublished] + public override Period GetPeriod => Period.TICK1; + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType; + + public HistoryAggregationTick(HistoryType historyType) + { + HistoryType = historyType; + } + + public HistoryAggregationTick(HistoryAggregationTick aggregation) + : base(aggregation) + { + HistoryType = aggregation.HistoryType; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 2); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(HistoryType); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationTick(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (!metadata.AllowedAggregations.Contains(Name)) + { + return null; + } + if (!metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(HistoryType)) + { + return null; + } + return this; + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)HistoryType; + } + } + public sealed class HistoryAggregationTickBars : HistoryAggregation, IHistoryAggregationHistoryTypeSupport + { + private const string ?? = "Ticks count"; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private HistoryType ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public int TicksCount + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override bool IsWaitingFirstQuoteRequired => true; + + public override IList Settings + { + get + { + List list = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 5), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 2), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 4) + }; + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TicksCount) + { + Minimum = 1, + Increment = 1, + SortIndex = 10 + }, + new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == (int)HistoryType) ?? list.FirstOrDefault(), list) + { + SortIndex = 11 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + HistoryType = (HistoryType)(int)(object)((SelectItem)item.Value).Value; + } + } + else + { + TicksCount = (int)item.Value; + } + } + } + } + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + [NotPublished] + public override Period GetPeriod => new Period(BasePeriod.Tick, TicksCount); + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType; + + public HistoryAggregationTickBars(int ticksCount, HistoryType historyType) + { + TicksCount = ticksCount; + HistoryType = historyType; + } + + public HistoryAggregationTickBars(HistoryAggregationTickBars aggregation) + : base(aggregation) + { + TicksCount = aggregation.TicksCount; + HistoryType = aggregation.HistoryType; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 3); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TicksCount); + defaultInterpolatedStringHandler.AppendFormatted(Period.BasePeriodToShortString(BasePeriod.Tick)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + if (TicksCount <= 1) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + return Core.Instance.TimeUtils.GetFormatedDateTime(dt); + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationTickBars(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (metadata.AllowedAggregations.Contains(Name)) + { + return this; + } + HistoryType historyType = HistoryType; + if (!metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(historyType)) + { + return null; + } + return new HistoryAggregationTick(HistoryType); + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)HistoryType; + } + } + public sealed class HistoryAggregationTickLastAggregated : HistoryAggregation + { + [CompilerGenerated] + private TimeSpan ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override Period GetPeriod => Period.TICK1; + + public override HistoryType GetHistoryType => HistoryType.Last; + + public TimeSpan TimeDelay + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TimeDelay.TotalMilliseconds) + { + SortIndex = 10, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 1 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + TimeDelay = TimeSpan.FromMilliseconds((int)item.Value); + } + } + } + } + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + public HistoryAggregationTickLastAggregated() + { + TimeDelay = TimeSpan.FromMilliseconds(500.0); + } + + public HistoryAggregationTickLastAggregated(HistoryAggregationTickLastAggregated original) + { + TimeDelay = original.TimeDelay; + } + + public override object Clone() + { + return new HistoryAggregationTickLastAggregated(this); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + return new HistoryAggregationTick(HistoryType.Last); + } + } + [Published] + public class HistoryAggregationTime : HistoryAggregation, IHistoryAggregationHistoryTypeSupport + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SelectItem ?(HistoryType P_0) + { + return new SelectItem(P_0.GetDescription(), (int)P_0); + } + } + + [CompilerGenerated] + private Period ??; + + [CompilerGenerated] + private HistoryType ??; + + [CompilerGenerated] + private bool ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool UsePrevCloseAsOpenPriceBar + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + private protected virtual IList SupportedHistoryTypes => new List + { + HistoryType.Last, + HistoryType.Mark, + HistoryType.Bid, + HistoryType.Ask, + HistoryType.Midpoint + }; + + public override IList Settings + { + get + { + List list = SupportedHistoryTypes.Select((HistoryType P_0) => new SelectItem(P_0.GetDescription(), (int)P_0)).ToList(); + List list2 = new List(); + list2.Add(new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Period) + { + SortIndex = 10, + ExcludedPeriods = new BasePeriod[1], + Description = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + list2.Add(new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.FirstOrDefault((SelectItem P_0) => (int)(object)P_0.Value == (int)HistoryType) ?? list.FirstOrDefault(), list) + { + SortIndex = 11 + }); + return list2; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + string name = item.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + HistoryType = (HistoryType)(int)(object)((SelectItem)item.Value).Value; + } + } + else + { + Period = (Period)item.Value; + } + } + } + } + + [NotPublished] + public override Period GetPeriod => Period; + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType; + + [NotPublished] + public override TimeScaleType TimeScaleType => TimeScaleType.Linear; + + [NotPublished] + public override Period DefaultRange + { + get + { + if (Period.Ticks < 600000000) + { + return Period.DAY1; + } + if (Period.Ticks == 600000000) + { + return new Period(BasePeriod.Day, 3); + } + if (Period.Ticks <= 864000000000L) + { + return Period.MONTH1; + } + return new Period(BasePeriod.Year, 10); + } + } + + public HistoryAggregationTime(Period period, HistoryType historyType) + { + Period = period; + HistoryType = historyType; + } + + [NotPublished] + public override string ToString() + { + return Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Period.Format(); + } + + protected HistoryAggregationTime(HistoryAggregationTime aggregation) + : base(aggregation) + { + Period = aggregation.Period; + HistoryType = aggregation.HistoryType; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationTime(this); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Period.Format(dt); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (metadata.AllowedAggregations.Contains(Name) && metadata.AllowedHistoryTypesHistoryAggregationTime.Contains(HistoryType)) + { + if (metadata.AllowedPeriodsHistoryAggregationTime.Contains(Period)) + { + return this; + } + if (metadata.AllowedBasePeriodsHistoryAggregationTime.Contains(Period.BasePeriod)) + { + return new HistoryAggregationTime(Period, HistoryType); + } + Period period = metadata.AllowedPeriodsHistoryAggregationTime.FirstOrDefault((Period P_0) => Period.Ticks % P_0.Ticks == 0); + if (period != default(Period)) + { + return new HistoryAggregationTime(period, HistoryType); + } + } + if (!metadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + return null; + } + HistoryType historyType = ((HistoryType == HistoryType.Ask || HistoryType == HistoryType.Bid) ? HistoryType.BidAsk : HistoryType); + if (!metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(historyType)) + { + return null; + } + return new HistoryAggregationTick(historyType); + } + + [CompilerGenerated] + private bool ?(SelectItem P_0) + { + return (int)(object)P_0.Value == (int)HistoryType; + } + + [CompilerGenerated] + private bool ?(Period P_0) + { + return Period.Ticks % P_0.Ticks == 0; + } + } + public sealed class HistoryAggregationTimeStatistics : HistoryAggregation + { + [CompilerGenerated] + private Period ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = period; + } + } + + public override IList Settings + { + get + { + List list = new List(); + list.Add(new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Period) + { + SortIndex = 10, + ExcludedPeriods = new BasePeriod[1], + Description = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + return list; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + Period = (Period)item.Value; + } + } + } + } + + [NotPublished] + public override Period GetPeriod => Period; + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType.Last; + + public HistoryAggregationTimeStatistics(Period period) + { + Period = period; + } + + protected HistoryAggregationTimeStatistics(HistoryAggregationTimeStatistics aggregation) + : base(aggregation) + { + Period = aggregation.Period; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationTimeStatistics(this); + } + + [NotPublished] + public override string ToString() + { + return Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Period.Format(); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (metadata.AllowedAggregations.Contains(Name) && (metadata.AllowedBasePeriodsHistoryAggregationTimeStatistics.Contains(Period.BasePeriod) || metadata.AllowedPeriodsHistoryAggregationTimeStatistics.Contains(Period))) + { + return this; + } + if (metadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && (metadata.AllowedBasePeriodsHistoryAggregationTimeStatistics.Contains(Period.BasePeriod) || metadata.AllowedPeriodsHistoryAggregationTimeStatistics.Contains(Period))) + { + return new HistoryAggregationVolumeProfile(Period); + } + if (metadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(HistoryType.Last)) + { + return new HistoryAggregationTick(HistoryType.Last); + } + return null; + } + } + public sealed class HistoryAggregationVolume : HistoryAggregation + { + public const string SETTINGS_AGGREGATION_VOLUME_VALUE = "Volume value"; + + [CompilerGenerated] + private int ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + + public int VolumeValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public override IList Settings + { + get + { + return new List + { + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), VolumeValue) + { + Minimum = 1, + Increment = 1, + SortIndex = 10 + } + }; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + VolumeValue = (int)item.Value; + } + } + } + } + + public override Period GetPeriod => Period.TICK1; + + public override HistoryType GetHistoryType => HistoryType.Last; + + [NotPublished] + public override Period DefaultRange => Period.HOUR1; + + public HistoryAggregationVolume(int volumeValue) + { + VolumeValue = volumeValue; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 2); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(VolumeValue); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private HistoryAggregationVolume(HistoryAggregationVolume P_0) + : base(P_0) + { + VolumeValue = P_0.VolumeValue; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationVolume(this); + } + + [NotPublished] + public override string FormatTime(DateTime dt) + { + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dt); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + return new HistoryAggregationTick(HistoryType.Last); + } + } + public sealed class HistoryAggregationVolumeProfile : HistoryAggregation + { + [CompilerGenerated] + private Period ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = period; + } + } + + public override IList Settings + { + get + { + List list = new List(); + list.Add(new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Period) + { + SortIndex = 10, + ExcludedPeriods = new BasePeriod[1], + Description = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + return list; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem item in value) + { + if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()) + { + Period = (Period)item.Value; + } + } + } + } + + [NotPublished] + public override Period GetPeriod => Period; + + [NotPublished] + public override HistoryType GetHistoryType => HistoryType.Last; + + public HistoryAggregationVolumeProfile(Period period) + { + Period = period; + } + + protected HistoryAggregationVolumeProfile(HistoryAggregationVolumeProfile aggregation) + : base(aggregation) + { + Period = aggregation.Period; + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationVolumeProfile(this); + } + + [NotPublished] + public override string ToString() + { + return Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Period.Format(); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (metadata.AllowedAggregations.Contains(Name) && metadata.AllowedPeriodsHistoryAggregationTime.Contains(Period)) + { + return this; + } + if (metadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(HistoryType.Last)) + { + return new HistoryAggregationTick(HistoryType.Last); + } + return null; + } + } + public sealed class HistoryAggregationVwap : HistoryAggregation + { + [CompilerGenerated] + private readonly HistoryAggregationVwapParameters ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public HistoryAggregationVwapParameters Parameters + { + [CompilerGenerated] + get + { + return ??; + } + } + + public override TimeScaleType TimeScaleType => Parameters.Aggregation.TimeScaleType; + + public override Period DefaultRange => Period.HOUR1; + + public override Period GetPeriod + { + get + { + if (Parameters.DataType == VwapDataType.Tick) + { + return Period.TICK1; + } + return Parameters.Aggregation.GetPeriod; + } + } + + public override HistoryType GetHistoryType => Parameters.Aggregation.GetHistoryType; + + public override IList Settings + { + get + { + return Parameters?.Settings ?? new List(); + } + set + { + if (Parameters != null) + { + Parameters.Settings = value; + } + } + } + + public HistoryAggregationVwap() + { + ?? = new HistoryAggregationVwapParameters(); + } + + public HistoryAggregationVwap(HistoryAggregationVwapParameters parameters) + : this() + { + ?? = new HistoryAggregationVwapParameters(parameters); + } + + protected HistoryAggregationVwap(HistoryAggregationVwap aggregation) + : base(aggregation) + { + ?? = new HistoryAggregationVwapParameters(aggregation.Parameters); + } + + [NotPublished] + public override object Clone() + { + return new HistoryAggregationVwap(this); + } + + public override HistoryAggregation GetAggregationToDirectDownload(HistoryMetadata metadata) + { + if (Parameters.DataType == VwapDataType.Tick) + { + if (!metadata.AllowedHistoryTypesHistoryAggregationTick.Contains(HistoryType.Last)) + { + return null; + } + return new HistoryAggregationTick(HistoryType.Last); + } + return Parameters.Aggregation.GetAggregationToDirectDownload(metadata); + } + } + public abstract class HistoryProcessor : IHistoryProcessor, IDisposable + { + protected long sessionOffset; + + [CompilerGenerated] + private HistoryEventHandler ??; + + [CompilerGenerated] + private HistoryEventHandler ??; + + public virtual SubscribeQuoteType? GetSubscribeQuoteType => null; + + public event HistoryEventHandler NewHistoryItem + { + [CompilerGenerated] + add + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Combine(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + [CompilerGenerated] + remove + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Remove(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + } + + public event HistoryEventHandler HistoryItemUpdated + { + [CompilerGenerated] + add + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Combine(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + [CompilerGenerated] + remove + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Remove(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + } + + public HistoryProcessor() + { + } + + public virtual void Initialize(HistoryRequestParameters historyRequestParameters) + { + try + { + if (historyRequestParameters?.SessionsContainer != null) + { + sessionOffset = -historyRequestParameters.SessionsContainer.GetSessionOpenTime(Core.Instance.TimeUtils.SelectedTimeZone); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public virtual IList AggregateHistory(HistoryHolder historyHolder) + { + return historyHolder.History; + } + + public virtual void ProcessQuote(MessageQuote messageQuote) + { + } + + public virtual void CorrectHistoryRequestBorders(HistoryRequestParameters historyRequestParameters) + { + } + + public virtual string GetTimeToNextBar() + { + return null; + } + + public virtual void Dispose() + { + } + + protected void OnNewHistoryItem(HistoryEventArgs e) + { + ???.Invoke(this, e); + } + + protected void OnHistoryItemUpdated(HistoryEventArgs e) + { + ???.Invoke(this, e); + } + + public static bool IsDayOpeningNow(long barTime, long currentTime, long sessionOffset) + { + return (barTime + sessionOffset) / 864000000000L != (currentTime + sessionOffset) / 864000000000L; + } + } + public class HistoryProcessorEventArgs : EventArgs + { + [CompilerGenerated] + private UpdateReason ?; + + public new static HistoryProcessorEventArgs Empty => new HistoryProcessorEventArgs(); + + public UpdateReason IndicatorUpdateReason + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = updateReason; + } + } + + public HistoryProcessorEventArgs(UpdateReason updateReason = UpdateReason.Unknown) + { + IndicatorUpdateReason = updateReason; + } + } + public class HistoryProcessorItemUpdatedEventArgs : HistoryProcessorEventArgs + { + [CompilerGenerated] + private int ??; + + public int ItemOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public HistoryProcessorItemUpdatedEventArgs(int itemOffset = 0) + { + ItemOffset = itemOffset; + } + } + public sealed class HistoricalDataCustom : HistoricalData + { + private Indicator ??; + + public double this[PriceType priceType, int offset = 0] + { + get + { + IHistoryItem historyItem = this[offset, SeekOriginHistory.End]; + switch (priceType) + { + case PriceType.Open: + return historyItem[PriceType.Open]; + case PriceType.High: + return historyItem[PriceType.High]; + case PriceType.Low: + return historyItem[PriceType.Low]; + case PriceType.Close: + return historyItem[PriceType.Close]; + default: + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(priceType); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + } + set + { + IHistoryItem historyItem = this[offset, SeekOriginHistory.End]; + switch (priceType) + { + case PriceType.Open: + SetValue(value, historyItem[PriceType.High], historyItem[PriceType.Low], historyItem[PriceType.Close], offset); + return; + case PriceType.High: + SetValue(historyItem[PriceType.Open], value, historyItem[PriceType.Low], historyItem[PriceType.Close], offset); + return; + case PriceType.Low: + SetValue(historyItem[PriceType.Open], historyItem[PriceType.High], value, historyItem[PriceType.Close], offset); + return; + case PriceType.Close: + SetValue(historyItem[PriceType.Open], historyItem[PriceType.High], historyItem[PriceType.Low], value, offset); + return; + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(priceType); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + + public HistoricalDataCustom(Indicator indicator = null) + { + Parameters = new HistoryRequestParameters(); + if (indicator != null) + { + ?? = indicator; + Parameters.Symbol = indicator.HistoricalData.Symbol; + Parameters.Aggregation = indicator.HistoricalData.Aggregation.Clone() as HistoryAggregation; + indicator.?(this); + } + else + { + Parameters.Aggregation = new HistoryAggregationTime(Period.MIN1, HistoryType.Bid); + } + } + + public void AddValue(double open, double high, double low, double close) + { + if (?? != null) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(153, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.ShortName); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + AddNewItem(new HistoryItemCustom(open, high, low, close)); + } + + public void SetValue(double open, double high, double low, double close, int offset = 0) + { + if (!(this[offset, SeekOriginHistory.End] is HistoryItemCustom historyItemCustom)) + { + throw new IndexOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Indicator[] all = Indicators.All; + if (all.Length != 0) + { + while (Count - all[0].Count > 1) + { + Indicators.Update(new UpdateArgs(UpdateReason.NewBar)); + } + } + bool isEmpty = historyItemCustom.IsEmpty; + historyItemCustom.Open = open; + historyItemCustom.High = high; + historyItemCustom.Low = low; + historyItemCustom.Close = close; + historyItemCustom.IsEmpty = false; + if (offset == 0) + { + Indicators.Update(new UpdateArgs(isEmpty ? UpdateReason.NewBar : UpdateReason.NewTick)); + } + } + + internal void ?() + { + AddNewItem(new HistoryItemCustom(double.NaN, double.NaN, double.NaN, double.NaN) + { + IsEmpty = true + }, updateIndicators: false); + } + + private protected override void ?(IHistoryItem P_0) + { + HistoryItemCustom obj = P_0 as HistoryItemCustom; + if (obj != null && !obj.IsEmpty) + { + base.?(P_0); + } + } + + private protected override void ?(HistoryEventArgs P_0 = null, IndicatorUpdateType? P_1 = null) + { + if (Count != 0 && !(base[0, SeekOriginHistory.End] as HistoryItemCustom).IsEmpty) + { + base.?(P_0, P_1); + } + } + + public override void Dispose() + { + base.Dispose(); + ?? = null; + } + + internal HistoricalDataCustom(HistoryRequestParameters P_0) + : base(P_0) + { + } + + private protected override void ?() + { + } + + protected override void SubscribeSymbol() + { + } + + protected override void UnSubscribeSymbol() + { + } + } + public sealed class HistoryItemCustom : HistoryItem + { + private const int ?? = 0; + + private const int ?? = 1; + + private const int ?? = 2; + + private const int ?? = 3; + + private double[] ??; + + [CompilerGenerated] + private bool ??; + + internal double Open + { + get + { + return ??[0]; + } + set + { + ??[0] = num; + } + } + + internal double High + { + get + { + return ??[1]; + } + set + { + ??[1] = num; + } + } + + internal double Low + { + get + { + return ??[2]; + } + set + { + ??[2] = num; + } + } + + internal double Close + { + get + { + return ??[3]; + } + set + { + ??[3] = num; + } + } + + public override double this[PriceType priceType] => priceType switch + { + PriceType.Open => Open, + PriceType.High => High, + PriceType.Low => Low, + PriceType.Close => Close, + _ => base[priceType], + }; + + internal bool IsEmpty + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + + internal HistoryItemCustom(double P_0, double P_1, double P_2, double P_3) + { + ?? = new double[4]; + Open = P_0; + High = P_1; + Low = P_2; + Close = P_3; + IsEmpty = double.IsNaN(P_0) && double.IsNaN(P_1) && double.IsNaN(P_2) && double.IsNaN(P_3); + } + + private HistoryItemCustom(HistoryItemCustom P_0) + : base(P_0) + { + ?? = new double[4]; + for (int i = 0; i < P_0.??.Length; i++) + { + ??[i] = P_0.??[i]; + } + } + + public override object Clone() + { + return new HistoryItemCustom(this); + } + } + public class Price + { + [CompilerGenerated] + private PriceType ?; + + [CompilerGenerated] + private double ?; + + public PriceType Type + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = priceType; + } + } + + public double Value + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + public Price(PriceType priceType) + { + Type = priceType; + Value = double.NaN; + } + + public Price(PriceType priceType, double value) + { + Type = priceType; + Value = value; + } + } + /// + /// Represent access to historical data information and indicators control. + /// + [Published] + public class HistoricalData : IDisposable, IIndicatorsCollection, IEnumerable, IEnumerable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func, Period> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func, Period> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func, Period> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal BasePeriod ?(Period P_0) + { + return P_0.BasePeriod; + } + + internal Period ?(IGrouping P_0) + { + return P_0.OrderByDescending((Period period) => period.PeriodMultiplier).Last(); + } + + internal int ?(Period P_0) + { + return P_0.PeriodMultiplier; + } + + internal Period ?(BasePeriod P_0) + { + return new Period(P_0, 1); + } + + internal long ?(Period P_0) + { + return P_0.Ticks; + } + + internal BasePeriod ?(Period P_0) + { + return P_0.BasePeriod; + } + + internal Period ?(IGrouping P_0) + { + return P_0.OrderByDescending((Period period) => period.PeriodMultiplier).Last(); + } + + internal int ?(Period P_0) + { + return P_0.PeriodMultiplier; + } + + internal Period ?(BasePeriod P_0) + { + return new Period(P_0, 1); + } + + internal long ?(Period P_0) + { + return P_0.Ticks; + } + + internal HistoryAggregationTimeStatistics ?(Period P_0) + { + return new HistoryAggregationTimeStatistics(P_0); + } + + internal BasePeriod ?(Period P_0) + { + return P_0.BasePeriod; + } + + internal Period ?(IGrouping P_0) + { + return P_0.OrderByDescending((Period period) => period.PeriodMultiplier).Last(); + } + + internal int ?(Period P_0) + { + return P_0.PeriodMultiplier; + } + + internal Period ?(BasePeriod P_0) + { + return new Period(P_0, 1); + } + + internal long ?(Period P_0) + { + return P_0.Ticks; + } + + internal HistoryAggregationVolumeProfile ?(Period P_0) + { + return new HistoryAggregationVolumeProfile(P_0); + } + } + + [CompilerGenerated] + private sealed class ? + { + public HistoryAggregationTime ??; + + public HistoryAggregationTimeStatistics ??; + + public HistoryAggregationVolumeProfile ??; + + internal bool ?(Period P_0) + { + return ??.Period.Ticks % P_0.Ticks == 0; + } + + internal bool ?(Period P_0) + { + return P_0.Ticks < ??.Period.Ticks; + } + + internal HistoryAggregationTime ?(Period P_0) + { + return new HistoryAggregationTime(P_0, ??.HistoryType); + } + + internal bool ?(Period P_0) + { + return ??.Period.Ticks % P_0.Ticks == 0; + } + + internal bool ?(Period P_0) + { + return P_0.Ticks < ??.Period.Ticks; + } + + internal bool ?(Period P_0) + { + return ??.Period.Ticks % P_0.Ticks == 0; + } + + internal bool ?(Period P_0) + { + return P_0.Ticks < ??.Period.Ticks; + } + } + + [StructLayout(LayoutKind.Auto)] + [CompilerGenerated] + private struct ? + { + public HistoricalData ??; + + public MessageQuote ??; + } + + [CompilerGenerated] + private HistoryEventHandler ??; + + [CompilerGenerated] + private HistoryEventHandler ??; + + [CompilerGenerated] + private HistoryEventHandler ??; + + private readonly List ??; + + protected readonly object itemsLocker; + + protected HistoryRequestParameters Parameters; + + private protected IHistoryProcessor ??; + + [CompilerGenerated] + private readonly BuiltInIndicators ??; + + private bool ??; + + private CancellationTokenSource ??; + + private HistoricalDataState ??; + + private readonly ConcurrentQueue ??; + + private readonly bool ??; + + private MessageQuote ??; + + private MessageQuote ??; + + private MessageQuote ??; + + private readonly ManualResetEventSlim ??; + + protected readonly IndicatorsCollection Indicators; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private IVolumeAnalysisCalculationProgress ??; + + /// + /// Gets HistoricalData symbol + /// + public Symbol Symbol => Parameters?.Symbol; + + /// + /// Gets HistoricalData aggregation + /// + public HistoryAggregation Aggregation => Parameters?.Aggregation; + + /// + /// Gets HistoricalData left time boundary + /// + public DateTime FromTime => Parameters.FromTime; + + /// + /// Gets HistoricalData right time boundary + /// + public DateTime ToTime => Parameters.ToTime; + + /// + /// Gets HistoricalData items amount + /// + public virtual int Count + { + get + { + lock (itemsLocker) + { + return ??.Count; + } + } + } + + /// + /// Retrieves HistoricalData item by indexing offset and direction to find. + /// + /// + /// + /// + public virtual IHistoryItem this[int offset, SeekOriginHistory origin = SeekOriginHistory.End] + { + get + { + if (origin == SeekOriginHistory.End) + { + return ??[Count - 1 - offset]; + } + return ??[offset]; + } + private set + { + lock (itemsLocker) + { + if (seekOriginHistory == SeekOriginHistory.End) + { + ??[Count - 1 - num] = value2; + } + else + { + ??[num] = value2; + } + } + } + } + + /// + /// Gets access to built-in indicators + /// + public BuiltInIndicators BuiltInIndicators + { + [CompilerGenerated] + get + { + return ??; + } + } + + protected virtual bool NeedSubscribe + { + get + { + if (!??) + { + return ToTime == default(DateTime); + } + return false; + } + } + + /// + /// Gets array of attached indicators + /// + public Indicator[] AttachedIndicators => Indicators.All; + + public IndicatorCalculationBehavior IndicatorCalculationBehavior + { + get + { + return Indicators.CalculationBehavior; + } + set + { + Indicators.CalculationBehavior = value; + } + } + + [NotPublished] + public IVolumeAnalysisCalculationProgress VolumeAnalysisCalculationProgress + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Will be triggered when new historical item created + /// + public event HistoryEventHandler NewHistoryItem + { + [CompilerGenerated] + add + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Combine(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + [CompilerGenerated] + remove + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Remove(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + } + + /// + /// Will be triggered when current historical item changed or updated + /// + public event HistoryEventHandler HistoryItemUpdated + { + [CompilerGenerated] + add + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Combine(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + [CompilerGenerated] + remove + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value2 = (HistoryEventHandler)Delegate.Remove(historyEventHandler2, value); + historyEventHandler = Interlocked.CompareExchange(ref ??, value2, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + } + + /// + /// Will be triggered when volume analysis of current historical item changed or updated + /// + public event Action HistoryItemVolumeAnalysisUpdated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + [SpecialName] + [CompilerGenerated] + internal void ?(HistoryEventHandler P_0) + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value = (HistoryEventHandler)Delegate.Combine(historyEventHandler2, P_0); + historyEventHandler = Interlocked.CompareExchange(ref ??, value, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + + [SpecialName] + [CompilerGenerated] + internal void ?(HistoryEventHandler P_0) + { + HistoryEventHandler historyEventHandler = ??; + HistoryEventHandler historyEventHandler2; + do + { + historyEventHandler2 = historyEventHandler; + HistoryEventHandler value = (HistoryEventHandler)Delegate.Remove(historyEventHandler2, P_0); + historyEventHandler = Interlocked.CompareExchange(ref ??, value, historyEventHandler2); + } + while ((object)historyEventHandler != historyEventHandler2); + } + + private protected HistoricalData() + { + ?? = new List(); + itemsLocker = new object(); + ?? = false; + Indicators = new IndicatorsCollection(this); + ?? = HistoricalDataState.Pending; + ?? = new ConcurrentQueue(); + ?? = new ManualResetEventSlim(); + } + + protected internal HistoricalData(HistoryRequestParameters historyRequestParameters) + : this() + { + Parameters = historyRequestParameters; + HistoryAggregation historyAggregation = Core.Instance.HistoryAggregations[Parameters.Aggregation.Name]; + if (historyAggregation == null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Parameters.Aggregation.Name); + } + historyAggregation = historyAggregation.Clone() as HistoryAggregation; + if (historyAggregation != null) + { + historyAggregation.Settings = Parameters.Aggregation.Settings; + } + Parameters.Aggregation = historyAggregation; + ?? = historyRequestParameters.ForceReload; + ?? = new BuiltInIndicators(this); + } + + /// + /// Reloads entire HistoricalData + /// + public void Reload() + { + if (Symbol == null || Symbol.State == BusinessObjectState.Fake) + { + return; + } + try + { + ?? = HistoricalDataState.Loading; + ???.Cancel(); + if (Parameters.CancellationToken == CancellationToken.None) + { + ?? = new CancellationTokenSource(); + } + ?(); + ?(); + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + HistoryRequestParameters copy = Parameters.Copy; + copy.ToTime = ((ToTime == default(DateTime) || ToTime >= dateTimeUtcNow) ? dateTimeUtcNow : ToTime); + if (Symbol.QuoteDelay != default(TimeSpan) && copy.ToTime > dateTimeUtcNow - Symbol.QuoteDelay) + { + copy.ToTime = dateTimeUtcNow - Symbol.QuoteDelay; + } + copy.ForceReload = ??; + copy.CancellationToken = ???.Token ?? Parameters.CancellationToken; + copy.ProgressInfo = Parameters.ProgressInfo; + if (Core.Instance.SymbolsMapping.TryGetHistorySymbol(Symbol, copy.Aggregation.GetPeriod, out var historySymbol)) + { + copy.Symbol = historySymbol; + } + if (NeedSubscribe) + { + SubscribeSymbol(); + if (Aggregation.IsWaitingFirstQuoteRequired) + { + WaitHandle.WaitAny(new WaitHandle[3] + { + copy.CancellationToken.WaitHandle, + ??.WaitHandle, + new CancellationTokenSource(TimeSpan.FromSeconds(3.0)).Token.WaitHandle + }); + } + if (?? != null) + { + copy.ToTime = ??.Time.AddMilliseconds(1.0); + } + } + if (!(FromTime == ToTime) || !(ToTime == default(DateTime))) + { + IList list = ?(copy); + if (Parameters.ExcludeOutOfSession && list != null && list.Count > 0 && Parameters.SessionsContainer != null && Parameters.SessionsContainer.ActiveSessions.Any()) + { + HistoryAggregation aggregationToDirectDownload = Parameters.Aggregation.GetAggregationToDirectDownload(Parameters.Symbol.HistoryMetadata); + if (aggregationToDirectDownload == null || !(aggregationToDirectDownload is HistoryAggregationTime historyAggregationTime) || !(historyAggregationTime.Period >= Period.DAY1)) + { + list = list.Where((IHistoryItem P_0) => Parameters.SessionsContainer.ContainsDate(P_0.TicksLeft)).ToList(); + } + } + if (list != null) + { + lock (itemsLocker) + { + ??.AddRange(list); + } + } + } + Indicators.Refresh(); + ?(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?? = HistoricalDataState.Working; + } + } + + private protected virtual IList ?(HistoryRequestParameters P_0) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.Aggregation); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.Interval); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + long num = 0L; + int num2 = 0; + List list = new List(); + if (P_0.Symbol.State == BusinessObjectState.Fake) + { + return list; + } + if (P_0.FromTime > P_0.ToTime) + { + return list; + } + Connection connection = Core.Instance.Connections[P_0.Symbol.ConnectionId]; + if (connection == null || !connection.Connected) + { + return list; + } + CancellationToken cancellationToken = P_0.CancellationToken; + HistoryRequestParameters copy = P_0.Copy; + copy.ProgressInfo = P_0.ProgressInfo; + HistoryAggregation aggregationToDirectDownload = copy.Aggregation.GetAggregationToDirectDownload(P_0.Symbol.HistoryMetadata); + if (aggregationToDirectDownload == null) + { + return list; + } + copy.Aggregation = aggregationToDirectDownload; + Interval[] array = copy.Interval.Split(P_0.Symbol.GetHistoryDownloadingStep(copy.Aggregation)).ToArray(); + if (!array.Any()) + { + return list; + } + long num3 = copy.FromTime.Ticks; + Interval[] array2 = array; + for (int i = 0; i < array2.Length; i++) + { + Interval interval = array2[i]; + if (cancellationToken.IsCancellationRequested) + { + return list; + } + int num4 = ++num2 * 100 / array.Length; + HistoryRequestParameters copy2 = copy.Copy; + copy2.FromTime = interval.From; + copy2.ToTime = interval.To; + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(35, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(array.Length); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(copy2.Interval); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + IList list2 = connection.HistoryLoadingManager.?(copy2); + IHistoryItem historyItem = list2.LastOrDefault(); + if (historyItem != null) + { + num3 = historyItem.TicksLeft + copy.Aggregation.GetPeriod.Ticks; + } + LoggerManager loggers3 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(75, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(array.Length); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list2.Count); + loggers3.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + if (cancellationToken.IsCancellationRequested) + { + return list; + } + num += list2.Count; + IList list4; + if (list2.Count <= 0) + { + IList list3 = new List(); + list4 = list3; + } + else + { + list4 = ??.AggregateHistory(new HistoryHolder(list2, copy, (P_0.Symbol.HistoryMetadata.BuildUncompletedBars && num4 == 100) ? 99 : num4)); + } + IList list5 = list4; + if (cancellationToken.IsCancellationRequested) + { + return list; + } + list.AddRange(list5); + LoggerManager loggers4 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(76, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(array.Length); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list5.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers4.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + if (P_0.ProgressInfo != null && array.Length > 2) + { + P_0.ProgressInfo.Report((float)num4 / 100f); + } + LoggerManager loggers5 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(40, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(array.Length); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers5.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + if (!P_0.Symbol.HistoryMetadata.BuildUncompletedBars || num4 != 100) + { + continue; + } + HistoryAggregation aggregation = copy.Aggregation; + HistoryAggregationTime ?? = aggregation as HistoryAggregationTime; + if (?? == null) + { + if (!(aggregation is HistoryAggregationTickBars historyAggregationTickBars)) + { + HistoryAggregationTimeStatistics ?? = aggregation as HistoryAggregationTimeStatistics; + if (?? == null) + { + HistoryAggregationVolumeProfile ?? = aggregation as HistoryAggregationVolumeProfile; + if (?? == null) + { + continue; + } + HistoryAggregation[] array3 = (from period in (from period in P_0.Symbol.HistoryMetadata.AllowedPeriodsHistoryAggregationTimeStatistics + where ??.Period.Ticks % period.Ticks == 0 + group period by period.BasePeriod into source + select source.OrderByDescending((Period period) => period.PeriodMultiplier).Last()).Union(P_0.Symbol.HistoryMetadata.AllowedBasePeriodsHistoryAggregationTimeStatistics.Select((BasePeriod basePeriod) => new Period(basePeriod, 1))) + where period.Ticks < ??.Period.Ticks + orderby period.Ticks descending + select new HistoryAggregationVolumeProfile(period)).Union((!P_0.Symbol.HistoryMetadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) ? ((IEnumerable)Array.Empty()) : ((IEnumerable)new HistoryAggregation[1] + { + new HistoryAggregationTick(HistoryType.Last) + })).ToArray(); + for (int num5 = 0; num5 < array3.Length; num5++) + { + HistoryAggregation historyAggregation = array3[num5]; + TimeSpan historyDownloadingStep = P_0.Symbol.GetHistoryDownloadingStep(historyAggregation); + if (copy.ToTime.Ticks - num3 > historyDownloadingStep.Ticks) + { + num3 = copy.ToTime.Ticks - historyDownloadingStep.Ticks; + } + HistoryRequestParameters historyRequestParameters = new HistoryRequestParameters(copy) + { + FromTime = new DateTime(num3, DateTimeKind.Utc), + Aggregation = historyAggregation + }; + IList list6 = connection.HistoryLoadingManager.?(historyRequestParameters); + historyItem = list6.LastOrDefault(); + if (historyItem != null && historyAggregation is HistoryAggregationVolumeProfile historyAggregationVolumeProfile) + { + num3 = historyItem.TicksLeft + historyAggregationVolumeProfile.Period.Ticks; + } + IList collection = ??.AggregateHistory(new HistoryHolder(list6, historyRequestParameters, (num5 == array3.Length - 1) ? 100 : 99)); + list.AddRange(collection); + } + continue; + } + HistoryAggregation[] array4 = (from period in (from period in P_0.Symbol.HistoryMetadata.AllowedPeriodsHistoryAggregationTimeStatistics + where ??.Period.Ticks % period.Ticks == 0 + group period by period.BasePeriod into source + select source.OrderByDescending((Period period) => period.PeriodMultiplier).Last()).Union(P_0.Symbol.HistoryMetadata.AllowedBasePeriodsHistoryAggregationTimeStatistics.Select((BasePeriod basePeriod) => new Period(basePeriod, 1))) + where period.Ticks < ??.Period.Ticks + orderby period.Ticks descending + select new HistoryAggregationTimeStatistics(period)).Union((!P_0.Symbol.HistoryMetadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) ? ((IEnumerable)Array.Empty()) : ((IEnumerable)new HistoryAggregation[1] + { + new HistoryAggregationTick(HistoryType.Last) + })).ToArray(); + for (int num6 = 0; num6 < array4.Length; num6++) + { + HistoryAggregation historyAggregation2 = array4[num6]; + TimeSpan historyDownloadingStep2 = P_0.Symbol.GetHistoryDownloadingStep(historyAggregation2); + if (copy.ToTime.Ticks - num3 > historyDownloadingStep2.Ticks) + { + num3 = copy.ToTime.Ticks - historyDownloadingStep2.Ticks; + } + HistoryRequestParameters historyRequestParameters2 = new HistoryRequestParameters(copy) + { + FromTime = new DateTime(num3, DateTimeKind.Utc), + Aggregation = historyAggregation2 + }; + IList list7 = connection.HistoryLoadingManager.?(historyRequestParameters2); + historyItem = list7.LastOrDefault(); + if (historyItem != null && historyAggregation2 is HistoryAggregationTimeStatistics historyAggregationTimeStatistics) + { + num3 = historyItem.TicksLeft + historyAggregationTimeStatistics.Period.Ticks; + } + IList collection2 = ??.AggregateHistory(new HistoryHolder(list7, historyRequestParameters2, (num6 == array4.Length - 1) ? 100 : 99)); + list.AddRange(collection2); + } + } + else + { + if (!P_0.Symbol.HistoryMetadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) || !P_0.Symbol.HistoryMetadata.AllowedHistoryTypesHistoryAggregationTick.Contains(historyAggregationTickBars.HistoryType)) + { + continue; + } + if (list.Any()) + { + IHistoryItem historyItem2 = list.Last(); + if (historyItem2.TicksRight == 0L) + { + list.RemoveAt(list.Count - 1); + num3 = historyItem2.TicksLeft; + } + else + { + num3 = historyItem2.TicksRight + 1; + } + } + TimeSpan downloadingStep_Tick = P_0.Symbol.HistoryMetadata.DownloadingStep_Tick; + if (copy.ToTime.Ticks - num3 > downloadingStep_Tick.Ticks) + { + num3 = copy.ToTime.Ticks - downloadingStep_Tick.Ticks; + } + HistoryRequestParameters historyRequestParameters3 = new HistoryRequestParameters(copy) + { + FromTime = new DateTime(num3, DateTimeKind.Utc), + Aggregation = new HistoryAggregationTick(historyAggregationTickBars.HistoryType) + }; + IList history = connection.HistoryLoadingManager.?(historyRequestParameters3); + IList collection3 = ??.AggregateHistory(new HistoryHolder(history, historyRequestParameters3)); + list.AddRange(collection3); + } + continue; + } + HistoryAggregation[] array5 = (from period in (from period in P_0.Symbol.HistoryMetadata.AllowedPeriodsHistoryAggregationTime + where ??.Period.Ticks % period.Ticks == 0 + group period by period.BasePeriod into source + select source.OrderByDescending((Period period) => period.PeriodMultiplier).Last()).Union(P_0.Symbol.HistoryMetadata.AllowedBasePeriodsHistoryAggregationTime.Select((BasePeriod basePeriod) => new Period(basePeriod, 1))) + where period.Ticks < ??.Period.Ticks + orderby period.Ticks descending + select new HistoryAggregationTime(period, ??.HistoryType)).Union((!P_0.Symbol.HistoryMetadata.AllowedAggregations.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) ? ((IEnumerable)Array.Empty()) : ((IEnumerable)new HistoryAggregation[1] + { + new HistoryAggregationTick((??.HistoryType == HistoryType.Bid || ??.HistoryType == HistoryType.Ask) ? HistoryType.BidAsk : ??.HistoryType) + })).ToArray(); + for (int num7 = 0; num7 < array5.Length; num7++) + { + HistoryAggregation historyAggregation3 = array5[num7]; + TimeSpan historyDownloadingStep3 = P_0.Symbol.GetHistoryDownloadingStep(historyAggregation3); + if (copy.ToTime.Ticks - num3 > historyDownloadingStep3.Ticks) + { + num3 = copy.ToTime.Ticks - historyDownloadingStep3.Ticks; + } + HistoryRequestParameters historyRequestParameters4 = new HistoryRequestParameters(copy) + { + FromTime = new DateTime(num3, DateTimeKind.Utc), + Aggregation = historyAggregation3, + HistoryRequestType = HistoryRequestType.BuildUncompleteBarLogic + }; + IList list8 = connection.HistoryLoadingManager.?(historyRequestParameters4); + historyItem = list8.LastOrDefault(); + if (historyItem != null && historyAggregation3 is HistoryAggregationTime historyAggregationTime) + { + num3 = historyItem.TicksLeft + historyAggregationTime.Period.Ticks; + } + IList collection4 = ??.AggregateHistory(new HistoryHolder(list8, historyRequestParameters4, (num7 == array5.Length - 1) ? 100 : 99)); + list.AddRange(collection4); + } + } + LoggerManager loggers6 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(123, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((Core.Instance.TimeUtils.DateTimeUtcNow - dateTimeUtcNow).TotalSeconds, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers6.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + return list; + } + + /// + /// Gets index by time with counting on search direction + /// + public double GetIndexByTime(long time, SeekOriginHistory origin = SeekOriginHistory.End) + { + if (Count == 0) + { + return -1.0; + } + if (time > this[0, SeekOriginHistory.End].TicksRight) + { + return -1.0; + } + double num = -1.0; + int num2 = 0; + int num3 = Count - 1; + while (num2 <= num3) + { + int num4 = (num2 + num3) / 2; + if (num3 - num2 < 2) + { + num = ((time >= this[num2, SeekOriginHistory.Begin].TicksLeft) ? ((time >= this[num3, SeekOriginHistory.Begin].TicksLeft) ? ((double)num3) : ((double)num2)) : ((double)(--num2))); + break; + } + if (time < this[num4, SeekOriginHistory.Begin].TicksLeft) + { + num3 = num4 - 1; + } + else + { + num2 = num4 + 1; + } + } + if (origin == SeekOriginHistory.End && num != -1.0) + { + return (double)(Count - 1) - num; + } + return num; + } + + private void ?() + { + if (?? != null) + { + ??.NewHistoryItem -= ?; + ??.HistoryItemUpdated -= ?; + ??.Dispose(); + ?? = null; + } + ??.Clear(); + lock (itemsLocker) + { + ??.Clear(); + } + } + + [NotPublished] + public virtual void Dispose() + { + ???.Cancel(); + Indicators.Clear(); + UnSubscribeSymbol(); + ?(); + if (VolumeAnalysisCalculationProgress != null) + { + VolumeAnalysisCalculationProgress.AbortLoading(); + VolumeAnalysisCalculationProgress.Dispose(); + VolumeAnalysisCalculationProgress = null; + } + Parameters = null; + } + + protected virtual void SubscribeSymbol() + { + if (Symbol != null && ?? != null) + { + switch (??.GetSubscribeQuoteType) + { + case SubscribeQuoteType.Quote: + Symbol.NewQuote += Symbol_NewQuote; + break; + case SubscribeQuoteType.Level2: + Symbol.NewLevel2 += ?; + break; + case SubscribeQuoteType.Last: + Symbol.NewLast += Symbol_NewLast; + break; + case SubscribeQuoteType.Mark: + Symbol.NewMark += ?; + break; + } + Symbol.NewDayBar += ?; + ?? = true; + } + } + + protected virtual void UnSubscribeSymbol() + { + if (Symbol != null && ?? != null) + { + switch (??.GetSubscribeQuoteType) + { + case SubscribeQuoteType.Quote: + Symbol.NewQuote -= Symbol_NewQuote; + break; + case SubscribeQuoteType.Level2: + Symbol.NewLevel2 -= ?; + break; + case SubscribeQuoteType.Last: + Symbol.NewLast -= Symbol_NewLast; + break; + case SubscribeQuoteType.Mark: + Symbol.NewMark -= ?; + break; + } + Symbol.NewDayBar -= ?; + ?? = null; + ?? = null; + ??.Reset(); + } + } + + protected void Symbol_NewQuote(Symbol symbol, Quote quote) + { + if (!?(quote)) + { + ProcessQuote(quote); + } + } + + protected void Symbol_NewLast(Symbol symbol, Last last) + { + if (!?(last)) + { + ProcessLast(last); + } + } + + private void ?(Symbol P_0, Mark P_1) + { + if (!?(P_1)) + { + ProcessMark(P_1); + } + } + + private void ?(Symbol P_0, DayBar P_1) + { + if (!?((MessageQuote)P_1)) + { + ?(P_1); + } + } + + private void ?(Symbol P_0, Level2Quote P_1, DOMQuote P_2) + { + MessageQuote messageQuote = (MessageQuote)(((object)P_1) ?? ((object)P_2)); + if (!?(messageQuote)) + { + ProcessLevel2Qute(messageQuote); + } + } + + private bool ?(MessageQuote P_0) + { + ? ? = default(?); + ?.?? = this; + ?.?? = P_0; + if (?? != HistoricalDataState.Loading && ??.IsEmpty) + { + return false; + } + if (?? == null && ?(ref ?)) + { + ?? = ?.??; + ??.Set(); + } + ??.Enqueue(?.??); + return true; + } + + private void ?() + { + DateTime? dateTime = this.LastOrDefault()?.TimeLeft; + MessageQuote result; + while (??.TryDequeue(out result)) + { + if (result == null) + { + continue; + } + if (dateTime.HasValue) + { + DateTime time = result.Time; + DateTime? dateTime2 = dateTime; + if (time <= dateTime2) + { + continue; + } + } + if (!(result is Quote quote)) + { + if (!(result is Last last)) + { + if (result is Mark mark) + { + ProcessMark(mark); + } + } + else + { + ProcessLast(last); + } + } + else + { + ProcessQuote(quote); + } + } + } + + protected virtual void ProcessQuote(Quote quote) + { + ?? = quote; + ???.ProcessQuote(quote); + } + + protected virtual void ProcessLast(Last last) + { + ?? = last; + ???.ProcessQuote(last); + } + + protected virtual void ProcessMark(Mark mark) + { + ?? = mark; + ???.ProcessQuote(mark); + } + + private void ?(DayBar P_0) + { + ?? = P_0; + ???.ProcessQuote(P_0); + } + + protected virtual void ProcessLevel2Qute(MessageQuote quote) + { + ?? = quote; + ???.ProcessQuote(quote); + } + + /// + /// Creates indicator by it's name and if it successfully created adds it to the HistoricalData + /// + /// + /// + /// + public Indicator AddIndicator(string indicatorName, params SettingItem[] settings) + { + if (string.IsNullOrEmpty(indicatorName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Indicator indicator = Core.Instance.Indicators.CreateIndicator(indicatorName, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + if (indicator == null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + indicator.Settings = settings; + AddIndicator(indicator); + return indicator; + } + + /// + /// Adds indicator to the HistoricalData + /// + /// + public void AddIndicator(Indicator indicator) + { + Indicators.AddIndicator(indicator); + } + + /// + /// Removes indicator from the HistoricalData + /// + /// + public void RemoveIndicator(Indicator indicator) + { + Indicators.RemoveIndicator(indicator); + } + + [NotPublished] + [EditorBrowsable(EditorBrowsableState.Never)] + public bool TryGetIndicatorWrapper(Indicator indicator, out IndicatorWrapper indicatorWrapper) + { + return Indicators.TryGetWrapper(indicator, out indicatorWrapper); + } + + public IVolumeAnalysisCalculationProgress CalculateVolumeProfile(VolumeAnalysisCalculationParameters volumeAnalysisCalculationParameters) + { + return Core.Instance.VolumeAnalysis.CalculateProfile(this, volumeAnalysisCalculationParameters); + } + + public IEnumerator GetEnumerator() + { + return ??.GetEnumerator(); + } + + private IEnumerator ?() + { + return ??.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + protected virtual IHistoryProcessor CreateHistoryProcessor() + { + return Core.Instance.HistoryAggregations.CreateHistoryProcessor(Parameters); + } + + private protected virtual void ?() + { + ?? = CreateHistoryProcessor(); + if (?? == null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??.CorrectHistoryRequestBorders(Parameters); + ??.NewHistoryItem += ?; + ??.HistoryItemUpdated += ?; + } + + private void ?(object P_0, HistoryEventArgs P_1) + { + if (P_1.HistoryItem != null && (!Parameters.ExcludeOutOfSession || Parameters.SessionsContainer == null || Parameters.SessionsContainer.ContainsDate(P_1.HistoryItem.TicksLeft))) + { + AddNewItem(P_1.HistoryItem, updateIndicators: true, P_1); + } + } + + private void ?(object P_0, HistoryEventArgs P_1) + { + if (P_1.HistoryItem == null || (Parameters.ExcludeOutOfSession && Parameters.SessionsContainer != null && !Parameters.SessionsContainer.ContainsDate(P_1.HistoryItem.TicksLeft))) + { + return; + } + if (P_1.ResetVolumeAnalysisRequired) + { + P_1.HistoryItem.VolumeAnalysisData = null; + } + else + { + IHistoryItem historyItem = P_1.HistoryItem; + if (historyItem.VolumeAnalysisData == null) + { + VolumeAnalysisData volumeAnalysisData = (historyItem.VolumeAnalysisData = this[0, SeekOriginHistory.End]?.VolumeAnalysisData); + } + } + this[0, SeekOriginHistory.End] = P_1.HistoryItem; + ?(P_1.HistoryItem); + Indicators.Update(new UpdateArgs(UpdateReason.NewTick), IndicatorUpdateType.OnTick); + ?(P_1); + } + + protected virtual void AddNewItem(IHistoryItem historyItem, bool updateIndicators = true, HistoryEventArgs e = null) + { + if (updateIndicators) + { + ?(e, IndicatorUpdateType.OnBarClose); + } + lock (itemsLocker) + { + ??.Add(historyItem); + } + ?(historyItem); + if (updateIndicators) + { + ?(e, IndicatorUpdateType.OnTick); + } + ?(historyItem); + } + + private protected virtual void ?(IHistoryItem P_0) + { + ??.InvokeSafely(this, new HistoryEventArgs + { + HistoryItem = P_0 + }); + } + + private void ?(HistoryEventArgs P_0) + { + ???.Invoke(this, P_0); + } + + private void ?(IHistoryItem P_0) + { + if (?? != ??) + { + ?? = ??; + ???.Invoke(this, new ? + { + HistoryItem = P_0, + MessageQuote = ?? + }); + } + } + + private protected virtual void ?(HistoryEventArgs P_0 = null, IndicatorUpdateType? P_1 = null) + { + Indicators.Update(new UpdateArgs(UpdateReason.NewBar), P_1); + } + + internal void ?() + { + ???.Invoke(); + } + + [NotPublished] + [EditorBrowsable(EditorBrowsableState.Never)] + public void CutItems(int count) + { + lock (itemsLocker) + { + count = Math.Min(??.Count, Math.Abs(count)); + ??.RemoveRange(0, count); + } + Parameters.FromTime = ((Count > 0) ? this[0, SeekOriginHistory.Begin].TimeLeft : Core.Instance.TimeUtils.DateTimeUtcNow); + } + + [NotPublished] + protected void InsertRange(int index, IList range) + { + lock (itemsLocker) + { + ??.InsertRange(index, range); + } + Indicators.Refresh(); + } + + public string GetTimeToNextBar() + { + return ??.GetTimeToNextBar(); + } + + [CompilerGenerated] + private bool ?(IHistoryItem P_0) + { + return Parameters.SessionsContainer.ContainsDate(P_0.TicksLeft); + } + + [CompilerGenerated] + private bool ?(ref ? P_0) + { + if (?? == null) + { + return false; + } + return ??.GetSubscribeQuoteType switch + { + SubscribeQuoteType.Quote => P_0.?? is Quote, + SubscribeQuoteType.Level2 => (P_0.?? is Level2Quote || P_0.?? is DOMQuote) ? true : false, + SubscribeQuoteType.Last => P_0.?? is Last, + SubscribeQuoteType.Mark => P_0.?? is Mark, + _ => false, + }; + } + } + /// + /// Period that can be used as a basis for history aggregations + /// + [DataContract(Name = "BasePeriod", Namespace = "TradingPlatform")] + [Published] + public enum BasePeriod + { + [EnumMember] + Tick, + [EnumMember] + Second, + [EnumMember] + Minute, + [EnumMember] + Hour, + [EnumMember] + Day, + [EnumMember] + Week, + [EnumMember] + Month, + [EnumMember] + Year + } + [Published] + public enum RenkoStyle + { + Classic, + HighLow, + AdvancedClassic, + AdvancedHighLow + } + [Published] + public enum PointsAndFiguresStyle + { + [Description("Classic")] + Classic, + [Description("High/Low")] + HighLow + } + [Published] + public enum PriceType + { + Open, + High, + Low, + Close, + Median, + Typical, + Weighted, + Bid, + BidSize, + Ask, + AskSize, + Last, + Volume, + Ticks, + AggressorFlag, + TickDirection, + BidTickDirection, + AskTickDirection, + OpenInterest, + Mark, + FundingRate, + QuoteAssetVolume + } + public enum SeekOriginHistory + { + Begin, + End + } + public enum HistoricalDataState + { + Pending, + Working, + Loading + } + public class HistoryEventArgs : EventArgs + { + [CompilerGenerated] + private IHistoryItem ?; + + [CompilerGenerated] + private bool ?; + + public IHistoryItem HistoryItem + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public bool ResetVolumeAnalysisRequired + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + } + public delegate void HistoryEventHandler(object sender, HistoryEventArgs e); + public class HistoryHolder + { + [CompilerGenerated] + private readonly IList ?; + + [CompilerGenerated] + private readonly HistoryRequestParameters ?; + + [CompilerGenerated] + private int ?; + + public IList History + { + [CompilerGenerated] + get + { + return ?; + } + } + + public HistoryRequestParameters RequestParameters + { + [CompilerGenerated] + get + { + return ?; + } + } + + public int ProgressPercent + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + public HistoryHolder(IList history, HistoryRequestParameters requestParameters, int progressPercent = 100) + { + ? = history; + ? = requestParameters; + ProgressPercent = progressPercent; + } + + public HistoryInterval ToHistoryInterval() + { + return new HistoryInterval + { + Description = RequestParameters.ToDescription(), + Interval = RequestParameters.Interval, + History = History + }; + } + } + [ProtoContract] + [ProtoInclude(2, typeof(HistoryItemLast))] + [ProtoInclude(3, typeof(HistoryItemTick))] + [ProtoInclude(4, typeof(HistoryItemMark))] + [ProtoInclude(5, typeof(HistoryItemBar))] + [ProtoInclude(6, typeof(HistoryItemLevel2))] + [ProtoInclude(7, typeof(HistoryItemDom))] + [ProtoInclude(8, typeof(HistoryItemTimeStatistics))] + [DataContract] + public abstract class HistoryItem : IHistoryItem, ICloneable + { + public static class CustomFields + { + public static class Trend + { + public const string UP = "up"; + + public const string DOWN = "down"; + } + + public const string IS_TEMPORARY_BAR = "isTemporaryBar"; + + public const string TREND = "trend"; + + public const string ONE_STEP_BACK = "OneStepBack"; + } + + [CompilerGenerated] + private long ??; + + private Dictionary ??; + + [CompilerGenerated] + private VolumeAnalysisData ??; + + public DateTime TimeLeft => new DateTime(TicksLeft, DateTimeKind.Utc); + + [ProtoMember(1)] + [DataMember(Order = 1)] + public long TicksLeft + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public virtual long TicksRight + { + get + { + return TicksLeft; + } + set + { + } + } + + public virtual double this[PriceType priceType] => double.NaN; + + public VolumeAnalysisData VolumeAnalysisData + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + protected HistoryItem() + { + TicksLeft = 0L; + } + + public void SetData(string key, object value) + { + if (string.IsNullOrEmpty(key)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (value == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (?? == null) + { + ?? = new Dictionary(); + } + ??[key] = value; + } + + public bool TryGetData(string key, out TData data) + { + data = default(TData); + if (?? == null) + { + return false; + } + if (!??.TryGetValue(key, out var value) || !(value is TData)) + { + return false; + } + data = (TData)value; + return true; + } + + protected HistoryItem(MessageQuote message) + { + TicksLeft = message.Time.Ticks; + } + + protected HistoryItem(HistoryItem original) + { + TicksLeft = original.TicksLeft; + if (original.VolumeAnalysisData != null) + { + VolumeAnalysisData = new VolumeAnalysisData(original.VolumeAnalysisData); + } + if (original.?? == null) + { + return; + } + foreach (KeyValuePair item in original.??) + { + SetData(item.Key, item.Value); + } + } + + public abstract object Clone(); + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 2); + defaultInterpolatedStringHandler.AppendFormatted(TicksLeft); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TimeLeft); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + /// + /// Represents historical data bar item + /// + [Published] + [ProtoContract] + public class HistoryItemBar : HistoryItem + { + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + /// + /// Gets bar's right time border + /// + public DateTime TimeRight => new DateTime(TicksRight, DateTimeKind.Utc); + + /// + /// Defines bar's ticks count + /// + public override long TicksRight + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines Open price + /// + [ProtoMember(1)] + public double Open + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines High price + /// + [ProtoMember(2)] + public double High + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines Low price + /// + [ProtoMember(3)] + public double Low + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines Close price + /// + [ProtoMember(4)] + public double Close + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets Median (High+Low)/2 price + /// + public double Median => (High + Low) / 2.0; + + /// + /// Gets Typical (High+Low+Close)/3 price + /// + public double Typical => (High + Low + Close) / 3.0; + + /// + /// Gets Weighted (High+Low+Close+Close)/4 price + /// + public double Weighted => (High + Low + Close + Close) / 4.0; + + /// + /// Defines ticks amount + /// + [ProtoMember(5)] + public long Ticks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines volume value + /// + [ProtoMember(6)] + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(7)] + public double OpenInterest + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(8)] + public double FundingRate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(9)] + public double QuoteAssetVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets price by indexing + /// + /// + /// + public override double this[PriceType priceType] => priceType switch + { + PriceType.Open => Open, + PriceType.High => High, + PriceType.Low => Low, + PriceType.Close => Close, + PriceType.Median => Median, + PriceType.Typical => Typical, + PriceType.Weighted => Weighted, + PriceType.Ticks => Ticks, + PriceType.Volume => Volume, + PriceType.OpenInterest => OpenInterest, + PriceType.FundingRate => FundingRate, + PriceType.QuoteAssetVolume => QuoteAssetVolume, + _ => base[priceType], + }; + + /// + /// Creates HistoryItemBar instance with default OHLC price = + /// + public HistoryItemBar() + { + Open = double.NaN; + High = double.NaN; + Low = double.NaN; + Close = double.NaN; + } + + /// + /// Comparing by , OHLC, + /// + /// + /// + [NotPublished] + public override bool Equals(object obj) + { + HistoryItemBar historyItemBar = obj as HistoryItemBar; + if (historyItemBar == null) + { + return false; + } + if (base.TicksLeft == historyItemBar.TicksLeft && Open == historyItemBar.Open && High == historyItemBar.High && Low == historyItemBar.Low && Close == historyItemBar.Close && Ticks == historyItemBar.Ticks && Volume == historyItemBar.Volume) + { + return QuoteAssetVolume == historyItemBar.QuoteAssetVolume; + } + return false; + } + + [NotPublished] + public override int GetHashCode() + { + return base.TicksLeft.GetHashCode() ^ Open.GetHashCode() ^ High.GetHashCode() ^ Low.GetHashCode() ^ Close.GetHashCode() ^ Ticks.GetHashCode() ^ Volume.GetHashCode() ^ QuoteAssetVolume.GetHashCode(); + } + + [NotPublished] + public static bool operator ==(HistoryItemBar a, HistoryItemBar b) + { + if ((object)a == b) + { + return true; + } + if ((object)a == null || (object)b == null) + { + return false; + } + return a.Equals(b); + } + + [NotPublished] + public static bool operator !=(HistoryItemBar a, HistoryItemBar b) + { + return !(a == b); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(39, 10); + defaultInterpolatedStringHandler.AppendFormatted(base.TicksLeft); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TicksRight); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Ticks); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.TimeLeft); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TimeRight); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Open); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(High); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Low); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Close); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((Close > Open) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private HistoryItemBar(HistoryItemBar P_0) + : base(P_0) + { + TicksRight = P_0.TicksRight; + Open = P_0.Open; + High = P_0.High; + Low = P_0.Low; + Close = P_0.Close; + Ticks = P_0.Ticks; + Volume = P_0.Volume; + OpenInterest = P_0.OpenInterest; + FundingRate = P_0.FundingRate; + QuoteAssetVolume = P_0.QuoteAssetVolume; + base.VolumeAnalysisData = P_0.VolumeAnalysisData; + } + + [NotPublished] + public override object Clone() + { + return new HistoryItemBar(this); + } + } + [ProtoContract] + public sealed class HistoryItemDom : HistoryItem + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal HistoryItemLevel2 ?(Level2Quote P_0) + { + return new HistoryItemLevel2(P_0); + } + + internal HistoryItemLevel2 ?(Level2Quote P_0) + { + return new HistoryItemLevel2(P_0); + } + + internal HistoryItemLevel2 ?(HistoryItemLevel2 P_0) + { + return new HistoryItemLevel2(P_0); + } + + internal HistoryItemLevel2 ?(HistoryItemLevel2 P_0) + { + return new HistoryItemLevel2(P_0); + } + } + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private List ??; + + [ProtoMember(1)] + public List Asks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public List Bids + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Creates HistoryItemLast instance + /// + public HistoryItemDom() + { + Asks = new List(); + Bids = new List(); + } + + public HistoryItemDom(DOMQuote domQuote) + : base(domQuote) + { + Asks = domQuote.Asks.Select((Level2Quote P_0) => new HistoryItemLevel2(P_0)).ToList(); + Bids = domQuote.Bids.Select((Level2Quote P_0) => new HistoryItemLevel2(P_0)).ToList(); + } + + public HistoryItemDom(HistoryItemDom original) + : base(original) + { + Asks = original.Asks.Select((HistoryItemLevel2 P_0) => new HistoryItemLevel2(P_0)).ToList(); + Bids = original.Bids.Select((HistoryItemLevel2 P_0) => new HistoryItemLevel2(P_0)).ToList(); + } + + [NotPublished] + public override object Clone() + { + return new HistoryItemDom(this); + } + } + /// + /// Represents historical data trade item + /// + [Published] + [ProtoContract] + [DataContract] + public sealed class HistoryItemLast : HistoryItem, IVolumeTickData, IBuyerSellerData + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private AggressorFlag ??; + + [CompilerGenerated] + private TickDirection ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + /// + /// Defines price value + /// + [ProtoMember(1)] + [DataMember(Order = 2)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines volume value + /// + [ProtoMember(2)] + [DataMember(Order = 3)] + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines trade operation side as aggressor flag + /// + [ProtoMember(3)] + [DataMember(Order = 4)] + public AggressorFlag AggressorFlag + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + [DataMember(Order = 5)] + public TickDirection TickDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + [DataMember(Order = 6)] + public double OpenInterest + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(6)] + [DataMember(Order = 7)] + public string Buyer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(7)] + [DataMember(Order = 8)] + public string Seller + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(8)] + [DataMember(Order = 9)] + public double FundingRate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(9)] + [DataMember(Order = 10)] + public double QuoteAssetVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets price by indexing + /// + /// + /// + public override double this[PriceType priceType] => priceType switch + { + PriceType.Last => Price, + PriceType.Open => Price, + PriceType.High => Price, + PriceType.Low => Price, + PriceType.Close => Price, + PriceType.Median => Price, + PriceType.Weighted => Price, + PriceType.Typical => Price, + PriceType.Bid => Price, + PriceType.Ask => Price, + PriceType.Mark => Price, + PriceType.Volume => Volume, + PriceType.AggressorFlag => (double)AggressorFlag, + PriceType.TickDirection => (double)TickDirection, + PriceType.BidTickDirection => (double)TickDirection, + PriceType.AskTickDirection => (double)TickDirection, + PriceType.OpenInterest => OpenInterest, + PriceType.FundingRate => FundingRate, + PriceType.QuoteAssetVolume => QuoteAssetVolume, + _ => base[priceType], + }; + + VolumeTickDataType IVolumeTickData.VolumeTickDataType => VolumeTickDataType.Lasts; + + long IVolumeTickData.Time => base.TicksLeft; + + /// + /// Creates HistoryItemLast instance + /// + public HistoryItemLast() + { + Price = double.NaN; + Volume = double.NaN; + QuoteAssetVolume = double.NaN; + AggressorFlag = AggressorFlag.NotSet; + TickDirection = TickDirection.NotSet; + } + + public HistoryItemLast(Last last) + : base(last) + { + Price = last.Price; + Volume = last.Size; + AggressorFlag = last.AggressorFlag; + TickDirection = last.TickDirection; + OpenInterest = last.OpenInterest; + Buyer = last.Buyer; + Seller = last.Seller; + QuoteAssetVolume = last.QuoteAssetVolume; + } + + private HistoryItemLast(HistoryItemLast P_0) + : base(P_0) + { + Price = P_0.Price; + Volume = P_0.Volume; + AggressorFlag = P_0.AggressorFlag; + TickDirection = P_0.TickDirection; + OpenInterest = P_0.OpenInterest; + FundingRate = P_0.FundingRate; + Buyer = P_0.Buyer; + Seller = P_0.Seller; + QuoteAssetVolume = P_0.QuoteAssetVolume; + } + + [NotPublished] + public override object Clone() + { + return new HistoryItemLast(this); + } + + /// + /// Comparing by , OHLC, + /// + /// + /// + [NotPublished] + public override bool Equals(object obj) + { + HistoryItemLast historyItemLast = obj as HistoryItemLast; + if (historyItemLast == null) + { + return false; + } + if (base.TicksLeft == historyItemLast.TicksLeft && Price == historyItemLast.Price && Volume == historyItemLast.Volume && QuoteAssetVolume == historyItemLast.QuoteAssetVolume) + { + return AggressorFlag == historyItemLast.AggressorFlag; + } + return false; + } + + [NotPublished] + public override int GetHashCode() + { + return base.TicksLeft.GetHashCode() ^ Price.GetHashCode() ^ Volume.GetHashCode() ^ QuoteAssetVolume.GetHashCode() ^ AggressorFlag.GetHashCode(); + } + + [NotPublished] + public static bool operator ==(HistoryItemLast a, HistoryItemLast b) + { + if ((object)a == b) + { + return true; + } + if ((object)a == null || (object)b == null) + { + return false; + } + return a.Equals(b); + } + + [NotPublished] + public static bool operator !=(HistoryItemLast a, HistoryItemLast b) + { + return !(a == b); + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(22, 3); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Volume); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [ProtoContract] + public sealed class HistoryItemLevel2 : HistoryItem + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private QuotePriceType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private bool ??; + + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public QuotePriceType PriceType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + public double Size + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public bool Closed + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Creates HistoryItemLast instance + /// + public HistoryItemLevel2() + { + Price = double.NaN; + Size = double.NaN; + } + + public HistoryItemLevel2(Level2Quote level2Quote) + : base(level2Quote) + { + Id = level2Quote.Id; + PriceType = level2Quote.PriceType; + Price = level2Quote.Price; + Size = level2Quote.Size; + Closed = level2Quote.Closed; + } + + public HistoryItemLevel2(HistoryItemLevel2 original) + : base(original) + { + Id = original.Id; + PriceType = original.PriceType; + Price = original.Price; + Size = original.Size; + Closed = original.Closed; + } + + [NotPublished] + public override object Clone() + { + return new HistoryItemLevel2(this); + } + } + [ProtoContract] + public class HistoryItemMark : HistoryItem + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [ProtoMember(1)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets price by indexing + /// + /// + /// + public override double this[PriceType priceType] + { + get + { + switch (priceType) + { + case PriceType.Open: + case PriceType.High: + case PriceType.Low: + case PriceType.Close: + case PriceType.Median: + case PriceType.Typical: + case PriceType.Weighted: + case PriceType.Bid: + case PriceType.Ask: + case PriceType.Last: + case PriceType.Mark: + return Price; + case PriceType.Volume: + return Volume; + default: + return base[priceType]; + } + } + } + + /// + /// Creates HistoryItemLast instance + /// + public HistoryItemMark() + { + Price = double.NaN; + Volume = double.NaN; + } + + private HistoryItemMark(HistoryItemMark P_0) + : base(P_0) + { + Price = P_0.Price; + Volume = P_0.Volume; + } + + [NotPublished] + public override object Clone() + { + return new HistoryItemMark(this); + } + } + /// + /// Represents historical data tick item + /// + [Published] + [ProtoContract] + public class HistoryItemTick : HistoryItem, IVolumeTickData + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private TickDirection ??; + + [CompilerGenerated] + private TickDirection ??; + + /// + /// Defines Bid price + /// + [ProtoMember(1)] + public double Bid + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines Bid size + /// + [ProtoMember(2)] + public double BidSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines Ask price + /// + [ProtoMember(3)] + public double Ask + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Defines Ask size + /// + [ProtoMember(4)] + public double AskSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public TickDirection BidTickDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(6)] + public TickDirection AskTickDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets price by indexing + /// + /// + /// + public override double this[PriceType priceType] + { + get + { + switch (priceType) + { + case PriceType.Open: + case PriceType.High: + case PriceType.Low: + case PriceType.Close: + case PriceType.Median: + case PriceType.Typical: + case PriceType.Weighted: + case PriceType.Bid: + case PriceType.Last: + case PriceType.Mark: + return Bid; + case PriceType.BidSize: + return BidSize; + case PriceType.Ask: + return Ask; + case PriceType.AskSize: + return AskSize; + case PriceType.Volume: + return 0.0; + case PriceType.TickDirection: + case PriceType.BidTickDirection: + return (double)BidTickDirection; + case PriceType.AskTickDirection: + return (double)AskTickDirection; + default: + return base[priceType]; + } + } + } + + VolumeTickDataType IVolumeTickData.VolumeTickDataType => VolumeTickDataType.Ticks; + + long IVolumeTickData.Time => base.TicksLeft; + + double IVolumeTickData.Price => Bid; + + double IVolumeTickData.Volume => 1.0; + + TickDirection IVolumeTickData.TickDirection => BidTickDirection; + + AggressorFlag IVolumeTickData.AggressorFlag => Symbol.ConvertTickDirection(BidTickDirection); + + /// + /// Creates HistoryItemBar instance with default Ask/AskSize/Bid/BidSize = + /// + public HistoryItemTick() + { + Bid = double.NaN; + BidSize = double.NaN; + Ask = double.NaN; + AskSize = double.NaN; + BidTickDirection = TickDirection.NotSet; + AskTickDirection = TickDirection.NotSet; + } + + private HistoryItemTick(HistoryItemTick P_0) + : base(P_0) + { + Bid = P_0.Bid; + BidSize = P_0.BidSize; + Ask = P_0.Ask; + AskSize = P_0.AskSize; + } + + [NotPublished] + public override object Clone() + { + return new HistoryItemTick(this); + } + + /// + /// Comparing by , OHLC, , , , + /// + /// + /// + [NotPublished] + public override bool Equals(object obj) + { + HistoryItemTick historyItemTick = obj as HistoryItemTick; + if (historyItemTick == null) + { + return false; + } + if (base.TicksLeft == historyItemTick.TicksLeft && Ask == historyItemTick.Ask && AskSize == historyItemTick.AskSize && Bid == historyItemTick.Bid) + { + return BidSize == historyItemTick.BidSize; + } + return false; + } + + [NotPublished] + public override int GetHashCode() + { + return base.TicksLeft.GetHashCode() ^ Ask.GetHashCode() ^ AskSize.GetHashCode() ^ Bid.GetHashCode() ^ BidSize.GetHashCode(); + } + + [NotPublished] + public static bool operator ==(HistoryItemTick a, HistoryItemTick b) + { + if ((object)a == b) + { + return true; + } + if ((object)a == null || (object)b == null) + { + return false; + } + return a.Equals(b); + } + + [NotPublished] + public static bool operator !=(HistoryItemTick a, HistoryItemTick b) + { + return !(a == b); + } + } + public sealed class HistoryItemTimeStatistics : HistoryItem, IVolumeData + { + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + public override long TicksRight + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Trades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double BuyVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int BuyTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double SellVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int SellTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryItemTimeStatistics() + { + } + + public HistoryItemTimeStatistics(HistoryItemTimeStatistics item) + : base(item) + { + TicksRight = item.TicksRight; + Volume = item.Volume; + BuyVolume = item.BuyVolume; + SellVolume = item.SellVolume; + Trades = item.Trades; + BuyTrades = item.BuyTrades; + SellTrades = item.SellTrades; + } + + public override object Clone() + { + return new HistoryItemTimeStatistics(this); + } + } + public sealed class HistoryItemVolumeProfile : HistoryItem + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, double> ??; + + public static Func, VolumeDataItem> ??; + + internal double ?(KeyValuePair P_0) + { + return P_0.Key; + } + + internal VolumeDataItem ?(KeyValuePair P_0) + { + return new VolumeDataItem(P_0.Value); + } + } + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private Dictionary ??; + + public override long TicksRight + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Dictionary PriceLevels + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryItemVolumeProfile() + { + } + + public HistoryItemVolumeProfile(HistoryItemVolumeProfile item) + : base(item) + { + TicksRight = item.TicksRight; + PriceLevels = item.PriceLevels.ToDictionary((KeyValuePair P_0) => P_0.Key, (KeyValuePair P_0) => new VolumeDataItem(P_0.Value)); + } + + public override object Clone() + { + return new HistoryItemVolumeProfile(this); + } + } + public interface IVolumeData + { + double Volume { get; set; } + + double BuyVolume { get; set; } + + double SellVolume { get; set; } + + int Trades { get; set; } + + int BuyTrades { get; set; } + + int SellTrades { get; set; } + } + public sealed class VolumeDataItem : IVolumeData + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double BuyVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double SellVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Trades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int BuyTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int SellTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VolumeDataItem() + { + } + + public VolumeDataItem(VolumeDataItem volumeData) + { + Volume = volumeData.Volume; + BuyVolume = volumeData.BuyVolume; + SellVolume = volumeData.SellVolume; + Trades = volumeData.Trades; + BuyTrades = volumeData.BuyTrades; + SellTrades = volumeData.SellTrades; + } + } + /// + /// Resolves a history request parameters per symbol + /// + [Published] + [ProtoContract] + public sealed class HistoryRequestParameters : RequestParameters + { + private Symbol ??; + + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private HistoryAggregation ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private ISessionsContainer ??; + + [CompilerGenerated] + private IProgress ??; + + [CompilerGenerated] + private readonly HistoryRequestType ??; + + public override RequestType Type => RequestType.History; + + public Symbol Symbol + { + get + { + return ??; + } + set + { + ?? = value; + ?? = ???.Id; + } + } + + [ProtoMember(1)] + public string SymbolId + { + get + { + string id = ??; + if (id == null) + { + Symbol symbol = Symbol; + if (symbol == null) + { + return null; + } + id = symbol.Id; + } + return id; + } + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public DateTime FromTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public DateTime ToTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Interval Interval + { + get + { + return new Interval(FromTime, ToTime); + } + set + { + FromTime = value.From; + ToTime = value.To; + } + } + + public HistoryAggregation Aggregation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ForceReload + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ExcludeOutOfSession + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ISessionsContainer SessionsContainer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IProgress ProgressInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryRequestParameters Copy => new HistoryRequestParameters(this); + + public HistoryRequestType HistoryRequestType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public HistoryRequestParameters() + { + ProgressInfo = new PercentageProgress(); + ForceReload = false; + ExcludeOutOfSession = true; + } + + public HistoryRequestParameters(HistoryRequestParameters original) + { + Symbol = original.Symbol; + SymbolId = original.SymbolId; + Aggregation = original.Aggregation?.Clone() as HistoryAggregation; + FromTime = original.FromTime; + ToTime = original.ToTime; + ForceReload = original.ForceReload; + base.CancellationToken = original.CancellationToken; + SessionsContainer = original.SessionsContainer; + ExcludeOutOfSession = original.ExcludeOutOfSession; + HistoryRequestType = original.HistoryRequestType; + } + + public HistoryDescription ToDescription() + { + return new HistoryDescription(SymbolId, Aggregation); + } + } + public enum HistoryRequestType + { + General, + BuildUncompleteBarLogic + } + public class PercentageProgress : IProgress + { + [CompilerGenerated] + private float ?; + + public float ProgressValue + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = num; + } + } + + public void Report(float value) + { + ProgressValue = value; + } + + public override string ToString() + { + return ProgressValue.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), CultureInfo.DefaultThreadCurrentUICulture); + } + } + /// + /// Represents mechanism for supporting predefined and custom periods + /// + [Serializable] + [Published] + [DataContract(Name = "Period", Namespace = "TradingPlatform")] + [ProtoContract] + public struct Period : IComparable, IXElementSerialization + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private BasePeriod ??; + + /// + /// Gets period multiplier + /// + [DataMember(Name = "PeriodMultiplier")] + [ProtoMember(1)] + public int PeriodMultiplier + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Gets base period type + /// + [DataMember(Name = "BasePeriod")] + [ProtoMember(2)] + public BasePeriod BasePeriod + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = basePeriod; + } + } + + /// + /// Gets ticks value as an result of base period multiplicated by + /// + public long Ticks => TicksInBasePeriod(BasePeriod) * PeriodMultiplier; + + public TimeSpan Duration => TimeSpan.FromTicks(Ticks); + + /// + /// Predefined period + /// + public static Period TICK1 => new Period(BasePeriod.Tick, 1); + + /// + /// Predefined period + /// + public static Period SECOND1 => new Period(BasePeriod.Second, 1); + + /// + /// Predefined period + /// + public static Period SECOND5 => new Period(BasePeriod.Second, 5); + + /// + /// Predefined period + /// + public static Period SECOND10 => new Period(BasePeriod.Second, 10); + + /// + /// Predefined period + /// + public static Period SECOND15 => new Period(BasePeriod.Second, 15); + + /// + /// Predefined period + /// + public static Period SECOND30 => new Period(BasePeriod.Second, 30); + + /// + /// Predefined period + /// + public static Period MIN1 => new Period(BasePeriod.Minute, 1); + + /// + /// Predefined period + /// + public static Period MIN2 => new Period(BasePeriod.Minute, 2); + + /// + /// Predefined period + /// + public static Period MIN3 => new Period(BasePeriod.Minute, 3); + + /// + /// Predefined period + /// + public static Period MIN4 => new Period(BasePeriod.Minute, 4); + + /// + /// Predefined period + /// + public static Period MIN5 => new Period(BasePeriod.Minute, 5); + + /// + /// Predefined period + /// + public static Period MIN10 => new Period(BasePeriod.Minute, 10); + + /// + /// Predefined period + /// + public static Period MIN15 => new Period(BasePeriod.Minute, 15); + + /// + /// Predefined period + /// + public static Period MIN30 => new Period(BasePeriod.Minute, 30); + + /// + /// Predefined period + /// + public static Period HOUR1 => new Period(BasePeriod.Hour, 1); + + /// + /// Predefined period + /// + public static Period HOUR2 => new Period(BasePeriod.Hour, 2); + + /// + /// Predefined period + /// + public static Period HOUR3 => new Period(BasePeriod.Hour, 3); + + /// + /// Predefined period + /// + public static Period HOUR4 => new Period(BasePeriod.Hour, 4); + + /// + /// Predefined period + /// + public static Period HOUR6 => new Period(BasePeriod.Hour, 6); + + /// + /// Predefined period + /// + public static Period HOUR8 => new Period(BasePeriod.Hour, 8); + + /// + /// Predefined period + /// + public static Period HOUR12 => new Period(BasePeriod.Hour, 12); + + /// + /// Predefined period + /// + public static Period DAY1 => new Period(BasePeriod.Day, 1); + + /// + /// Predefined period + /// + public static Period WEEK1 => new Period(BasePeriod.Week, 1); + + /// + /// Predefined period + /// + public static Period MONTH1 => new Period(BasePeriod.Month, 1); + + /// + /// Predefined period + /// + public static Period YEAR1 => new Period(BasePeriod.Year, 1); + + /// + /// Creates Period instance with greater than 0 + /// + /// + /// + public Period(BasePeriod basePeriod, int periodMultiplier) + { + if (periodMultiplier <= 0) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + BasePeriod = basePeriod; + PeriodMultiplier = periodMultiplier; + } + + /// + /// True if their base paeriods and are respectively equal. + /// + /// + /// + /// + [NotPublished] + public static bool operator ==(Period period1, Period period2) + { + if (period1.BasePeriod == period2.BasePeriod) + { + return period1.PeriodMultiplier == period2.PeriodMultiplier; + } + return false; + } + + /// + /// True if any of their base paeriods and are respectively not equal. + /// + /// + /// + /// + [NotPublished] + public static bool operator !=(Period period1, Period period2) + { + if (period1.BasePeriod == period2.BasePeriod) + { + return period1.PeriodMultiplier != period2.PeriodMultiplier; + } + return true; + } + + /// + /// True if their ticks values are satisfying initial condition + /// + /// + /// + /// + [NotPublished] + public static bool operator <(Period period1, Period period2) + { + long ticks = period1.Ticks; + long ticks2 = period2.Ticks; + if (ticks < 0 && ticks2 < 0) + { + return ticks > ticks2; + } + return ticks < ticks2; + } + + /// + /// True if their ticks values are satisfying initial condition + /// + /// + /// + /// + [NotPublished] + public static bool operator >(Period period1, Period period2) + { + long ticks = period1.Ticks; + long ticks2 = period2.Ticks; + if (ticks < 0 && ticks2 < 0) + { + return ticks < ticks2; + } + return ticks > ticks2; + } + + /// + /// True if their ticks values are satisfying initial condition + /// + /// + /// + /// + [NotPublished] + public static bool operator <=(Period period1, Period period2) + { + long ticks = period1.Ticks; + long ticks2 = period2.Ticks; + if (ticks < 0 && ticks2 < 0) + { + return ticks >= ticks2; + } + return ticks <= ticks2; + } + + /// + /// True if their ticks values are satisfying initial condition + /// + /// + /// + /// + [NotPublished] + public static bool operator >=(Period period1, Period period2) + { + long ticks = period1.Ticks; + long ticks2 = period2.Ticks; + if (ticks < 0 && ticks2 < 0) + { + return ticks <= ticks2; + } + return ticks >= ticks2; + } + + /// + /// True if their base paeriods and are respectively equal. + /// + /// + /// + [NotPublished] + public override bool Equals(object obj) + { + if (obj is Period period) + { + if (BasePeriod == period.BasePeriod) + { + return PeriodMultiplier == period.PeriodMultiplier; + } + return false; + } + return false; + } + + [NotPublished] + public override int GetHashCode() + { + return PeriodMultiplier ^ (int)BasePeriod; + } + + /// + /// Formats given value to a specific user friendly string + /// + /// + /// + [NotPublished] + public string Format(DateTime dateTime) + { + switch (BasePeriod) + { + case BasePeriod.Tick: + if (PeriodMultiplier > 1) + { + return Core.Instance.TimeUtils.GetFormatedDateTime(dateTime); + } + return Core.Instance.TimeUtils.GetFormatedDateTimeWithMilliseconds(dateTime); + case BasePeriod.Second: + return Core.Instance.TimeUtils.GetFormatedDateTime(dateTime); + case BasePeriod.Minute: + case BasePeriod.Hour: + return Core.Instance.TimeUtils.GetFormatedDateShortTime(dateTime); + case BasePeriod.Day: + case BasePeriod.Week: + return Core.Instance.TimeUtils.GetFormatedDate(dateTime); + case BasePeriod.Month: + case BasePeriod.Year: + return Core.Instance.TimeUtils.GetFormatedDate(dateTime); + default: + return Core.Instance.TimeUtils.GetFormatedDate(dateTime); + } + } + + [NotPublished] + public string Format() + { + return $"{PeriodMultiplier}{BasePeriodToShortString(BasePeriod)}"; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 2); + defaultInterpolatedStringHandler.AppendFormatted(PeriodMultiplier); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(BasePeriod); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + /// + /// Returns value in ticks according to base period type + /// + /// + /// + public static long TicksInBasePeriod(BasePeriod basePeriod) + { + return basePeriod switch + { + BasePeriod.Tick => -1L, + BasePeriod.Second => 10000000L, + BasePeriod.Minute => 600000000L, + BasePeriod.Hour => 36000000000L, + BasePeriod.Day => 864000000000L, + BasePeriod.Week => 6048000000000L, + BasePeriod.Month => 25920000000000L, + BasePeriod.Year => 315360000000000L, + _ => throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + }; + } + + /// + /// Returns shorted string according to base period type + /// + /// + /// + public static string BasePeriodToShortString(BasePeriod basePeriod) + { + return basePeriod switch + { + BasePeriod.Tick => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Second => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Minute => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Hour => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Day => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Week => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Month => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + BasePeriod.Year => loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + _ => string.Empty, + }; + } + + /// + /// Converts time gap into dates range + /// + /// + /// + public void ToDatesRange(out DateTime from, out DateTime to) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + if (BasePeriod == BasePeriod.Day) + { + from = dateTimeUtcNow.AddDays(-PeriodMultiplier); + } + else if (BasePeriod == BasePeriod.Month) + { + from = dateTimeUtcNow.AddMonths(-PeriodMultiplier); + } + else if (BasePeriod == BasePeriod.Year) + { + from = dateTimeUtcNow.AddYears(-PeriodMultiplier); + } + else + { + from = dateTimeUtcNow.AddTicks(-Ticks); + } + to = dateTimeUtcNow; + } + + /// + /// Compares by + /// + /// + /// + [NotPublished] + public int CompareTo(object other) + { + return Ticks.CompareTo(((Period)other).Ticks); + } + + public static bool TryParse(string value, out Period period) + { + period = default(Period); + string[] array = value.Split('-'); + if (array.Length != 2) + { + return false; + } + if (!int.TryParse(array[0].Trim(), out var result)) + { + return false; + } + if (!Enum.TryParse(array[1].Trim(), ignoreCase: true, out var result2)) + { + return false; + } + period = new Period(result2, result); + return true; + } + + /// + /// Serialize into object + /// + /// + [NotPublished] + public XElement ToXElement() + { + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)BasePeriod).ToString()), new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PeriodMultiplier.ToString())); + } + + /// + /// Deserialize from + /// + /// + /// + [NotPublished] + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + BasePeriod = (BasePeriod)xElement.ToInt(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + PeriodMultiplier = xElement2.ToInt(); + } + } + } +} +namespace ? +{ + internal class ? : HistoryEventArgs + { + [CompilerGenerated] + private MessageQuote ??; + + public MessageQuote MessageQuote + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = messageQuote; + } + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// Represent access to DayBar quote, which contains summary information about instrument prices. + /// + [DataContract(Name = "DayBar", Namespace = "TradingPlatform")] + [ProtoContract] + [Published] + public class DayBar : MessageQuote, IXElementSerialization + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private bool ??; + + [NotPublished] + public override MessageType Type => MessageType.DayBar; + + /// + /// High price + /// + [DataMember(Name = "High")] + [ProtoMember(1)] + public double High + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Open price + /// + [DataMember(Name = "Open")] + [ProtoMember(2)] + public double Open + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Low price + /// + [DataMember(Name = "Low")] + [ProtoMember(3)] + public double Low + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Previous Close price + /// + [DataMember(Name = "PreviousClose")] + [ProtoMember(4)] + public double PreviousClose + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Ticks value + /// + [DataMember(Name = "Ticks")] + [ProtoMember(5)] + public long Ticks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Volume value + /// + [DataMember(Name = "Volume")] + [ProtoMember(6)] + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Volume value + /// + [DataMember(Name = "quoteAssetVolume")] + [ProtoMember(7)] + public double QuoteAssetVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Previous settlement price + /// + [DataMember(Name = "PrevSettlementPrice")] + [ProtoMember(8)] + public double PrevSettlementPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Bid price + /// + [DataMember(Name = "Bid")] + [ProtoMember(9)] + public double Bid + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Bid size + /// + [DataMember(Name = "BidSize")] + [ProtoMember(10)] + public double BidSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Ask price + /// + [DataMember(Name = "Ask")] + [ProtoMember(11)] + public double Ask + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Ask size + /// + [DataMember(Name = "AskSize")] + [ProtoMember(12)] + public double AskSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Last price + /// + [DataMember(Name = "Last")] + [ProtoMember(13)] + public double Last + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Last size + /// + [DataMember(Name = "LastSize")] + [ProtoMember(14)] + public double LastSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Trades value + /// + [DataMember(Name = "Trades")] + [ProtoMember(15)] + public long Trades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Change value + /// + [DataMember(Name = "Change")] + [ProtoMember(16)] + public double Change + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Change value in percentage + /// + [DataMember(Name = "ChangePercentage")] + [ProtoMember(17)] + public double ChangePercentage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// + /// + [DataMember(Name = "OpenInterest")] + [ProtoMember(18)] + public double OpenInterest + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TopPriceLimit")] + [ProtoMember(19)] + public double TopPriceLimit + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "BottomPriceLimit")] + [ProtoMember(20)] + public double BottomPriceLimit + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AverageTradedPrice")] + [ProtoMember(21)] + public double AverageTradedPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TotalBuyQuantity")] + [ProtoMember(22)] + public double TotalBuyQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TotalSellQuantity")] + [ProtoMember(23)] + public double TotalSellQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "IV")] + [ProtoMember(24)] + public double IV + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Delta")] + [ProtoMember(25)] + public double Delta + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Vega")] + [ProtoMember(26)] + public double Vega + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Gamma")] + [ProtoMember(27)] + public double Gamma + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Theta")] + [ProtoMember(28)] + public double Theta + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Rho")] + [ProtoMember(29)] + public double Rho + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Mark")] + [ProtoMember(30)] + public double Mark + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "MarkSize")] + [ProtoMember(31)] + public double MarkSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "FundingRate")] + [ProtoMember(32)] + public double FundingRate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "FundingTime")] + [ProtoMember(33)] + public DateTime FundingTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + internal bool FullRefresh + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + + private DayBar() + { + } + + [NotPublished] + public DayBar(string symbolId, DateTime time) + : base(symbolId, time) + { + High = double.NaN; + Open = double.NaN; + Low = double.NaN; + PreviousClose = double.NaN; + Ticks = -1L; + Volume = double.NaN; + QuoteAssetVolume = double.NaN; + PrevSettlementPrice = double.NaN; + Bid = double.NaN; + BidSize = double.NaN; + Ask = double.NaN; + AskSize = double.NaN; + Last = double.NaN; + LastSize = double.NaN; + Mark = double.NaN; + Trades = -1L; + Change = double.NaN; + ChangePercentage = double.NaN; + OpenInterest = double.NaN; + TopPriceLimit = double.NaN; + BottomPriceLimit = double.NaN; + AverageTradedPrice = double.NaN; + TotalBuyQuantity = double.NaN; + TotalSellQuantity = double.NaN; + IV = double.NaN; + Delta = double.NaN; + Vega = double.NaN; + Gamma = double.NaN; + Theta = double.NaN; + Rho = double.NaN; + FundingRate = double.NaN; + FundingTime = default(DateTime); + } + + [NotPublished] + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.SymbolId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Ask)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AskSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Bid)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BidSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Last)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LastSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), Mark); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Open)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), High)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Low)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PreviousClose)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Ticks)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Trades)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Volume)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuoteAssetVolume)); + return xElement; + } + + [NotPublished] + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + base.SymbolId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Ask = xElement2.ToDouble(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + AskSize = xElement3.ToDouble(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + Bid = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + BidSize = xElement5.ToDouble(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + Last = xElement6.ToDouble(); + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + LastSize = xElement7.ToDouble(); + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + Mark = xElement8.ToDouble(); + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + Open = xElement9.ToDouble(); + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + High = xElement10.ToDouble(); + } + XElement xElement11 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + Low = xElement11.ToDouble(); + } + XElement xElement12 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + PreviousClose = xElement12.ToDouble(); + } + XElement xElement13 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement13 != null) + { + Ticks = xElement13.ToLong(); + } + XElement xElement14 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement14 != null) + { + Trades = xElement14.ToLong(); + } + XElement xElement15 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + if (xElement15 != null) + { + Volume = xElement15.ToDouble(); + } + XElement xElement16 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement16 != null) + { + QuoteAssetVolume = xElement16.ToDouble(); + } + } + } + /// + /// Represent access to DOM2 quote, which contains Bids and Asks. + /// + [DataContract(Name = "DOMQuote", Namespace = "TradingPlatform")] + [ProtoContract] + [Published] + public class DOMQuote : MessageQuote + { + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private List ??; + + [NotPublished] + public override MessageType Type => MessageType.DOM; + + /// + /// Collection of Asks quotes + /// + [DataMember(Name = "Asks")] + [ProtoMember(1)] + public List Asks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Collection of Bids quotes + /// + [DataMember(Name = "Bids")] + [ProtoMember(2)] + public List Bids + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + private DOMQuote() + { + } + + [NotPublished] + public DOMQuote(string symbolId, DateTime time) + : base(symbolId, time) + { + Asks = new List(); + Bids = new List(); + } + + [NotPublished] + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); + handler.AppendFormatted(base.ToString()); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder2.Append(ref handler); + foreach (Level2Quote ask in Asks) + { + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(ask.ToString()); + } + foreach (Level2Quote bid in Bids) + { + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(bid.ToString()); + } + return stringBuilder.ToString(); + } + } + /// + /// Represent access to trade information. + /// + [DataContract(Name = "Last", Namespace = "TradingPlatform")] + [ProtoContract] + [Published] + public class Last : MessageQuote, IVolumeTickData, IBuyerSellerData + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private AggressorFlag ??; + + [CompilerGenerated] + private TickDirection ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [NotPublished] + public override MessageType Type => MessageType.Last; + + /// + /// Price at which trade occured + /// + [DataMember(Name = "Price")] + [ProtoMember(1)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Size of the trade + /// + [DataMember(Name = "Size")] + [ProtoMember(2)] + public double Size + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Information about operation side of the trade + /// + [DataMember(Name = "AggressorFlag")] + [ProtoMember(3)] + public AggressorFlag AggressorFlag + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Shows the direction of price movement, comparing to previous value. + /// + [DataMember(Name = "TickDirection")] + [ProtoMember(4)] + public TickDirection TickDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "OpenInterest")] + [ProtoMember(5)] + public double OpenInterest + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Buyer")] + [ProtoMember(6)] + public string Buyer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Seller")] + [ProtoMember(7)] + public string Seller + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TradeId")] + [ProtoMember(8)] + public string TradeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "QuoteAssetVolume")] + [ProtoMember(9)] + public double QuoteAssetVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + VolumeTickDataType IVolumeTickData.VolumeTickDataType => VolumeTickDataType.Lasts; + + long IVolumeTickData.Time => base.Time.Ticks; + + double IVolumeTickData.Volume => Size; + + private Last() + { + } + + [NotPublished] + public Last(string symbol, double price, double size, DateTime time) + : base(symbol, time) + { + OpenInterest = double.NaN; + Price = price; + Size = size; + QuoteAssetVolume = double.NaN; + AggressorFlag = AggressorFlag.NotSet; + TickDirection = TickDirection.NotSet; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(23, 4); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Size); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TradeId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + /// + /// Represent access to Level2 quote. + /// + [DataContract(Name = "Level2Quote", Namespace = "TradingPlatform")] + [ProtoContract] + [Published] + public class Level2Quote : MessageQuote + { + [CompilerGenerated] + private QuotePriceType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private int ??; + + [NotPublished] + public override MessageType Type => MessageType.Level2; + + /// + /// Price type of Level2 quote: Bid or Ask + /// + [DataMember(Name = "PriceType")] + [ProtoMember(1)] + public QuotePriceType PriceType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = quotePriceType; + } + } + + /// + /// Price of Level2 quote + /// + [DataMember(Name = "Price")] + [ProtoMember(2)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Size of Level2 quote + /// + [DataMember(Name = "Size")] + [ProtoMember(3)] + public double Size + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Unique ID of Level2 quote + /// + [DataMember(Name = "Id")] + [ProtoMember(4)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Shows, whether Level2 quote is using only for removing from depth + /// + [DataMember(Name = "Closed")] + [ProtoMember(5)] + public bool Closed + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Broker identifier that send level2 quote + /// + [DataMember(Name = "Broker")] + [ProtoMember(6)] + public string Broker + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// specifies the implied quantity associated with the price for the quote. Subtracting this amount from the Size yields the outright quantity for the price level. A value of zero indicates that the implied size is not available/defined or that it is actually zero. + /// + [DataMember(Name = "ImpliedSize")] + [ProtoMember(7)] + public double ImpliedSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Priority")] + [ProtoMember(8)] + public long Priority + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Number orders of Level2 quote + /// + [DataMember(Name = "NumberOrders")] + [ProtoMember(9)] + public int NumberOrders + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + private Level2Quote() + { + } + + [NotPublished] + public Level2Quote(QuotePriceType priceType, string symbolId, string id, double price, double size, DateTime time) + : base(symbolId, time) + { + PriceType = priceType; + Price = price; + Size = size; + Id = id; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(33, 5); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Size); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Closed); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [DataContract(Name = "Mark", Namespace = "TradingPlatform")] + [ProtoContract] + [Published] + public class Mark : MessageQuote + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [NotPublished] + public override MessageType Type => MessageType.Mark; + + [DataMember(Name = "Price")] + [ProtoMember(1)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + [DataMember(Name = "Size")] + [ProtoMember(2)] + public double Size + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + private Mark() + { + } + + [NotPublished] + public Mark(string symbol, DateTime time, double price, double size = double.NaN) + : base(symbol, time) + { + Price = price; + Size = size; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 3); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Size); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [Serializable] + [KnownType(typeof(Level2Quote))] + [KnownType(typeof(Last))] + [KnownType(typeof(Quote))] + [KnownType(typeof(DOMQuote))] + [KnownType(typeof(DayBar))] + [KnownType(typeof(Mark))] + [DataContract(Name = "MessageQuote", Namespace = "TradingPlatform")] + [ProtoContract] + [ProtoInclude(3, typeof(Quote))] + [ProtoInclude(4, typeof(Last))] + [ProtoInclude(5, typeof(Level2Quote))] + [ProtoInclude(6, typeof(DOMQuote))] + [ProtoInclude(7, typeof(DayBar))] + [ProtoInclude(8, typeof(Mark))] + public abstract class MessageQuote : Message + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [DataMember(Name = "Symbol")] + [ProtoMember(1)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected internal set + { + ?? = value; + } + } + + /// + /// Time of the quote + /// + [DataMember(Name = "Time")] + [ProtoMember(2)] + public DateTime Time + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + private protected MessageQuote() + { + } + + protected MessageQuote(string symbolId, DateTime time) + { + SymbolId = symbolId; + Time = time; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(5, 4); + defaultInterpolatedStringHandler.AppendFormatted(Time.Ticks); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Time); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + /// + /// Represent access to quote information. + /// + [DataContract(Name = "Quote", Namespace = "TradingPlatform")] + [ProtoContract] + [Published] + public class Quote : MessageQuote, IVolumeTickData + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private TickDirection ??; + + [CompilerGenerated] + private TickDirection ??; + + [NotPublished] + public override MessageType Type => MessageType.Quote; + + /// + /// Bid price + /// + [DataMember(Name = "Bid")] + [ProtoMember(1)] + public double Bid + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Bid size + /// + [DataMember(Name = "BidSize")] + [ProtoMember(2)] + public double BidSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Ask price + /// + [DataMember(Name = "Ask")] + [ProtoMember(3)] + public double Ask + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Ask size + /// + [DataMember(Name = "AskSize")] + [ProtoMember(4)] + public double AskSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Shows the direction of bid price movement, comparing to previous value. + /// + [DataMember(Name = "BidTickDirection")] + [ProtoMember(5)] + public TickDirection BidTickDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = tickDirection; + } + } + + /// + /// Shows the direction of ask price movement, comparing to previous value. + /// + [DataMember(Name = "AskTickDirection")] + [ProtoMember(6)] + public TickDirection AskTickDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = tickDirection; + } + } + + VolumeTickDataType IVolumeTickData.VolumeTickDataType => VolumeTickDataType.Ticks; + + long IVolumeTickData.Time => base.Time.Ticks; + + double IVolumeTickData.Price => Bid; + + double IVolumeTickData.Volume => 1.0; + + TickDirection IVolumeTickData.TickDirection => BidTickDirection; + + AggressorFlag IVolumeTickData.AggressorFlag => Symbol.ConvertTickDirection(BidTickDirection); + + private Quote() + { + } + + [NotPublished] + public Quote(string symbol, double bid, double bidSize, double ask, double askSize, DateTime time) + : base(symbol, time) + { + Bid = bid; + BidSize = bidSize; + Ask = ask; + AskSize = askSize; + BidTickDirection = TickDirection.NotSet; + AskTickDirection = TickDirection.NotSet; + } + + [NotPublished] + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(36, 5); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Bid); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Ask); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(BidSize); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(AskSize); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + /// + /// Specifies the reason of price data updating. + /// + public enum UpdateReason + { + Unknown, + /// + /// Indicates the processing of new historical bar. + /// + HistoricalBar, + /// + /// Indicates the coming of new real-time tick. + /// + NewTick, + /// + /// Indicates a start of new real-time bar. + /// + NewBar + } + /// + /// Specifies the type of events when indicator should recalculate itself. + /// + public enum IndicatorUpdateType + { + OnTick, + OnBarClose + } + /// + /// Specifies the style of indicator line. + /// + [Published] + public enum LineStyle + { + [Description("Solid")] + Solid, + [Description("Dash")] + Dash, + [Description("Dot")] + Dot, + [Description("Dash dot")] + DashDot, + [Description("Histogramm")] + Histogramm, + [Description("Points")] + Points, + [Description("Columns")] + Columns, + [Description("Step line")] + StepLine + } + [Published] + public enum StrategyState + { + Created = 10, + Working = 20, + Stopped = 30, + Removed = 40, + WaitingForConnection = 50 + } + [Published] + public enum StrategyLoggingLevel + { + Info, + Trading, + Error + } + /// + /// Moving average mode + /// + [Published] + public enum MaMode + { + /// + /// Simple Moving Average + /// + SMA, + /// + /// Exponential Moving Average + /// + EMA, + /// + /// Smoothed Moving Average + /// + SMMA, + /// + /// Linearly Weighted Moving Average + /// + LWMA + } + public enum AfirmaMode + { + Hanning, + Hamming, + Blackman, + BlackmanHarris + } + public enum RSIMode + { + Simple, + Exponential + } + public enum AMATrendType + { + Fixed, + Average + } + /// + /// + /// + public enum HVSheduleMode + { + /// + /// Displays HV schedule and percentile value. + /// + HV, + /// + /// Displays the percentile schedule only. + /// + Percentile + } + public enum ScriptCreationType + { + [Description("Default")] + [EnumMember(Value = "Default")] + Default, + [Description("Custom")] + [EnumMember(Value = "Custom")] + Custom + } + [NotPublished] + public enum TemplateType + { + Indicator, + DrawingTool + } + [NotPublished] + public enum IndicatorCalculationType + { + ByPeriod, + AllAvailableData + } + public abstract class ExecutionEntity : IDisposable, ICustomizable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(FieldInfo P_0) + { + return Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + + internal bool ?(PropertyInfo P_0) + { + return Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + + internal bool ?(FieldInfo P_0) + { + if (??.IsAssignableFrom(P_0.FieldType)) + { + return !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + return false; + } + + internal bool ?(PropertyInfo P_0) + { + if (??.IsAssignableFrom(P_0.PropertyType)) + { + return !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + return false; + } + + internal bool ?(FieldInfo P_0) + { + return Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + + internal bool ?(PropertyInfo P_0) + { + return Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + + internal bool ?(FieldInfo P_0) + { + if (??.IsAssignableFrom(P_0.FieldType)) + { + return !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + return false; + } + + internal bool ?(PropertyInfo P_0) + { + if (??.IsAssignableFrom(P_0.PropertyType)) + { + return !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)); + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public SettingItem ??; + + internal bool ?(SettingItem P_0) + { + return P_0.Name == ??.Name; + } + } + + [CompilerGenerated] + private sealed class ? + { + public SettingItem ??; + + internal bool ?(SettingItem P_0) + { + return P_0.Name == ??.Name; + } + } + + private static readonly Type ??; + + private static readonly Dictionary ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private ScriptKey ??; + + [CompilerGenerated] + private readonly Version ??; + + [CompilerGenerated] + private Action ??; + + private readonly Type ??; + + [CompilerGenerated] + private bool ??; + + protected static Core Core => Core.Instance; + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public ScriptKey Key + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = scriptKey; + } + } + + public Version Version + { + [CompilerGenerated] + get + { + return ??; + } + } + + public virtual IList Settings + { + get + { + List list = new List(); + SettingItemSeparatorGroup separatorGroup = new SettingItemSeparatorGroup(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), -1000) + { + Key = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + foreach (FieldInfo item in from P_0 in ??.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0) + { + InputParameterAttribute customAttribute = item.GetCustomAttribute(inherit: true); + object value = item.GetValue(this); + SettingItem ?? = ?(customAttribute, item.FieldType, item.Name, value); + if (?? != null) + { + if (list.Any((SettingItem P_0) => P_0.Name == ??.Name)) + { + Core.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ??.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + else + { + list.Add(??); + } + } + } + foreach (PropertyInfo item2 in from P_0 in ??.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0) + { + InputParameterAttribute customAttribute2 = item2.GetCustomAttribute(inherit: true); + object value2 = item2.GetValue(this); + SettingItem ?? = ?(customAttribute2, item2.PropertyType, item2.Name, value2); + if (?? != null) + { + if (list.Any((SettingItem P_0) => P_0.Name == ??.Name)) + { + Core.Loggers.Log(Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ??.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + else + { + list.Add(??); + } + } + } + foreach (FieldInfo item3 in from P_0 in ??.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where ??.IsAssignableFrom(P_0.FieldType) && !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0) + { + if (item3.GetValue(this) is SettingItem settingItem) + { + list.Add(settingItem.GetCopy()); + } + } + foreach (PropertyInfo item4 in from P_0 in ??.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where ??.IsAssignableFrom(P_0.PropertyType) && !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0) + { + if (item4.GetValue(this) is SettingItem settingItem2) + { + list.Add(settingItem2.GetCopy()); + } + } + list.Add(new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Key.ToString()) + { + VisibilityMode = VisibilityMode.Hidden + }); + for (int num = 0; num < list.Count; num++) + { + list[num].SeparatorGroup = separatorGroup; + } + return list; + } + set + { + if (value == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + bool flag = false; + Dictionary dictionary = null; + Dictionary dictionary2 = null; + IEnumerable enumerable = from P_0 in ??.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0; + IEnumerable enumerable2 = from P_0 in ??.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0; + if (enumerable.Count() > 0) + { + dictionary = new Dictionary(); + foreach (FieldInfo item in enumerable) + { + InputParameterAttribute customAttribute = item.GetCustomAttribute(inherit: true); + string key = (string.IsNullOrEmpty(customAttribute.Name) ? item.Name : customAttribute.Name); + dictionary.TryAdd(key, item); + } + } + if (enumerable2.Count() > 0) + { + dictionary2 = new Dictionary(); + foreach (PropertyInfo item2 in enumerable2) + { + InputParameterAttribute customAttribute2 = item2.GetCustomAttribute(inherit: true); + string key2 = (string.IsNullOrEmpty(customAttribute2.Name) ? item2.Name : customAttribute2.Name); + dictionary2.TryAdd(key2, item2); + } + } + foreach (SettingItem item3 in value) + { + object value2; + if (item3.Type == SettingItemType.SelectorLocalized) + { + if (!(item3.Value is SelectItem selectItem)) + { + continue; + } + value2 = selectItem.Value; + } + else + { + value2 = item3.Value; + } + FieldInfo value3 = null; + if (dictionary != null && dictionary.TryGetValue(item3.Name, out value3)) + { + value3.SetValue(this, value2); + flag = true; + continue; + } + PropertyInfo value4 = null; + if (dictionary2 != null && dictionary2.TryGetValue(item3.Name, out value4)) + { + value4.SetValue(this, value2); + flag = true; + } + } + foreach (FieldInfo item4 in from P_0 in ??.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where ??.IsAssignableFrom(P_0.FieldType) && !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0) + { + if (item4.GetValue(this) is SettingItem settingItem) + { + flag |= settingItem.?(value); + } + } + foreach (PropertyInfo item5 in from P_0 in ??.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + where ??.IsAssignableFrom(P_0.PropertyType) && !Attribute.IsDefined(P_0, typeof(InputParameterAttribute)) + select P_0) + { + if (item5.GetValue(this) is SettingItem settingItem2) + { + flag |= settingItem2.?(value); + } + } + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemString settingItemString && !string.IsNullOrEmpty(settingItemString.Value as string)) + { + Key = ScriptKey.CreateScriptKeyFromString(settingItemString.Value.ToString()); + } + if (flag) + { + OnSettingsUpdated(); + } + } + } + + private protected bool Disposed + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public event Action OnDispose + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + static ExecutionEntity() + { + ?? = typeof(SettingItem); + ?? = new Dictionary + { + { + typeof(bool), + SettingItemType.Boolean + }, + { + typeof(int), + SettingItemType.Integer + }, + { + typeof(string), + SettingItemType.String + }, + { + typeof(long), + SettingItemType.Integer + }, + { + typeof(double), + SettingItemType.Double + }, + { + typeof(decimal), + SettingItemType.Double + }, + { + typeof(DateTime), + SettingItemType.DateTime + }, + { + typeof(Period), + SettingItemType.Period + }, + { + typeof(Account), + SettingItemType.Account + }, + { + typeof(Symbol), + SettingItemType.Symbol + }, + { + typeof(Color), + SettingItemType.Color + }, + { + typeof(PairColor), + SettingItemType.PairColor + }, + { + typeof(LineOptions), + SettingItemType.LineOptions + } + }; + } + + protected ExecutionEntity() + { + ?? = GetType(); + string text = ??.Assembly.?(); + ?? = (string.IsNullOrEmpty(text) ? null : new Version(text)); + } + + public virtual void Dispose() + { + Disposed = true; + ???.Invoke(this); + } + + protected virtual void OnSettingsUpdated() + { + } + + protected void CheckDisposed() + { + if (Disposed) + { + throw new ObjectDisposedException(Name); + } + } + + private static SettingItem ?(InputParameterAttribute P_0, Type P_1, string P_2, object P_3) + { + string name = (string.IsNullOrEmpty(P_0.Name) ? P_2 : P_0.Name); + int sortIndex = P_0.SortIndex; + double minimum = P_0.Minimum; + double maximum = P_0.Maximum; + double increment = P_0.Increment; + int decimalPlaces = P_0.DecimalPlaces; + SettingItem result = null; + SettingItemType value2; + if (P_0.Variants != null) + { + if (P_0.Variants.Length % 2 != 0) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IComparable comparable = P_3 as IComparable; + if (comparable == null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + List list = new List(); + SelectItem value = null; + for (int i = 0; i < P_0.Variants.Length; i += 2) + { + IComparable comparable2 = P_0.Variants[i + 1]; + if (comparable2 == null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (comparable2.GetType() != P_1) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(70, 2); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1); + throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + if (comparable2 is Enum) + { + comparable2 = (int)(object)comparable2; + comparable = (int)(object)comparable; + } + SelectItem selectItem = new SelectItem(P_0.Variants[i].ToString(), comparable2); + list.Add(selectItem); + if (comparable2.CompareTo(comparable) == 0) + { + value = selectItem; + } + } + result = new SettingItemSelectorLocalized(name, value, list, sortIndex); + } + else if (??.TryGetValue(P_1, out value2)) + { + SettingItem settingItem; + switch (value2) + { + case SettingItemType.Boolean: + settingItem = new SettingItemBoolean(name, P_3 != null && (bool)P_3, sortIndex); + break; + case SettingItemType.Integer: + settingItem = new SettingItemInteger(name, (P_3 != null) ? ((int)P_3) : 0, sortIndex) + { + Minimum = (int)minimum, + Maximum = (int)maximum, + Increment = Math.Max((int)increment, 1) + }; + break; + case SettingItemType.String: + settingItem = new SettingItemString(name, (P_3 == null) ? null : ((string)P_3), sortIndex); + break; + case SettingItemType.Double: + settingItem = new SettingItemDouble(name, (P_3 == null) ? 0.0 : ((double)P_3), sortIndex) + { + Minimum = minimum, + Maximum = maximum, + Increment = increment, + DecimalPlaces = decimalPlaces + }; + break; + case SettingItemType.DateTime: + settingItem = new SettingItemDateTime(name, (P_3 == null) ? default(DateTime) : ((DateTime)P_3), sortIndex); + break; + case SettingItemType.Period: + settingItem = new SettingItemPeriod(name, (P_3 == null) ? default(Period) : ((Period)P_3), sortIndex); + break; + case SettingItemType.Account: + settingItem = new SettingItemAccount(name, (P_3 == null) ? null : ((Account)P_3), sortIndex); + break; + case SettingItemType.Symbol: + settingItem = new SettingItemSymbol(name, (P_3 == null) ? null : ((Symbol)P_3), sortIndex); + break; + case SettingItemType.Color: + settingItem = new SettingItemColor(name, (P_3 == null) ? default(Color) : ((Color)P_3), sortIndex); + break; + case SettingItemType.PairColor: + settingItem = new SettingItemPairColor(name, (P_3 == null) ? null : ((PairColor)P_3), sortIndex); + break; + case SettingItemType.LineOptions: + settingItem = new SettingItemLineOptions(name, (P_3 == null) ? null : ((LineOptions)P_3), sortIndex); + break; + default: + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(37, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_3.GetType()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + result = settingItem; + } + return result; + } + } + [Published] + public sealed class BuiltInIndicators + { + private readonly IIndicatorsCollection ?; + + internal BuiltInIndicators(IIndicatorsCollection P_0 = null) + { + ? = P_0; + } + + private void ?(Indicator P_0) + { + ??.AddIndicator(P_0); + } + + /// + /// Returns an instance of the Exponential Moving Average (EMA) indicator. + /// EMA provides a weighted price calculation for the last N periods. + /// + /// Period of Exponential Moving Average + /// Sources prices for MA + /// Calculation type + public Indicator EMA(int maPeriod, PriceType priceType, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), maPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Linearly Weighted Moving Average + /// Linear Weighted Moving Average makes the most recent bar more important unlike SMA. + /// + /// Moving average period + /// Type of the price + /// + public Indicator LWMA(int maPeriod, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), maPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the SMA(Simple Moving Average) indicator. + /// The 'SMA' indicator provides an average price for the last N periods. + /// + /// Period of simple moving average. + /// Sources prices for MA. + /// + public Indicator SMA(int period, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Smoothed Moving Average (SMMA) indicator. + /// SMMA indicator provides a smoothed average price for the last N periods. + /// + /// Moving average period + /// Type of the price + /// Calculation type + /// + public Indicator SMMA(int period, PriceType priceType, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the PPMA(Pivot Point Moving Average) indicator. + /// The 'PPMA' indicator uses the pivot point calculation as the input a simple moving average. + /// + /// Period of PPMA indicator + /// + /// + public Indicator PPMA(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the MAS3 (3MASignal) indicator. + /// The 'MAS3' indicator offers buy and sell signals according to intersections of three moving averages. + /// + /// Short moving average period. + /// Middle moving average period. + /// Long moving average period. + /// The count of bars. The trend will be determined on this interval. + /// + /// + public Indicator MAS3(int shortPeriod, int middlePeriod, int longPeriod, int barsInterval) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), shortPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), middlePeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), longPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), barsInterval); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the specific MA indicator, according to selected 'MaMode'. + /// + /// Period of moving average. + /// Type of price. + /// MA mode. + /// Calculation type + /// + /// + public Indicator MA(int period, PriceType priceType, MaMode maMode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + return maMode switch + { + MaMode.SMA => SMA(period, priceType), + MaMode.EMA => EMA(period, priceType, calculationType), + MaMode.SMMA => SMMA(period, priceType, calculationType), + MaMode.LWMA => LWMA(period, priceType), + _ => null, + }; + } + + /// + /// Gets the BB(Bollinger Bands) indicator. + /// The 'BB' indicator provides a relative definition of high and low based on standard deviation and a simple moving average. + /// + /// Period of MA for envelopes. + /// Value of confidence interval. + /// Sources prices for MA. + /// Type of moving average. + /// Calculation type + /// + public Indicator BB(int period, double coefficient, PriceType priceType, MaMode maMode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), coefficient); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(maMode.ToString(), (int)maMode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Commodity Channel Index. + /// Measures the position of price in relation to its moving average. + /// + /// Period for CCI MA + /// Sources prices for CCI + /// MA mode for CCI + /// Calculation type + /// + public Indicator CCI(int maPeriod, PriceType priceType, MaMode maMode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), maPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(maMode.ToString(), (int)maMode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Modified Moving Average (MMA) indicator. + /// MMA comprises a sloping factor to help it overtake with the growing or declining value of the trading price of the currency. + /// + /// Period of Modified Moving Average + /// Sources prices for MA + /// + public Indicator MMA(int maPeriod, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), maPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Regression indicator + /// The Linear Regression Indicator plots the ending value of a Linear Regression Line for a specified number of bars; showing, statistically, where the price is expected to be. + /// + /// Moving average period + /// Type of the price + /// + public Indicator Regression(int period, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Channel (Price Channel) indicator. + /// The 'Channel' indicator is based on measurement of min and max prices for the definite number of periods. + /// + /// Period of price channel + /// + /// + public Indicator Channel(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the AFIRMA indicator + /// Autoregressive finite impulse response moving average. A digital filter accurately shows the price movement as powered with least square method to minimise time lag + /// + /// Moving average period + /// Type of the price + /// Afirma mode + /// with least squares method overlapping if true + /// + public Indicator AFIRMA(int period, PriceType priceType, AfirmaMode afirmaMode, bool least_squares_method) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(afirmaMode.ToString(), (int)afirmaMode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), least_squares_method); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the RSI indicator. + /// Relative Strength Index (RSI) is a momentum oscillator that measures the speed and change of price movements. + /// + /// RSI Period + /// Price Type + /// RSI Mode (Simple or Exponential) + /// MA Mode for smooth data + /// MA period for smooth data + /// Calculation type + /// + public Indicator RSI(int period, PriceType priceType, RSIMode rsiMode, MaMode maMode, int maperiod, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(rsiMode.ToString(), (int)rsiMode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(maMode.ToString(), (int)maMode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), maperiod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the McGinley Dynamic indicator. + /// McGinley Dynamic avoids of most whipsaws and it rapidly moves up or down according to a quickly changing market. It needs no adjusting because it is dynamic and it adjusts itself. + /// + /// Period of exponential moving average + /// Dynamic tracking factor + /// Source price type + /// Calculation type + /// + public Indicator MD(int period, int trackingFactor, PriceType priceType, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), trackingFactor); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the MAE (Moving Average Envelope) indicator. + /// The 'MAE' indicator demonstrates a range of the prices discrepancy from a Moving Average. + /// + /// Period of MA for envelopes. + /// Sources prices for MA. + /// Type of moving average. + /// Upband deviation in %. + /// Downband deviation in %. + /// Calculation type + /// + public Indicator MAE(int period, PriceType priceType, MaMode maMode, double upShift, double downShift, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(maMode.ToString(), (int)maMode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), upShift); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), downShift); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Parabolic Time/Price System (SAR) indicator. + /// SAR indicator helps to define the direction of the prevailing trend and the moment to close positions opened during the reversal. + /// + /// Step of parabolic SAR system + /// Maximum value for the acceleration factor + /// + /// + public Indicator SAR(double step, double maximum) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), step); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), maximum); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the AO (Awesome Oscillator) indicator. + /// The 'AO' indicator determines market momentum. + /// + /// + public Indicator AO() + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + ?(indicator); + return indicator; + } + + /// + /// Gets the CMO (Chande Momentum Oscillator) indicator. + /// The CMO calculates the dividing of difference between the sum of all recent gains and the sum of all recent losses by the sum of all price movement over the period. + /// + /// Period of MA for envelopes. + /// Sources prices for MA. + /// + /// + public Indicator CMO(int period, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the ZigZag indicator. + /// ZigZag is a trend following indicator that is used to predict when a given symbol's momentum is reversing. + /// + /// Percent Deviation + /// + /// + public Indicator ZZ(double deviation) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), deviation); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Aroon indicator. + /// Reveals the beginning of a new trend and determines how strong it is + /// + /// Aroons period + /// + /// + public Indicator AROON(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Standart Deviation (SD) indicator. + /// The SD shows the difference of the volatility value from the average one. + /// + /// Period of indicator + /// Sources prices for MA + /// Type of Moving Average + /// Calculation type + /// + public Indicator SD(int period, PriceType priceType, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the MACD (Moving Average Convergence/Divergence) indicator. + /// The MACD is a trend-following momentum indicator that shows the relationship between two moving averages of prices. + /// + /// Period of fast EMA. + /// Period of slow EMA. + /// Period of signal EMA. + /// Calculation type + /// + public Indicator MACD(int fastEMA, int slowEMA, int signalEMA, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), fastEMA); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), slowEMA); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), signalEMA); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Kairi Relative Index (KRI) indicator. + /// KRI calculates deviation of the current price from its simple moving average as a percent of the moving average. + /// + /// + /// + /// + public Indicator KRI(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Bollinger Bands Flat (BBF) indicator. + /// The BBF provides the same data as BB, but drawn in separate field and easier to recognize whether price is in or out of the band. + /// + /// Period + /// Deviation + /// Sources prices for MA + /// Type of Moving Average + /// Calculation type + /// + public Indicator BBF(int period, double deviation, PriceType priceType, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), deviation); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the ROC (Rate of Change) indicator. + /// The ROC shows the speed at which price is changing. + /// + /// Period of momentum. + /// + /// + public Indicator ROC(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Momentum indicator. + /// Momentum compares where the current price is in relation to where the price was in the past. + /// + /// Period for Momentum + /// Sources prices for Momentum + /// + /// + public Indicator Momentum(int period, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the %R Larry Williams. + /// Uses Stochastic to determine overbought and oversold levels. + /// + /// Period for Momentum + /// + /// + public Indicator RLW(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Price Oscillator (PO) indicator. + /// PO calculates the variation between price moving averages. + /// + /// Period of MA1 + /// Period of MA2 + /// Sources prices for MA + /// Type of Moving Average + /// Calculation type + /// + public Indicator PO(int period1, int period2, PriceType priceType, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period1); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period2); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the OsMA (Moving Average of Oscillator) indicator. + /// The OsMA reflects the difference between an oscillator (MACD) and its moving average (signal line). + /// + /// Period of fast EMA. + /// Period of slow EMA. + /// Period of signal EMA. + /// Calculation type + /// + public Indicator OsMA(int fastEMA, int slowEMA, int signalEMA, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), fastEMA); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), slowEMA); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), signalEMA); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets On Balance Volume. + /// On Balance Volume (OBV) measures buying and selling pressure as a cumulative indicator that adds volume on up days and subtracts volume on down days. + /// + /// Sources prices for OBV + /// + /// + public Indicator OBV(PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Positive Volume Index (PVI) indicator. + /// The PVI value changes on the periods in which value of volume has increased in comparison with the previous period. + /// + /// + /// + /// + public Indicator PVI(PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Volume indicator. + /// Volume allows to confirm the strength of a trend or to suggest about it's weakness. + /// + /// + /// + public Indicator Volume() + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + ?(indicator); + return indicator; + } + + /// + /// Gets the MFI(Money Flow Index) indicator. + /// The MFI(Money Flow Index) is an oscillator that uses both price and volume to measure buying and selling pressure. + /// + /// Period of MFI. + /// + /// + public Indicator MFI(int period) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), period); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Acceleration/Deceleration Oscillator (AC). + /// AC measures the acceleration and deceleration of the current momentum. + /// + /// + /// + public Indicator AC() + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + ?(indicator); + return indicator; + } + + /// + /// Gets the Average True Range (ATR) indicator. + /// The ATR measures of market volatility. + /// + /// + /// Period of Moving Average. + /// Type of Moving Average + /// Calculation type + /// + public Indicator ATR(int period, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Kaufman Adaptive Moving Average (KAMA) indicator. + /// KAMA is an exponential style average with a smoothing that varies according to recent data. + /// + /// Period + /// Fast factor + /// Slow factor + /// Sources prices for MA + /// + /// + public Indicator KAMA(int period, double fast, double slow, PriceType priceType) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), fast); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), slow); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Qstick indicator. + /// The Qstick is a moving average that shows the difference between the prices at which an issue opens and closes. + /// + /// + /// + /// Calculation type + /// + public Indicator Qstick(int period, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Get the Swing Index (SI) indicator. + /// The SI is used to confirm trend line breakouts on price charts. + /// + /// The divider. + /// + /// + public Indicator SI(double divider) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), divider); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Get the True Strength Index (TSI) indicator. + /// + /// The TSI is a variation of the Relative Strength Indicator which uses a doubly-smoothed + /// EMA of price momentum to eliminate choppy price changes and spot trend changes. + /// + /// + /// First MA period. + /// Second MA period. + /// Calculation type + /// + public Indicator TSI(int firstPeriod, int secondPeriod, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), firstPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), secondPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Average Directional Index (ADX) indicator. + /// The ADX determines the strength of a prevailing trend. + /// + /// Period + /// Type of Moving Average + /// Calculation type + /// + public Indicator ADX(int period, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Keltner Channel indicator. + /// Keltner Channels are volatility-based envelopes set above and below an exponential moving average. + /// + /// Period of MA for Keltner's Channel + /// Coefficient of channel's width + /// Sources prices for MA + /// Type of Moving Average + /// Calculation type + /// + public Indicator Keltner(int period, double offset, PriceType priceType, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), offset); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(priceType.ToString(), (int)priceType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Returns an instance of the Percentage Price Oscillator (PPO). + /// Percentage Price Oscillator is a momentum indicator. Signal line is EMA of PPO. Formula: (FastEMA-SlowEMA)/SlowEMA. + /// + /// Fast EMA Period + /// Slow EMA Period + /// Signal EMA Period + /// Calculation type + /// + public Indicator PPO(int fastPeriod, int slowPeriod, int signalPeriod, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), fastPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), slowPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), signalPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Stochastic Slow. + /// Shows the location of the current close relative to the high/low range over a set number of periods (Slow). + /// + /// Period + /// Smoothing + /// Double smoothing + /// Moving type + /// Calculation type + /// + public Indicator Stochastic(int period, int smooth, int doubleSmooth, MaMode MaType, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), smooth); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), doubleSmooth); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(MaType.ToString(), (int)MaType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Stochastic x Relative Strength Index. + /// StochRSI is an oscillator that measures the level of RSI relative to its range. + /// + /// Period + /// Smoothing + /// Double smoothing + /// + /// + public Indicator StochasticxRSI(int rsiPeriod, int kPeriod, int dPeriod) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), rsiPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), kPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), dPeriod); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Ichimoku. + /// Enables to quickly discern and filter 'at a glance' the low-probability trading setups from those of higher probability. + /// + /// Tenkan Period + /// Kijun Period + /// Senkou Span B + /// + /// + public Indicator ICH(int TenkanPeriod, int KijunPeriod, int SenkouSpanB) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TenkanPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), KijunPeriod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SenkouSpanB); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Directional Movement Index(DMI) indicator. + /// The DMI ?dentifies whether there is a definable trend in the market. + /// + /// Period of Moving Average. + /// Type of Moving Average. + /// Calculation type + /// + public Indicator DMI(int period, MaMode mode, IndicatorCalculationType calculationType = IndicatorCalculationType.AllAvailableData) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), period); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(mode.ToString(), (int)mode)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new SelectItem(calculationType.ToString(), (int)calculationType)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + /// + /// Gets the Alligator. + /// Three moving averages with different colors, periods and calculation methods. + /// + /// Type of Jaw Moving Average. + /// SourcePrice of Jaw Moving Average. + /// Period of Jaw Moving Average. + /// Shift of Jaw Moving Average. + /// Period of Moving Average. + /// Type of Moving Average. + /// Period of Moving Average. + /// Type of Moving Average. + /// Period of Moving Average. + /// Type of Moving Average. + /// Period of Moving Average. + /// Type of Moving Average. + /// + /// + public Indicator Alligator(MaMode JawMAType, PriceType JawSourcePrice, int JawMAPeiod, int JawMAShift, MaMode TeethMAType, PriceType TeethSourcePrice, int TeethMAPeiod, int TeethMAShift, MaMode LipsMAType, PriceType LipsSourcePrice, int LipsMAPeiod, int LipsMAShift) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(JawMAType.ToString(), (int)JawMAType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(JawSourcePrice.ToString(), (int)JawSourcePrice)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), JawMAPeiod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), JawMAShift); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(TeethMAType.ToString(), (int)TeethMAType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(TeethSourcePrice.ToString(), (int)TeethSourcePrice)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TeethMAPeiod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TeethMAShift); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(LipsMAType.ToString(), (int)LipsMAType)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(LipsSourcePrice.ToString(), (int)LipsSourcePrice)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LipsMAPeiod); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LipsMAShift); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + + public Indicator HV(int stdPeriod, int volatilityPeriod, PriceType priceType, HVSheduleMode hvMode) + { + return ?(stdPeriod, volatilityPeriod, priceType, hvMode, true, 0); + } + + public Indicator HV(int stdPeriod, int volatilityPeriod, PriceType priceType, HVSheduleMode hvMode, int percentilePeriod) + { + return ?(stdPeriod, volatilityPeriod, priceType, hvMode, false, percentilePeriod); + } + + private Indicator ?(int P_0, int P_1, PriceType P_2, HVSheduleMode P_3, bool P_4, int P_5) + { + Indicator indicator = Core.Instance.Indicators.CreateIndicator(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ScriptCreationType.Default); + IList settings = indicator.Settings; + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_1); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(P_2.ToString(), (int)P_2)); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_4); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_5); + settings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new SelectItem(P_3.ToString(), (int)P_3)); + indicator.Settings = settings; + ?(indicator); + return indicator; + } + } + /// + /// Base class for all indicators. + /// + [Published] + public abstract class Indicator : ExecutionEntity, IIndicatorsCollection + { + private class ? + { + [CompilerGenerated] + private Color? ??; + + [CompilerGenerated] + private Color? ??; + + public Color? BeginColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = color; + } + } + + public Color? EndColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = color; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(BeginColor); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(EndColor); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + + [NotPublished] + public const string EMA = "Exponential Moving Average"; + + [NotPublished] + public const string LWMA = "Linearly Weighted Moving Average"; + + [NotPublished] + public const string SMA = "Simple Moving Average"; + + [NotPublished] + public const string SMMA = "Smoothed Moving Average"; + + [NotPublished] + public const string PPMA = "Pivot Point Moving Average"; + + [NotPublished] + public const string CCI = "Commodity Channel Index"; + + [NotPublished] + public const string MAS3 = "3MASignal"; + + [NotPublished] + public const string MMA = "Modified Moving Average"; + + [NotPublished] + public const string Regression = "Regression Line"; + + [NotPublished] + public const string BB = "Bollinger Bands"; + + [NotPublished] + public const string Channel = "Price Channel"; + + [NotPublished] + public const string AFIRMA = "Autoregressive Finite Impulse Response Moving Average"; + + [NotPublished] + public const string RSI = "Relative Strength Index"; + + [NotPublished] + public const string MD = "McGinley Dynamic"; + + [NotPublished] + public const string MAE = "Moving Average Envelope"; + + [NotPublished] + public const string SAR = "Parabolic SAR"; + + [NotPublished] + public const string AO = "Awesome Oscillator"; + + [NotPublished] + public const string CMO = "Chande Momentum Oscillator"; + + [NotPublished] + public const string ZZ = "ZigZag"; + + [NotPublished] + public const string AROON = "Aroon"; + + [NotPublished] + public const string MACD = "Moving Average Convergence/Divergence"; + + [NotPublished] + public const string SD = "Standard Deviation"; + + [NotPublished] + public const string KRI = "Kairi Relative Index"; + + [NotPublished] + public const string BBF = "Bollinger Bands Flat"; + + [NotPublished] + public const string ROC = "Rate of Change"; + + [NotPublished] + public const string Momentum = "Momentum"; + + [NotPublished] + public const string RLW = "%R Larry Williams"; + + [NotPublished] + public const string PO = "Price Oscillator"; + + [NotPublished] + public const string OBV = "On Balance Volume"; + + [NotPublished] + public const string OsMA = "Moving Average of Oscillator"; + + [NotPublished] + public const string PVI = "Positive Volume Index"; + + [NotPublished] + public const string VOLUME = "Volume"; + + [NotPublished] + public const string MFI = "Money Flow Index"; + + [NotPublished] + public const string AC = "Acceleration Oscillator"; + + [NotPublished] + public const string ATR = "Average True Range"; + + [NotPublished] + public const string KAMA = "Kaufman Adaptive Moving Average"; + + [NotPublished] + public const string Stochastic = "Stochastic Slow"; + + [NotPublished] + public const string StochasticxRSI = "Stochastic x Relative Strength Index"; + + [NotPublished] + public const string Qstick = "Qstick"; + + [NotPublished] + public const string SI = "Swing Index"; + + [NotPublished] + public const string ADX = "Average Directional Index"; + + [NotPublished] + public const string Keltner = "Keltner Channel"; + + [NotPublished] + public const string PPO = "Percentage Price Oscillator"; + + [NotPublished] + public const string TSI = "True Strength Index"; + + [NotPublished] + public const string DMI = "Directional Movement Index"; + + [NotPublished] + public const string ICH = "Ichimoku"; + + [NotPublished] + public const string Alligator = "Alligator"; + + [NotPublished] + public const string HV = "Historical Volatility"; + + [NotPublished] + public const string PAZ = "Price Action Zones"; + + [NotPublished] + public const string OSCILLATOR_GROUP = "Oscillators"; + + [NotPublished] + public const string MOVING_AVERAGE_GROUP = "Moving averages"; + + [NotPublished] + public const string TREND_GROUP = "Trend"; + + [NotPublished] + public const string VOLATILITY_GROUP = "Volatility"; + + [NotPublished] + public const string CHANNEL_GROUP = "Channels"; + + [NotPublished] + public const string VOLUME_GROUP = "Volume"; + + [NotPublished] + public const string HIDDEN_GROUP = "Hidden"; + + [NotPublished] + protected internal const IndicatorCalculationType DEFAULT_CALCULATION_TYPE = IndicatorCalculationType.AllAvailableData; + + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private HistoricalData ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private int ?? = -1; + + [CompilerGenerated] + private TimeFrameConfig ?? = new TimeFrameConfig(); + + [CompilerGenerated] + private IndicatorUpdateType ??; + + [CompilerGenerated] + private bool ?? = true; + + private const string ?? = "Line_"; + + private const string ?? = "Level_"; + + [CompilerGenerated] + private IChart ??; + + private readonly List ??; + + private readonly List ??; + + private readonly object ??; + + private readonly List ??; + + private readonly object ??; + + private readonly List ??; + + private readonly object ??; + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obfuscation(Exclude = true)] + private bool debugMode; + + private bool ??; + + private readonly IDictionary> ??; + + private readonly object ??; + + private readonly List ??; + + [CompilerGenerated] + private ? ??; + + /// + /// Short name of indicator + /// + public virtual string ShortName + { + get + { + if (string.IsNullOrEmpty(??)) + { + return base.Name; + } + return ??; + } + [Obsolete("Override getter")] + protected set + { + ?? = value; + } + } + + /// + /// Access to current Symbol of indicator + /// + public Symbol Symbol => HistoricalData?.Symbol; + + /// + /// Amount of items in internal buffers + /// + public int Count + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Represent access to current used historical data. + /// + public HistoricalData HistoricalData + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = historicalData; + } + } + + /// + /// Represent access indicator series + /// + public LineSeries[] LinesSeries => ??.ToArray(); + + /// + /// + /// + public LineLevel[] LinesLevels => ??.ToArray(); + + /// + /// Specified, whether indicator should use main or additional window on the chart + /// + public bool SeparateWindow + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Specified, whether indicator should draw on chart background by default. + /// + public bool OnBackGround + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Specified, whether indicator should participate into price auto scale system. + /// + public bool AllowFitAuto + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Precision amount for formatting price (the count of digits after decimal point); By default = -1, which means to use precision from indicator's symbol + /// + public int Digits + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeFrameConfig TFConfig + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeFrameConfig; + } + } + + public IndicatorUpdateType UpdateType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + protected bool IsUpdateTypesSupported + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Indicator's settings + /// + public override IList Settings + { + get + { + IList settings = base.Settings; + if (?? != null) + { + for (int i = 0; i < ??.Count; i++) + { + int num = i + 1; + LineSeries lineSeries = ??[i]; + string text = string.Format(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), num); + SettingItemSeparatorGroup separatorGroup = new SettingItemSeparatorGroup((string.IsNullOrEmpty(lineSeries.Name) || lineSeries.Name.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) ? text : string.Format(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), lineSeries.Name), num); + IList settings2 = lineSeries.Settings; + foreach (SettingItem item in settings2) + { + item.SeparatorGroup = separatorGroup; + } + settings.Add(new SettingItemGroup($"{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{i}", settings2) + { + Text = text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + } + if (?? != null) + { + for (int j = 0; j < ??.Count; j++) + { + int num2 = ??.Count + j; + LineLevel lineLevel = ??[j]; + string text2 = string.Format(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), j + 1); + SettingItemSeparatorGroup separatorGroup2 = new SettingItemSeparatorGroup((string.IsNullOrEmpty(lineLevel.Name) || lineLevel.Name.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) ? text2 : string.Format(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), lineLevel.Name), num2 + 1); + IList settings3 = lineLevel.Settings; + foreach (SettingItem item2 in settings3) + { + item2.SeparatorGroup = separatorGroup2; + } + settings.Add(new SettingItemGroup($"{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{num2}", settings3) + { + Text = text2 + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + } + } + } + if (HistoricalData != null && (TFConfig.DefaultAggregation == null || (HistoricalData.Aggregation != null && !HistoricalData.Aggregation.Equals(TFConfig.DefaultAggregation)))) + { + TFConfig.DefaultAggregation = HistoricalData.Aggregation; + } + settings.Add(new SettingItemTimeFrameConfig(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TFConfig) + { + SeparatorGroup = new SettingItemSeparatorGroup(string.Empty, 1000) + }); + List list = new List + { + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 0), + new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1) + }; + if (IsUpdateTypesSupported) + { + settings.Add(new SettingItemSelectorLocalized(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), list.GetItemByValue((int)UpdateType), list) + { + SeparatorGroup = new SettingItemSeparatorGroup(string.Empty, 1100) + }); + } + return settings; + } + set + { + base.Settings = value; + foreach (SettingItem item in value) + { + if (!(item is SettingItemGroup { Value: IList value2 }) || !value2.Any() || value2[0].Group == null || !int.TryParse(value2[0].Group.Name.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()), out var result)) + { + continue; + } + if (result < ??.Count) + { + ??[result].Settings = value2; + continue; + } + int num = result - ??.Count; + if (num < ??.Count) + { + ??[num].Settings = value2; + } + } + bool flag = false; + if (value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemTimeFrameConfig settingItemTimeFrameConfig) + { + TFConfig = (TimeFrameConfig)settingItemTimeFrameConfig.Value; + } + if (IsUpdateTypesSupported && value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) is SettingItemSelectorLocalized settingItemSelectorLocalized) + { + UpdateType = (IndicatorUpdateType)(int)(object)((SelectItem)settingItemSelectorLocalized.Value).Value; + flag = settingItemSelectorLocalized.ValueChangingReason == SettingItemValueChangingReason.Manually; + } + if (flag) + { + OnSettingsUpdated(); + } + } + } + + /// + /// Represent access to the chart, that created indicator + /// + public IChart CurrentChart + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public virtual string HelpLink => string.Empty; + + public virtual string SourceCodeLink => string.Empty; + + internal int ChildIndicatorsCount + { + get + { + lock (??) + { + return ??.Count; + } + } + } + + internal ? Refresher + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = ?; + } + } + + protected virtual void OnInit() + { + } + + protected virtual void OnUpdate(UpdateArgs args) + { + } + + protected virtual void OnClear() + { + } + + public LineSeries AddLineSeries(string lineName = "", Color lineColor = default(Color), int lineWidth = 1, LineStyle lineStyle = LineStyle.Solid) + { + if (string.IsNullOrEmpty(lineName)) + { + lineName = $"{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{??.Count + 1}"; + } + if (lineColor == default(Color)) + { + lineColor = Color.Blue; + } + LineSeries lineSeries = new LineSeries(lineName, lineColor, lineWidth, lineStyle); + AddLineSeries(lineSeries); + return lineSeries; + } + + public void AddLineSeries(LineSeries lineSeries) + { + if (lineSeries == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + lock (??) + { + ??.Add(lineSeries); + } + } + + public LineLevel AddLineLevel(double level, string lineName = "", Color lineColor = default(Color), int lineWidth = 1, LineStyle lineStyle = LineStyle.Solid) + { + if (string.IsNullOrEmpty(lineName)) + { + lineName = $"{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{level}"; + } + if (lineColor == default(Color)) + { + lineColor = Color.Blue; + } + LineLevel lineLevel = new LineLevel(level, lineName, lineColor, lineWidth, lineStyle); + AddLineLevel(lineLevel); + return lineLevel; + } + + public void AddLineLevel(LineLevel lineLevel) + { + if (lineLevel == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??.Add(lineLevel); + } + + /// + /// Recalculate indicator + /// + public void Refresh() + { + Refresher?.?(this); + } + + /// + /// + /// + /// + public void AddIndicator(Indicator indicator) + { + if (indicator == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + lock (??) + { + if (??.Contains(indicator)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + indicator.HistoricalData = HistoricalData; + indicator.Init(); + for (int i = 0; i < Count; i++) + { + indicator.Update(new UpdateArgs(UpdateReason.HistoricalBar)); + } + ??.Add(indicator); + } + } + + public void RemoveIndicator(Indicator indicator) + { + if (indicator == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + lock (??) + { + ??.Remove(indicator); + } + indicator.Clear(); + indicator.Dispose(); + } + + /// + /// Sets the value of indicator into internal buffer + /// + /// Value + /// Index of indicator line + /// Offset value + public void SetValue(double value, int lineIndex = 0, int offset = 0) + { + ??[lineIndex].SetValue(value, offset); + } + + /// + /// Gets the value of indicator from internal buffer + /// + /// Offset value + /// Index of indicator line + /// Offset start point + /// + public double GetValue(int offset = 0, int lineIndex = 0, SeekOriginHistory origin = SeekOriginHistory.End) + { + double result = double.NaN; + if (lineIndex < 0 || lineIndex >= ??.Count) + { + return result; + } + return ??[lineIndex].GetValue(offset, origin); + } + + /// + /// Set line break point. + /// + /// Offset value + /// Index of indicator line + /// Offset start point + public void SetLineBreak(int offset = 0, int lineIndex = 0, SeekOriginHistory origin = SeekOriginHistory.End) + { + if (lineIndex < 0 || lineIndex >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + int lineBreak = ((origin == SeekOriginHistory.End) ? offset : (Count - offset - 1)); + LinesSeries[lineIndex].SetLineBreak(lineBreak); + } + + /// + /// Remove line break point. + /// + /// Offset value + /// Index of indicator line + /// Offset start point + public void RemoveLineBreak(int offset = 0, int lineIndex = 0, SeekOriginHistory origin = SeekOriginHistory.End) + { + if (lineIndex < 0 || lineIndex >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + int offset2 = ((origin == SeekOriginHistory.End) ? offset : (Count - offset - 1)); + LinesSeries[lineIndex].RemoveLineBreak(offset2); + } + + /// + /// Check if the point is a break point. + /// + /// Offset value + /// Index of indicator line + /// Offset start point + public bool GetLineBreak(int offset = 0, int lineIndex = 0, SeekOriginHistory origin = SeekOriginHistory.End) + { + if (lineIndex < 0 || lineIndex >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + int offset2 = ((origin == SeekOriginHistory.End) ? offset : (Count - offset - 1)); + return LinesSeries[lineIndex].GetLineBreak(offset2); + } + + /// + /// Gets the price from historical data + /// + /// + /// + /// + protected double GetPrice(PriceType priceType, int offset = 0) + { + return HistoricalData[Count - 1 - offset, SeekOriginHistory.Begin][priceType]; + } + + protected VolumeAnalysisData GetVolumeAnalysisData(int offset = 0) + { + return HistoricalData[Count - 1 - offset, SeekOriginHistory.Begin].VolumeAnalysisData; + } + + /// + /// Get Bid price + /// + /// Offset value + /// + protected double Bid(int offset = 0) + { + return GetPrice(PriceType.Bid, offset); + } + + /// + /// Get Ask price + /// + /// Offset value + /// + protected double Ask(int offset = 0) + { + return GetPrice(PriceType.Ask, offset); + } + + /// + /// Get Last price + /// + /// Offset value + /// + protected double Last(int offset = 0) + { + return GetPrice(PriceType.Last, offset); + } + + /// + /// Get Open price + /// + /// Offset value + /// + protected double Open(int offset = 0) + { + return GetPrice(PriceType.Open, offset); + } + + /// + /// Get High price + /// + /// Offset value + /// + protected double High(int offset = 0) + { + return GetPrice(PriceType.High, offset); + } + + /// + /// Get Low price + /// + /// Offset value + /// + protected double Low(int offset = 0) + { + return GetPrice(PriceType.Low, offset); + } + + /// + /// Get Close price + /// + /// Offset value + /// + protected double Close(int offset = 0) + { + return GetPrice(PriceType.Close, offset); + } + + /// + /// Get Median price + /// + /// Offset value + /// + protected double Median(int offset = 0) + { + return GetPrice(PriceType.Median, offset); + } + + /// + /// Get Typical price + /// + /// Offset value + /// + protected double Typical(int offset = 0) + { + return GetPrice(PriceType.Typical, offset); + } + + /// + /// Get Weighted price + /// + /// Offset value + /// + protected double Weighted(int offset = 0) + { + return GetPrice(PriceType.Weighted, offset); + } + + /// + /// Get Volume + /// + /// Offset value + /// + protected double Volume(int offset = 0) + { + return GetPrice(PriceType.Volume, offset); + } + + /// + /// Get Volume in quoting asset + /// + /// Offset value + /// + protected double QuoteAssetVolume(int offset = 0) + { + return GetPrice(PriceType.QuoteAssetVolume, offset); + } + + /// + /// Get Ticks + /// + /// Offset value + /// + protected double Ticks(int offset = 0) + { + return GetPrice(PriceType.Ticks, offset); + } + + /// + /// Get Open interest + /// + /// Offset value + /// + protected double OpenInterest(int offset = 0) + { + return GetPrice(PriceType.OpenInterest, offset); + } + + /// + /// Get Funding rate + /// + /// Offset value + /// + protected double FundingRate(int offset = 0) + { + return GetPrice(PriceType.FundingRate, offset); + } + + /// + /// Get Time + /// + /// Offset value + /// + protected DateTime Time(int offset = 0) + { + return new DateTime(HistoricalData[Count - 1 - offset, SeekOriginHistory.Begin].TicksLeft, DateTimeKind.Utc); + } + + /// + /// Formatting price, using precision from assigned symbol or Digits value if specified + /// + /// Price value + /// + public string FormatPrice(double price) + { + if (Digits != -1) + { + return price.Format(Digits); + } + if (Symbol != null) + { + return Symbol.FormatPrice(price); + } + return price.ToString(); + } + + [NotPublished] + public override void Dispose() + { + base.Dispose(); + HistoricalData = null; + } + + public virtual void OnPaintChart(PaintChartEventArgs args) + { + } + + public void Calculate(HistoricalData historicalData) + { + if (historicalData == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + HistoricalData?.RemoveIndicator(this); + historicalData.AddIndicator(this); + } + + /// + /// Marks cloud begin between two line series with specific color + /// + /// First line series index + /// Second line series index + /// Cloud color + /// Offset + protected void BeginCloud(int line1Index, int line2Index, Color color, int offset = 0) + { + IndicatorCloudKey indicatorCloudKey = new IndicatorCloudKey(line1Index, line2Index); + int num = Count - 1 - offset; + ? ? = this.?(indicatorCloudKey, num); + if (?.EndColor == color) + { + ?.EndColor = null; + } + else + { + ?.BeginColor = color; + } + } + + /// + /// Marks cloud end between two line series with specific color + /// + /// First line series index + /// Second line series index + /// Cloud color + /// Offset + protected void EndCloud(int line1Index, int line2Index, Color color, int offset = 0) + { + IndicatorCloudKey indicatorCloudKey = new IndicatorCloudKey(line1Index, line2Index); + int num = Count - 1 - offset; + ? ? = this.?(indicatorCloudKey, num); + if (?.BeginColor == color) + { + ?.BeginColor = null; + } + else + { + ?.EndColor = color; + } + } + + private ? ?(IndicatorCloudKey P_0, int P_1) + { + lock (??) + { + if (!??.TryGetValue(P_0, out var value)) + { + value = (??[P_0] = new List()); + for (int i = 0; i < Count; i++) + { + value.Add(new ?()); + } + } + ? ? = value[P_1]; + if (? == null) + { + ? = (value[P_1] = new ?()); + } + return ?; + } + } + + [NotPublished] + public IDictionary AnalyzeClouds() + { + IDictionary> dictionary; + lock (??) + { + if (??.Count == 0) + { + return null; + } + dictionary = new Dictionary>(??); + } + Dictionary dictionary2 = new Dictionary(); + foreach (KeyValuePair> item in dictionary) + { + IndicatorCloudKey key = item.Key; + List value = item.Value; + List list = new List(); + IndicatorCloud indicatorCloud = null; + for (int i = 0; i < value.Count; i++) + { + ? ? = value[i]; + if (?.EndColor.HasValue && indicatorCloud != null) + { + indicatorCloud.ToIndex = i; + if (indicatorCloud.ToIndex - indicatorCloud.FromIndex > 0) + { + indicatorCloud.ToIndex--; + } + list.Add(indicatorCloud); + indicatorCloud = null; + } + if (?.BeginColor.HasValue) + { + indicatorCloud = new IndicatorCloud + { + Color = ?.BeginColor.Value, + FromIndex = i + }; + } + } + if (indicatorCloud != null) + { + if (indicatorCloud.ToIndex == -1) + { + indicatorCloud.ToIndex = Count - 1; + } + list.Add(indicatorCloud); + } + dictionary2.Add(key, list.ToArray()); + } + return dictionary2; + } + + public void SetBarColor(Color? color = null, int offset = 0) + { + int index = ??.Count - 1 - offset; + if (!color.HasValue) + { + ??[index] = null; + return; + } + ??[index] = new IndicatorBarAppearance + { + BarColor = color.Value + }; + } + + public IndicatorBarAppearance GetBarAppearance(int offset = 0) + { + int num = ??.Count - 1 - offset; + if (num < 0) + { + return null; + } + return ??[num]; + } + + public void SetBarAppearance(IndicatorBarAppearance barAppearance, int offset = 0) + { + int index = ??.Count - 1 - offset; + ??[index] = barAppearance; + } + + protected virtual bool OnTryGetMinMax(int fromOffset, int toOffset, out double min, out double max) + { + min = double.NaN; + max = double.NaN; + return false; + } + + protected Indicator() + { + ?? = new object(); + ?? = new List(); + ?? = new List(); + ?? = new List(); + ?? = new object(); + ?? = new List(); + ?? = new object(); + ?? = new Dictionary>(); + ?? = new object(); + ?? = new List(); + } + + public void Init() + { + try + { + OnInit(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public void Update(UpdateArgs args) + { + if (debugMode) + { + while (!base.Disposed) + { + Thread.Sleep(100); + if (??) + { + break; + } + } + } + bool num = ?(args.Reason); + ?(args); + if (num) + { + Count++; + ?(); + ?(); + } + try + { + OnUpdate(args); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?? = false; + } + + public void Clear() + { + ?(); + ?(); + Count = 0; + if (?? == null) + { + return; + } + lock (??) + { + foreach (LineSeries item in ??) + { + item.Clear(); + } + } + lock (??) + { + ??.Clear(); + } + ??.Clear(); + try + { + OnClear(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public bool TryGetMinMax(int fromOffset, int toOffset, out double min, out double max) + { + min = double.NaN; + max = double.NaN; + try + { + return OnTryGetMinMax(fromOffset, toOffset, out min, out max); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return false; + } + + public void PaintChart(PaintChartEventArgs ev) + { + try + { + OnPaintChart(ev); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + ?? = true; + } + + private bool ?(UpdateReason P_0) + { + switch (P_0) + { + case UpdateReason.HistoricalBar: + return true; + case UpdateReason.NewBar: + return true; + case UpdateReason.NewTick: + if (HistoricalData.Aggregation == null) + { + return false; + } + if (HistoricalData.Aggregation.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() && HistoricalData.Aggregation.GetPeriod == Period.TICK1) + { + return true; + } + break; + } + return false; + } + + private void ?() + { + lock (??) + { + foreach (LineSeries item in ??) + { + item.?(); + } + } + lock (??) + { + foreach (KeyValuePair> item2 in ??) + { + item2.Value.Add(new ?()); + } + } + ??.Add(null); + } + + private void ?(UpdateArgs P_0) + { + lock (??) + { + foreach (Indicator item in ??) + { + item.Update(P_0); + } + } + } + + private void ?() + { + lock (??) + { + foreach (Indicator item in ??) + { + item.Clear(); + item.Dispose(); + } + ??.Clear(); + } + } + + internal void ?(HistoricalDataCustom P_0) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + lock (??) + { + if (??.Contains(P_0)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + for (int i = 0; i < Count; i++) + { + P_0.?(); + } + ??.Add(P_0); + } + } + + private void ?() + { + lock (??) + { + foreach (HistoricalDataCustom item in ??) + { + item.?(); + } + } + } + + private void ?() + { + lock (??) + { + foreach (HistoricalDataCustom item in ??) + { + item.Dispose(); + } + ??.Clear(); + } + } + + protected override void OnSettingsUpdated() + { + Refresh(); + } + } + public class IndicatorBarAppearance + { + [CompilerGenerated] + private Color ?; + + [CompilerGenerated] + private Color ?; + + [CompilerGenerated] + private Color ?; + + public Color BarColor + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public Color BorderColor + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public Color WickColor + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + } + public enum IndicatorCalculationBehavior + { + Synchronous, + Asynchronous + } + public class IndicatorCloud : IComparable + { + [CompilerGenerated] + private int ?; + + [CompilerGenerated] + private int ?; + + private Color ?; + + [CompilerGenerated] + private SolidBrush ?; + + internal const int ? = -1; + + public int FromIndex + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public int ToIndex + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public Interval Interval => new Interval(FromIndex, ToIndex); + + public Color Color + { + get + { + return ?; + } + set + { + ? = value; + Brush = new SolidBrush(?); + } + } + + public SolidBrush Brush + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = solidBrush; + } + } + + public IndicatorCloud() + { + FromIndex = -1; + ToIndex = -1; + } + + public int CompareTo(IndicatorCloud other) + { + if (this == other) + { + return 0; + } + if (other == null) + { + return 1; + } + return FromIndex.CompareTo(other.FromIndex); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3); + defaultInterpolatedStringHandler.AppendFormatted(FromIndex); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ToIndex); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Color.Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public readonly struct IndicatorCloudKey : IEquatable + { + [CompilerGenerated] + private readonly int ?; + + [CompilerGenerated] + private readonly int ?; + + public int Line1Index + { + [CompilerGenerated] + get + { + return ?; + } + } + + public int Line2Index + { + [CompilerGenerated] + get + { + return ?; + } + } + + public IndicatorCloudKey(int line1Index, int line2Index) + { + ? = line1Index; + ? = line2Index; + } + + public bool Equals(IndicatorCloudKey other) + { + if (Line1Index == other.Line1Index) + { + return Line2Index == other.Line2Index; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj is IndicatorCloudKey other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (Line1Index * 397) ^ Line2Index; + } + } + public class IndicatorInfo : ScriptInfo + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + public string Group + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public bool IsAvailableInWatchlist + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public string ShortName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal IndicatorInfo(ConstructorInfo P_0, ScriptCreationType P_1, string P_2, string P_3) + : base(P_0, P_1, P_2, P_3) + { + } + + protected override void Initialize(string relativePath, string assemblyName) + { + using Indicator indicator = ctor.Invoke(null) as Indicator; + base.Name = indicator.Name; + ShortName = ?(indicator); + base.Description = indicator.Description; + base.Version = indicator.Version; + base.Key = new ScriptKey(base.ScriptCreationType, relativePath, assemblyName, base.Name); + indicator.Key = base.Key; + base.Settings = indicator.Settings as List; + IsAvailableInWatchlist = indicator is IWatchlistIndicator; + } + + internal Indicator ?() + { + Indicator indicator = ctor?.Invoke(null) as Indicator; + if (indicator != null) + { + indicator.Key = base.Key; + } + return indicator; + } + + public override string ToString() + { + return base.Name; + } + + private string ?(Indicator P_0) + { + if (string.IsNullOrEmpty(P_0.ShortName)) + { + return string.Empty; + } + int num = P_0.ShortName.IndexOf('('); + if (num == -1) + { + return P_0.ShortName; + } + return P_0.ShortName.Substring(0, num).TrimEnd(); + } + } + public sealed class IndicatorManager : ScriptManager + { + [CompilerGenerated] + private BuiltInIndicators ?; + + public BuiltInIndicators BuiltIn + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = builtInIndicators; + } + } + + protected override string DefaultScriptsPath => Const.DEFAULT_INDICATORS_RELATIVE_PATH; + + public override string CustomScriptsPath => Const.CUSTOM_INDICATORS_PATH; + + internal IndicatorManager() + { + BuiltIn = new BuiltInIndicators(); + } + + internal override void ?() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + try + { + base.?(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + public Indicator CreateIndicator(string indicatorName, string assemblyName = "", string relativePath = "", ScriptCreationType scriptCreationType = ScriptCreationType.Custom) + { + if (string.IsNullOrEmpty(indicatorName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ScriptKey scriptKey = SearchScriptKey(indicatorName, assemblyName, relativePath, scriptCreationType); + return CreateIndicator(scriptKey); + } + + public Indicator CreateIndicator(ScriptKey scriptKey) + { + if (scriptsInfoCache.TryGetValue(scriptKey, out var value)) + { + return CreateIndicator(value); + } + return null; + } + + public Indicator CreateIndicator(IndicatorInfo indicatorInfo) + { + return indicatorInfo.?(); + } + + protected override string GetScriptsFolderPath(ScriptCreationType scriptCreationType) + { + if (scriptCreationType != ScriptCreationType.Default) + { + return Const.CUSTOM_INDICATORS_PATH; + } + return Path.Combine(Const.EXECUTING_FOLDER, Const.DEFAULT_INDICATORS_RELATIVE_PATH); + } + + protected override IndicatorInfo CreateScriptInfo(ConstructorInfo ctor, ScriptCreationType scriptCreationType, string relativePath, string assemblyName) + { + return new IndicatorInfo(ctor, scriptCreationType, relativePath, assemblyName); + } + } + /// + /// Using IndicatorLineMarker class you can mark by color or icon any point of your indicator's line. + /// + public class IndicatorLineMarker + { + [CompilerGenerated] + private Color ? = Color.Empty; + + [CompilerGenerated] + private IndicatorLineMarkerIconType ?; + + [CompilerGenerated] + private IndicatorLineMarkerIconType ?; + + /// + /// Color of the marker + /// + public Color Color + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + /// + /// Icon that will be drawn above the indicator line + /// + public IndicatorLineMarkerIconType UpperIcon + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + /// + /// Icon that will be drawn beyond the indicator line + /// + public IndicatorLineMarkerIconType BottomIcon + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + /// + /// Constructor for IndicatorLineMarker + /// + /// + /// + /// + public IndicatorLineMarker(Color color, IndicatorLineMarkerIconType upperIcon = IndicatorLineMarkerIconType.None, IndicatorLineMarkerIconType bottomIcon = IndicatorLineMarkerIconType.None) + { + Color = color; + UpperIcon = upperIcon; + BottomIcon = bottomIcon; + } + + /// + /// Constructor for IndicatorLineMarker + /// + public IndicatorLineMarker() + { + } + } + /// + /// Different type of icons for Indicator marker + /// + public enum IndicatorLineMarkerIconType + { + None, + UpArrow, + DownArrow, + Flag, + FillCircle + } + public class IndicatorsCollection : IIndicatorsCollection, ?, ITaskSchedulerProvider + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal Indicator ?(IndicatorWrapper P_0) + { + return P_0.Indicator; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Indicator ??; + + internal bool ?(IndicatorWrapper P_0) + { + return object.Equals(P_0.Indicator, ??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Indicator ??; + + internal bool ?(IndicatorWrapper P_0) + { + return object.Equals(P_0.Indicator, ??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Indicator ??; + + internal bool ?(IndicatorWrapper P_0) + { + return object.Equals(P_0.Indicator, ??); + } + } + + private IndicatorCalculationBehavior ??; + + private readonly HistoricalData ??; + + private readonly List ??; + + private readonly object ??; + + private TaskScheduler ??; + + public Indicator[] All + { + get + { + lock (??) + { + return ??.Select((IndicatorWrapper P_0) => P_0.Indicator).ToArray(); + } + } + } + + public IndicatorCalculationBehavior CalculationBehavior + { + get + { + return ??; + } + set + { + if (?? != value) + { + ?? = value; + ?? = ((?? == IndicatorCalculationBehavior.Synchronous) ? null : new DegreeOfParallelismTaskScheduler(3)); + } + } + } + + TaskScheduler ITaskSchedulerProvider.TaskScheduler => ??; + + public IndicatorsCollection(HistoricalData historicalData) + { + ?? = historicalData; + ?? = new List(); + ?? = new object(); + CalculationBehavior = IndicatorCalculationBehavior.Synchronous; + } + + public void AddIndicator(Indicator indicator) + { + if (indicator == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + lock (??) + { + if (??.Any((IndicatorWrapper P_0) => object.Equals(P_0.Indicator, indicator))) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IndicatorWrapper indicatorWrapper = new IndicatorWrapper(indicator, this); + ??.Add(indicatorWrapper); + indicator.HistoricalData = ??; + indicator.Refresher = this; + indicatorWrapper.?(??.Count, false); + } + } + + public void RemoveIndicator(Indicator indicator) + { + if (indicator == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IndicatorWrapper indicatorWrapper; + lock (??) + { + indicatorWrapper = ??.FirstOrDefault((IndicatorWrapper P_0) => object.Equals(P_0.Indicator, indicator)); + if (indicatorWrapper != null) + { + ??.Remove(indicatorWrapper); + } + } + indicatorWrapper?.Dispose(); + } + + public void Update(UpdateArgs args, IndicatorUpdateType? updateType = null) + { + lock (??) + { + foreach (IndicatorWrapper item in ??) + { + item.?(args, updateType); + } + } + } + + public void Refresh() + { + lock (??) + { + int count = ??.Count; + foreach (IndicatorWrapper item in ??) + { + item.?(count, true); + } + } + } + + private void ?(Indicator P_0) + { + if (TryGetWrapper(P_0, out var wrapper)) + { + wrapper.?(??.Count, true); + } + } + + void global::?.?.?(Indicator P_0) + { + //ILSpy generated this explicit interface implementation from .override directive in ? + this.?(P_0); + } + + public bool TryGetWrapper(Indicator indicator, out IndicatorWrapper wrapper) + { + lock (??) + { + wrapper = ??.FirstOrDefault((IndicatorWrapper P_0) => object.Equals(P_0.Indicator, indicator)); + } + return wrapper != null; + } + + public void Clear() + { + lock (??) + { + foreach (IndicatorWrapper item in ??) + { + item.Dispose(); + } + ??.Clear(); + } + } + } + public enum IndicatorStatus + { + Pending, + Loading, + Working + } + public class IndicatorWrapper : IDisposable + { + [CompilerGenerated] + private sealed class ? + { + public IndicatorWrapper ??; + + public int ??; + + public bool ??; + + public CancellationToken ??; + + internal void ?() + { + ??.?(??, ??, ??); + } + + internal void ?(Task P_0) + { + ??.?(??, ??); + } + } + + [CompilerGenerated] + private IndicatorStatus ?; + + [CompilerGenerated] + private readonly Indicator ?; + + [CompilerGenerated] + private IProgress ?; + + private readonly ITaskSchedulerProvider ?; + + private CancellationTokenSource ?; + + private readonly Queue ?; + + private SpinLock ?; + + private Task ?; + + private readonly object ?; + + private bool ?; + + private readonly ManualResetEventSlim ?; + + public IndicatorStatus Status + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = indicatorStatus; + } + } + + public Indicator Indicator + { + [CompilerGenerated] + get + { + return ?; + } + } + + public IProgress CalculatingProgress + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + private set + { + ? = progress; + } + } + + public IndicatorWrapper(Indicator indicator, ITaskSchedulerProvider taskSchedulerProvider) + { + ? = taskSchedulerProvider; + ? = indicator; + Status = IndicatorStatus.Pending; + ? = new Queue(); + ? = default(SpinLock); + ? = Task.CompletedTask; + ? = new object(); + ? = new ManualResetEventSlim(); + } + + internal void ?(int P_0, bool P_1) + { + Status = IndicatorStatus.Pending; + CancellationToken cancellationToken = ?(); + if (Indicator.UpdateType == IndicatorUpdateType.OnBarClose) + { + P_0--; + } + if (?.TaskScheduler != null) + { + lock (?) + { + if (!?.IsCompleted) + { + ? = true; + } + else + { + ?(P_0, P_1, cancellationToken); + } + return; + } + } + ?(P_0, P_1, cancellationToken); + } + + private void ?(int P_0, bool P_1, CancellationToken P_2) + { + try + { + CalculatingProgress = new PercentageProgress(); + Status = IndicatorStatus.Loading; + ?.Reset(); + if (P_1) + { + Indicator.Clear(); + } + Indicator.Init(); + float num = P_0; + for (int i = 0; i < P_0; i++) + { + if (P_2.IsCancellationRequested) + { + return; + } + Indicator.Update(new UpdateArgs(UpdateReason.HistoricalBar)); + CalculatingProgress.Report((float)i / num); + } + while (!P_2.IsCancellationRequested) + { + bool lockTaken = false; + UpdateArgs updateArgs; + try + { + ?.Enter(ref lockTaken); + if (?.Count == 0) + { + Status = IndicatorStatus.Working; + break; + } + updateArgs = ?.Dequeue(); + } + finally + { + if (lockTaken) + { + ?.Exit(); + } + } + if (updateArgs != null) + { + Indicator.Update(updateArgs); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?.Set(); + } + } + + internal void ?(UpdateArgs P_0, IndicatorUpdateType? P_1 = null) + { + if (P_1.HasValue && P_1.Value != Indicator.UpdateType) + { + return; + } + bool lockTaken = false; + try + { + ?.Enter(ref lockTaken); + IndicatorStatus status = Status; + bool flag = (uint)status <= 1u; + if (flag || ?.Count > 0) + { + ?.Enqueue(P_0.?()); + return; + } + } + finally + { + if (lockTaken) + { + ?.Exit(); + } + } + Indicator.Update(P_0.?()); + } + + public void CallVolumeAnalysisLoaded() + { + if (Indicator is IVolumeAnalysisIndicator volumeAnalysisIndicator) + { + ?.Wait(); + volumeAnalysisIndicator.VolumeAnalysisData_Loaded(); + } + } + + public void Dispose() + { + ??.Cancel(); + ??.Dispose(); + Indicator?.Clear(); + Indicator?.Dispose(); + } + + private void ?(int P_0, bool P_1) + { + lock (?) + { + if (?) + { + ? = false; + ?(P_0, P_1, ?.Token); + } + } + } + + private void ?(int P_0, bool P_1, CancellationToken P_2) + { + ? = Task.Factory.StartNew(delegate + { + ?(P_0, P_1, P_2); + }, P_2, TaskCreationOptions.None, ?.TaskScheduler).ContinueWith(delegate + { + ?(P_0, P_1); + }, CancellationToken.None, TaskContinuationOptions.None, ?.TaskScheduler); + } + + private CancellationToken ?() + { + lock (?) + { + ??.Cancel(); + ? = new CancellationTokenSource(); + return ?.Token; + } + } + } + public abstract class Line : ICustomizable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private LineStyle ??; + + [CompilerGenerated] + private bool ??; + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color Color + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Width + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public LineStyle Style + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool Visible + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public virtual IList Settings + { + get + { + return new List + { + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Visible) + { + SortIndex = 0 + }, + new SettingItemLineOptions(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new LineOptions + { + WithCheckBox = false, + Color = Color, + Width = Width, + LineStyle = Style + }) + { + SortIndex = 1 + } + }; + } + set + { + SettingItem itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null && itemByName.Value is bool visible) + { + Visible = visible; + } + itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null && itemByName.Value is LineOptions lineOptions) + { + Color = lineOptions.Color; + Width = lineOptions.Width; + Style = lineOptions.LineStyle; + } + } + } + + protected Line(string name, Color color, int width, LineStyle style) + { + Name = name; + Color = color; + Width = width; + Style = style; + Visible = true; + } + } + public sealed class LineLevel : Line + { + [CompilerGenerated] + private double ??; + + public double Level + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + IList settings = base.Settings; + settings.Add(new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Level) + { + SortIndex = 2 + }); + return settings; + } + set + { + SettingItem itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null && itemByName.Value is double level) + { + Level = level; + } + base.Settings = value; + } + } + + public LineLevel(double level, string name, Color color, int width, LineStyle style) + : base(name, color, width, style) + { + Level = level; + } + } + public sealed class LineSeries : Line + { + internal List ??; + + [CompilerGenerated] + private int ??; + + private static int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private bool ?? = true; + + private readonly List ??; + + private readonly List ?? = new List(); + + internal int LineSeriesId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + internal int Count => ??.Count; + + /// + /// Sets the bar number (from the data beginning) from which the drawing of the given indicator line must start; + /// + public int DrawBegin + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Time shift of indicator's line + /// + public int TimeShift + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ShowLineMarker + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double this[int offset = 0, SeekOriginHistory origin = SeekOriginHistory.End] + { + get + { + return GetValue(offset, origin); + } + set + { + SetValue(value, offset); + } + } + + public override IList Settings + { + get + { + IList settings = base.Settings; + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TimeShift) + { + SortIndex = 3 + }); + settings.Add(new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ShowLineMarker) + { + SortIndex = 4 + }); + settings.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LineSeriesId) + { + VisibilityMode = VisibilityMode.Hidden + }); + return settings; + } + set + { + base.Settings = value; + SettingItem itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null && itemByName.Value is int timeShift) + { + TimeShift = timeShift; + } + itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (itemByName != null && itemByName.Value is bool showLineMarker) + { + ShowLineMarker = showLineMarker; + } + } + } + + public LineSeries(string name, Color color, int width, LineStyle style) + : base(name, color, width, style) + { + LineSeriesId = ??++; + ?? = new List(); + ?? = new List(); + } + + public double GetValue(int offset = 0, SeekOriginHistory origin = SeekOriginHistory.End) + { + double result = double.NaN; + int num = ?(offset, origin); + if (num >= 0 && num < Count) + { + result = ??[num]; + } + return result; + } + + public void SetValue(double value, int offset = 0, SeekOriginHistory origin = SeekOriginHistory.End) + { + int index = ?(offset, origin); + ??[index] = value; + } + + internal void ?() + { + ??.Add(double.NaN); + ??.Add(null); + ??.Add(item: false); + } + + public void Clear() + { + ??.Clear(); + ClearMarkers(); + ??.Clear(); + } + + /// + /// Redraws parts of indicator's line within the interval set by offset + /// + public void SetMarker(int offset, Color color) + { + SetMarker(offset, new IndicatorLineMarker + { + Color = color + }); + } + + public void SetMarker(int offset, IndicatorLineMarker indicatorMarker) + { + if (offset < 0 || offset >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??[??.Count - 1 - offset] = indicatorMarker; + } + + /// + /// Removes redrawn parts of indicator's line within the interval set by offset + /// + public void RemoveMarker(int offset) + { + if (offset < 0 || offset >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??[??.Count - 1 - offset] = null; + } + + /// + /// + /// + public IndicatorLineMarker GetMarker(int offset) + { + if (offset < 0 || offset >= ??.Count) + { + return null; + } + return ??[??.Count - 1 - offset]; + } + + /// + /// Fully clears markers from line + /// + public void ClearMarkers() + { + for (int i = 0; i < ??.Count; i++) + { + ??[i] = null; + } + } + + public void SetLineBreak(int offset) + { + if (offset < 0 || offset >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??[??.Count - 1 - offset] = true; + } + + public void RemoveLineBreak(int offset) + { + if (offset < 0 || offset >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??[??.Count - 1 - offset] = false; + } + + public bool GetLineBreak(int offset) + { + if (offset < 0 || offset >= ??.Count) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return ??[??.Count - 1 - offset]; + } + + private int ?(int P_0, SeekOriginHistory P_1) + { + int result = P_0; + if (P_1 == SeekOriginHistory.End) + { + result = Count - 1 - P_0; + } + return result; + } + } + [Published] + public class PaintChartEventArgs + { + [CompilerGenerated] + private Graphics ?; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private Rectangle ??; + + [CompilerGenerated] + private Point ??; + + [CompilerGenerated] + private int ??; + + public Graphics Graphics + { + [CompilerGenerated] + get + { + return ?; + } + [CompilerGenerated] + set + { + ? = value; + } + } + + public bool DrawBackground + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Rectangle Rectangle + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Point MousePosition + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int WindowIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public PaintChartEventArgs(Graphics graphics, Rectangle rectangle, Point mousePosition, int windowIndex) + { + Graphics = graphics; + Rectangle = rectangle; + MousePosition = mousePosition; + WindowIndex = windowIndex; + } + } + /// + /// Use this attribute to mark input parameters of your script. You will see them in the settings screen on adding + /// + [Published] + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class InputParameterAttribute : Attribute + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private IComparable[] ??; + + /// + /// Displayed name of input parameter + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Sort index for input paramter + /// + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Minimal value for numeric input parameters + /// + public double Minimum + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Maximal value for numeric input parameters + /// + public double Maximum + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Increment value for numeric input parameters + /// + public double Increment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// Decimal palces for numeric input parameters + /// + public int DecimalPlaces + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + /// + /// List of predefined values + /// + public IComparable[] Variants + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + public InputParameterAttribute(string name = "", int sortIndex = 0, double minimum = -2147483648.0, double maximum = 2147483647.0, double increment = 0.01, int decimalPlaces = 2, object[] variants = null) + { + Name = name; + SortIndex = sortIndex; + Minimum = minimum; + Maximum = maximum; + Increment = increment; + DecimalPlaces = decimalPlaces; + Variants = variants?.Cast()?.ToArray(); + } + } + public sealed class OrderPlacingStrategiesManager : ScriptManager + { + private readonly List ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + public OrderPlacingStrategy[] Created => ??.ToArray(); + + public override string CustomScriptsPath => Const.CUSTOM_PLACE_ORDER_STRATEGIES_PATH; + + protected override string DefaultScriptsPath => Const.DEFAULT_PLACE_ORDER_STRATEGIES_RELATIVE_PATH; + + public event Action StrategyCreated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action StrategyRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public OrderPlacingStrategiesManager() + { + ?? = new List(); + } + + internal override void ?() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + try + { + base.?(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + protected override OrderPlacingStrategyInfo CreateScriptInfo(ConstructorInfo ctor, ScriptCreationType scriptCreationType, string relativePath, string assemblyName) + { + return new OrderPlacingStrategyInfo(ctor, scriptCreationType, relativePath, assemblyName); + } + + protected override string GetScriptsFolderPath(ScriptCreationType scriptCreationType) + { + if (scriptCreationType != ScriptCreationType.Default) + { + return Const.CUSTOM_PLACE_ORDER_STRATEGIES_PATH; + } + return Path.Combine(Const.EXECUTING_FOLDER, Const.DEFAULT_PLACE_ORDER_STRATEGIES_RELATIVE_PATH); + } + + public OrderPlacingStrategy CreateStrategy(OrderPlacingStrategyInfo orderPlacingStrategyInfo) + { + OrderPlacingStrategy orderPlacingStrategy = orderPlacingStrategyInfo.?(); + ??.Add(orderPlacingStrategy); + ???.Invoke(orderPlacingStrategy); + return orderPlacingStrategy; + } + + internal void ?(OrderPlacingStrategy P_0) + { + if (??.Remove(P_0)) + { + P_0.Dispose(); + ???.Invoke(P_0); + } + } + } + public abstract class ScriptInfo + { + [CompilerGenerated] + private ScriptKey ??; + + [CompilerGenerated] + private ScriptCreationType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Version ??; + + [CompilerGenerated] + private List ??; + + protected ConstructorInfo ctor; + + public ScriptKey Key + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public ScriptCreationType ScriptCreationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = scriptCreationType; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public Version Version + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + public List Settings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + protected set + { + ?? = value; + } + } + + protected ScriptInfo(ConstructorInfo ctor, ScriptCreationType scriptCreationType, string relativePath, string assemblyName) + { + this.ctor = ctor; + ScriptCreationType = scriptCreationType; + try + { + Initialize(relativePath, assemblyName); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + assemblyName + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + protected abstract void Initialize(string relativePath, string assemblyName); + } + public class ScriptInfoEventArgs : EventArgs + { + } + public struct ScriptKey + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal string ?(DescriptionAttribute P_0) + { + return P_0.Description; + } + } + + [CompilerGenerated] + private string[] ??; + + [CompilerGenerated] + private ScriptCreationType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + private const string ?? = "|"; + + public string[] FoldersHierarchy + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + internal ScriptCreationType ScriptCreationType + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = scriptCreationType; + } + } + + internal string RelativePath + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal string AssemblyName + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal string ScriptName + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public ScriptKey(ScriptCreationType scriptCreationType, string relativePath, string assemblyName, string scriptName) + { + this = default(ScriptKey); + ScriptCreationType = scriptCreationType; + RelativePath = relativePath; + AssemblyName = assemblyName; + ScriptName = scriptName; + FoldersHierarchy = relativePath.Split(new char[1] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); + } + + public override bool Equals(object obj) + { + ScriptKey scriptKey = (ScriptKey)obj; + if (ScriptName != scriptKey.ScriptName) + { + return false; + } + if (AssemblyName != scriptKey.AssemblyName) + { + return false; + } + if (RelativePath != scriptKey.RelativePath) + { + return false; + } + if (ScriptCreationType != scriptKey.ScriptCreationType) + { + return false; + } + return true; + } + + public override int GetHashCode() + { + return ((((((0x50C5D1F ^ ScriptCreationType.GetHashCode()) * 16777619) ^ (RelativePath ?? string.Empty).GetHashCode()) * 16777619) ^ (AssemblyName ?? string.Empty).GetHashCode()) * 16777619) ^ (ScriptName ?? string.Empty).GetHashCode(); + } + + public static bool operator !=(ScriptKey key1, ScriptKey key2) + { + return !key1.Equals(key2); + } + + public static bool operator ==(ScriptKey key1, ScriptKey key2) + { + return key1.Equals(key2); + } + + public static ScriptKey CreateScriptKeyFromString(string stringKey) + { + string[] array = stringKey.Split(new string[1] { 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() }, StringSplitOptions.None); + if (array.Length != 4 || !array[0].TryParseEnum((DescriptionAttribute P_0) => P_0.Description, out var enumValue)) + { + return default(ScriptKey); + } + return new ScriptKey(enumValue, array[1], array[2], array[3]); + } + + public override string ToString() + { + return $"{ScriptCreationType.GetDescription()}{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{RelativePath}{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{AssemblyName}{3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()}{ScriptName}"; + } + } + public abstract class ScriptManager : IDisposable where TScriptInfo : ScriptInfo where TScript : ExecutionEntity + { + [CompilerGenerated] + private sealed class ? + { + public ScriptCreationType ??; + + public string ??; + + public string ??; + + internal bool ?(ScriptKey P_0) + { + return P_0.ScriptCreationType == ??; + } + + internal bool ?(ScriptKey P_0) + { + return P_0.RelativePath == ??; + } + + internal bool ?(ScriptKey P_0) + { + return P_0.AssemblyName == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ScriptManager ??; + + public FileSystemEventArgs ??; + + internal void ?(Task P_0) + { + ??.?(??.FullPath); + } + } + + [CompilerGenerated] + private sealed class ? + { + public ScriptManager ??; + + public FileSystemEventArgs ??; + + internal void ?(Task P_0) + { + ??.?(??.FullPath); + } + } + + [CompilerGenerated] + private sealed class ? + { + public ScriptManager ??; + + public List ??; + + internal void ?(string P_0) + { + ??.??.Add(P_0); + } + + internal void ?(Task P_0) + { + foreach (string item in ??) + { + if (!??.??.Contains(item)) + { + break; + } + ??.??.Remove(item); + if (!??.??.TryGetValue(item, out var value)) + { + continue; + } + foreach (TScriptInfo item2 in new List(value)) + { + ??.?(item2, item); + ??.?(item2); + } + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(string P_0) + { + return P_0.Contains(??); + } + } + + [CompilerGenerated] + private ScriptInfoEventHandler ??; + + [CompilerGenerated] + private ScriptInfoEventHandler ??; + + [CompilerGenerated] + private ScriptInfoEventHandler ??; + + protected Dictionary scriptsInfoCache; + + private readonly Dictionary> ??; + + private readonly Dictionary> ??; + + private readonly FileSystemWatcher ??; + + private readonly HashSet ??; + + private readonly Dictionary ??; + + private readonly object ??; + + protected abstract string DefaultScriptsPath { get; } + + public abstract string CustomScriptsPath { get; } + + public TScriptInfo[] All => scriptsInfoCache.Values.ToArray(); + + public event ScriptInfoEventHandler ScriptAdded + { + [CompilerGenerated] + add + { + ScriptInfoEventHandler scriptInfoEventHandler = ??; + ScriptInfoEventHandler scriptInfoEventHandler2; + do + { + scriptInfoEventHandler2 = scriptInfoEventHandler; + ScriptInfoEventHandler value2 = (ScriptInfoEventHandler)Delegate.Combine(scriptInfoEventHandler2, value); + scriptInfoEventHandler = Interlocked.CompareExchange(ref ??, value2, scriptInfoEventHandler2); + } + while ((object)scriptInfoEventHandler != scriptInfoEventHandler2); + } + [CompilerGenerated] + remove + { + ScriptInfoEventHandler scriptInfoEventHandler = ??; + ScriptInfoEventHandler scriptInfoEventHandler2; + do + { + scriptInfoEventHandler2 = scriptInfoEventHandler; + ScriptInfoEventHandler value2 = (ScriptInfoEventHandler)Delegate.Remove(scriptInfoEventHandler2, value); + scriptInfoEventHandler = Interlocked.CompareExchange(ref ??, value2, scriptInfoEventHandler2); + } + while ((object)scriptInfoEventHandler != scriptInfoEventHandler2); + } + } + + public event ScriptInfoEventHandler ScriptUpdated + { + [CompilerGenerated] + add + { + ScriptInfoEventHandler scriptInfoEventHandler = ??; + ScriptInfoEventHandler scriptInfoEventHandler2; + do + { + scriptInfoEventHandler2 = scriptInfoEventHandler; + ScriptInfoEventHandler value2 = (ScriptInfoEventHandler)Delegate.Combine(scriptInfoEventHandler2, value); + scriptInfoEventHandler = Interlocked.CompareExchange(ref ??, value2, scriptInfoEventHandler2); + } + while ((object)scriptInfoEventHandler != scriptInfoEventHandler2); + } + [CompilerGenerated] + remove + { + ScriptInfoEventHandler scriptInfoEventHandler = ??; + ScriptInfoEventHandler scriptInfoEventHandler2; + do + { + scriptInfoEventHandler2 = scriptInfoEventHandler; + ScriptInfoEventHandler value2 = (ScriptInfoEventHandler)Delegate.Remove(scriptInfoEventHandler2, value); + scriptInfoEventHandler = Interlocked.CompareExchange(ref ??, value2, scriptInfoEventHandler2); + } + while ((object)scriptInfoEventHandler != scriptInfoEventHandler2); + } + } + + public event ScriptInfoEventHandler ScriptDeleted + { + [CompilerGenerated] + add + { + ScriptInfoEventHandler scriptInfoEventHandler = ??; + ScriptInfoEventHandler scriptInfoEventHandler2; + do + { + scriptInfoEventHandler2 = scriptInfoEventHandler; + ScriptInfoEventHandler value2 = (ScriptInfoEventHandler)Delegate.Combine(scriptInfoEventHandler2, value); + scriptInfoEventHandler = Interlocked.CompareExchange(ref ??, value2, scriptInfoEventHandler2); + } + while ((object)scriptInfoEventHandler != scriptInfoEventHandler2); + } + [CompilerGenerated] + remove + { + ScriptInfoEventHandler scriptInfoEventHandler = ??; + ScriptInfoEventHandler scriptInfoEventHandler2; + do + { + scriptInfoEventHandler2 = scriptInfoEventHandler; + ScriptInfoEventHandler value2 = (ScriptInfoEventHandler)Delegate.Remove(scriptInfoEventHandler2, value); + scriptInfoEventHandler = Interlocked.CompareExchange(ref ??, value2, scriptInfoEventHandler2); + } + while ((object)scriptInfoEventHandler != scriptInfoEventHandler2); + } + } + + protected ScriptManager() + { + scriptsInfoCache = new Dictionary(); + ?? = new Dictionary>(); + ?? = new Dictionary>(); + ?? = new FileSystemWatcher(); + ?? = new HashSet(); + ?? = new Dictionary(); + ?? = new object(); + } + + internal virtual void ?() + { + string customScriptsPath = CustomScriptsPath; + if (!Directory.Exists(customScriptsPath)) + { + Directory.CreateDirectory(customScriptsPath); + } + List list = AssemblyLoader.LoadTypes(DefaultScriptsPath, typeof(TScript), null, SearchOption.AllDirectories, loadInMemory: true); + ?(list, ScriptCreationType.Default); + List list2 = AssemblyLoader.LoadTypes(customScriptsPath, typeof(TScript), null, SearchOption.AllDirectories, loadInMemory: true, allowLoadingReferences: true); + ?(list2, ScriptCreationType.Custom); + ??.Path = customScriptsPath; + ??.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Size; + ??.IncludeSubdirectories = true; + ??.Created += ?; + ??.Changed += ?; + ??.Deleted += ?; + ??.EnableRaisingEvents = true; + } + + private void ?(List P_0, ScriptCreationType P_1) + { + if (P_0 == null) + { + return; + } + string scriptsFolderPath = GetScriptsFolderPath(P_1); + foreach (TypeWrapper item in P_0) + { + try + { + ConstructorInfo constructor = item.Type.GetConstructor(Array.Empty()); + string directoryName = Path.GetDirectoryName(?(item.AssemblyLocation, scriptsFolderPath)); + TScriptInfo val = CreateScriptInfo(constructor, P_1, directoryName, item.Type.Assembly.GetName().Name); + if (!(val.Key == default(ScriptKey))) + { + ?(val, item.AssemblyLocation); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + protected abstract string GetScriptsFolderPath(ScriptCreationType scriptCreationType); + + protected abstract TScriptInfo CreateScriptInfo(ConstructorInfo ctor, ScriptCreationType scriptCreationType, string relativePath, string assemblyName); + + protected ScriptKey SearchScriptKey(string scriptName, string assemblyName, string relativePath, ScriptCreationType scriptCreationType = ScriptCreationType.Default) + { + if (!??.TryGetValue(scriptName, out var value)) + { + return default(ScriptKey); + } + if (!value.Any()) + { + return default(ScriptKey); + } + List source = new List(value); + source = source.Where((ScriptKey P_0) => P_0.ScriptCreationType == scriptCreationType).ToList(); + if (!string.IsNullOrEmpty(relativePath)) + { + source = source.Where((ScriptKey P_0) => P_0.RelativePath == relativePath).ToList(); + } + if (!string.IsNullOrEmpty(assemblyName)) + { + source = source.Where((ScriptKey P_0) => P_0.AssemblyName == assemblyName).ToList(); + } + return source.FirstOrDefault(); + } + + private static string ?(string P_0, string P_1) + { + Uri uri = new Uri(P_0); + if (!P_1.EndsWith(Path.DirectorySeparatorChar.ToString())) + { + P_1 += Path.DirectorySeparatorChar; + } + return Uri.UnescapeDataString(new Uri(P_1).MakeRelativeUri(uri).ToString().Replace('/', Path.DirectorySeparatorChar)); + } + + public virtual void Dispose() + { + ??.Created -= ?; + ??.Changed -= ?; + ??.Deleted -= ?; + ??.EnableRaisingEvents = false; + ??.Dispose(); + scriptsInfoCache?.Clear(); + ???.Clear(); + } + + private void ?(object P_0, FileSystemEventArgs P_1) + { + if (!?(P_1.FullPath)) + { + ??.Remove(P_1.FullPath); + Task.Delay(1000).ContinueWith(delegate + { + ?(P_1.FullPath); + }); + } + } + + private void ?(object P_0, FileSystemEventArgs P_1) + { + if (!?(P_1.FullPath)) + { + Task.Delay(1000).ContinueWith(delegate + { + ?(P_1.FullPath); + }); + } + } + + private void ?(object P_0, FileSystemEventArgs P_1) + { + List ?? = new List(); + if (!Path.HasExtension(P_1.FullPath)) + { + string ?? = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + MakeRelativePath(CustomScriptsPath, P_1.FullPath) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + ??.AddRange(??.Keys.Where((string text) => text.Contains(??))); + } + else if (Path.GetExtension(P_1.FullPath) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ??.Add(P_1.FullPath); + } + if (??.Count == 0) + { + return; + } + ??.ForEach(delegate(string item) + { + ??.Add(item); + }); + Task.Delay(2000).ContinueWith(delegate + { + foreach (string item in ??) + { + if (!??.Contains(item)) + { + break; + } + ??.Remove(item); + if (??.TryGetValue(item, out var value)) + { + foreach (TScriptInfo item2 in new List(value)) + { + ?(item2, item); + ?(item2); + } + } + } + }); + } + + private void ?(ScriptInfo P_0) + { + ???.Invoke(P_0, new ScriptInfoEventArgs()); + } + + protected virtual void OnScriptUpdated(ScriptInfo scriptInfo) + { + ???.Invoke(scriptInfo, new ScriptInfoEventArgs()); + } + + private void ?(ScriptInfo P_0) + { + ???.Invoke(P_0, new ScriptInfoEventArgs()); + } + + private void ?(TScriptInfo P_0, string P_1) + { + ScriptKey key = P_0.Key; + scriptsInfoCache.Add(key, P_0); + if (!??.TryGetValue(key.ScriptName, out var value)) + { + value = new List(); + ??.Add(key.ScriptName, value); + } + value.Add(key); + if (!??.TryGetValue(P_1, out var value2)) + { + value2 = new List(); + ??.Add(P_1, value2); + } + value2.Add(P_0); + } + + private void ?(TScriptInfo P_0, string P_1) + { + ScriptKey key = P_0.Key; + scriptsInfoCache.Remove(key); + if (??.TryGetValue(key.ScriptName, out var value)) + { + value.Remove(key); + } + if (??.TryGetValue(P_1, out var value2)) + { + value2.Remove(P_0); + } + if (!value2.Any()) + { + ??.Remove(P_1); + } + } + + private bool ?(string P_0, DateTime P_1) + { + if (??.TryGetValue(P_0, out var value)) + { + return value == P_1; + } + return false; + } + + private void ?(string P_0) + { + try + { + lock (??) + { + DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(P_0); + bool num = ?(P_0, lastWriteTimeUtc); + ??[P_0] = lastWriteTimeUtc; + if (num) + { + return; + } + } + string scriptsFolderPath = GetScriptsFolderPath(ScriptCreationType.Custom); + foreach (TypeWrapper item in AssemblyLoader.?(P_0, typeof(TScript), true, true)) + { + try + { + ConstructorInfo constructor = item.Type.GetConstructor(Array.Empty()); + string directoryName = Path.GetDirectoryName(?(item.AssemblyLocation, scriptsFolderPath)); + TScriptInfo val = CreateScriptInfo(constructor, ScriptCreationType.Custom, directoryName, item.Type.Assembly.GetName().Name); + if (!(val.Key == default(ScriptKey))) + { + ScriptKey key = val.Key; + if (scriptsInfoCache.ContainsKey(key)) + { + scriptsInfoCache[key] = val; + OnScriptUpdated(val); + } + else + { + ?(val, P_0); + ?(val); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + } + + private static bool ?(string P_0) + { + if (!Path.HasExtension(P_0)) + { + return true; + } + if (Path.GetExtension(P_0) != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return true; + } + return false; + } + + public static string MakeRelativePath(string fromPath, string toPath) + { + if (string.IsNullOrEmpty(fromPath)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (string.IsNullOrEmpty(toPath)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Uri uri = new Uri(fromPath); + Uri uri2 = new Uri(toPath); + if (uri.Scheme != uri2.Scheme) + { + return toPath; + } + string text = Uri.UnescapeDataString(uri.MakeRelativeUri(uri2).ToString()); + if (uri2.Scheme.Equals(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), StringComparison.InvariantCultureIgnoreCase)) + { + text = text.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + return text; + } + } + public delegate void ScriptInfoEventHandler(ScriptInfo scriptInfo, ScriptInfoEventArgs e); + /// + /// The base class for strategies + /// + [Published] + public abstract class Strategy : ExecutionEntity, IXElementSerialization, IConnectionStateDependent + { + [CompilerGenerated] + private string ??; + + private StrategyState ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private StrategyEventHandler ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private bool ??; + + private ILogger ??; + + private DateTime ??; + + private DateTime ??; + + private Meter ??; + + private readonly ConnectionStateObserver ??; + + private StrategyState? ??; + + /// + /// Unique ID of the strategy + /// + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + /// + /// The current state of the strategy + /// + public StrategyState State + { + get + { + return ??; + } + internal set + { + StrategyState strategyState = ??; + ?? = strategyState2; + Core.Instance.Strategies.?(this, ??, strategyState); + } + } + + public string InstanceName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override IList Settings + { + get + { + IList settings = base.Settings; + settings.Add(new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), InstanceName) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SeparatorGroup = new SettingItemSeparatorGroup(loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), -1100) + }); + return settings; + } + set + { + if (value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value2)) + { + InstanceName = value2; + } + if (State == StrategyState.Working) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + base.Settings = value; + ???.Invoke(this); + } + } + + public bool NewVersionAvailable + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = flag; + } + } + + public virtual string[] MonitoringConnectionsIds => new string[0]; + + private string DataFolderName => base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + Id + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + + internal string DataFolderPath => Path.Combine(Const.SCRIPTS_DATA_PATH, DataFolderName); + + /// + /// Event occured when strategy write a new log + /// + public event StrategyEventHandler NewLog + { + [CompilerGenerated] + add + { + StrategyEventHandler strategyEventHandler = ??; + StrategyEventHandler strategyEventHandler2; + do + { + strategyEventHandler2 = strategyEventHandler; + StrategyEventHandler value2 = (StrategyEventHandler)Delegate.Combine(strategyEventHandler2, value); + strategyEventHandler = Interlocked.CompareExchange(ref ??, value2, strategyEventHandler2); + } + while ((object)strategyEventHandler != strategyEventHandler2); + } + [CompilerGenerated] + remove + { + StrategyEventHandler strategyEventHandler = ??; + StrategyEventHandler strategyEventHandler2; + do + { + strategyEventHandler2 = strategyEventHandler; + StrategyEventHandler value2 = (StrategyEventHandler)Delegate.Remove(strategyEventHandler2, value); + strategyEventHandler = Interlocked.CompareExchange(ref ??, value2, strategyEventHandler2); + } + while ((object)strategyEventHandler != strategyEventHandler2); + } + } + + /// + /// Event occured if any of strategy settings was changed + /// + public event Action SettingsChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + internal void ?() + { + CheckDisposed(); + string dataFolderPath = DataFolderPath; + if (!Directory.Exists(dataFolderPath)) + { + Directory.CreateDirectory(dataFolderPath); + } + ?? = Core.Instance.Loggers.GetLogger(new LoggerConfig + { + LoggerName = DataFolderName, + OutputFolderPath = Path.Combine(DataFolderPath, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Scope = LoggerScope.General + }); + try + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 3); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Key); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + ?? = new Meter(defaultInterpolatedStringHandler.ToStringAndClear(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + OnInitializeMetrics(??); + } + catch (Exception ex) + { + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (ex.InnerException?.Message ?? ex.Message), StrategyLoggingLevel.Error); + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + State = StrategyState.Created; + try + { + OnCreated(); + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + catch (Exception ex2) + { + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (ex2.InnerException?.Message ?? ex2.Message), StrategyLoggingLevel.Error); + Core.Instance.Loggers.Log(ex2, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + /// + /// Run strategy + /// + public void Run() + { + CheckDisposed(); + if (State == StrategyState.Working) + { + return; + } + string[] monitoringConnectionsIds = MonitoringConnectionsIds; + if (monitoringConnectionsIds != null) + { + string[] array = monitoringConnectionsIds; + foreach (string text in array) + { + if (text != null) + { + Connection connection = Core.Instance.Connections[text]; + if (connection == null || connection.State != ConnectionState.Connected) + { + State = StrategyState.WaitingForConnection; + return; + } + } + } + } + State = StrategyState.Working; + ?? = Core.Instance.TimeUtils.DateTimeUtcNow; + try + { + OnRun(); + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + catch (Exception ex) + { + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (ex.InnerException?.Message ?? ex.Message), StrategyLoggingLevel.Error); + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + /// + /// Stop strategy + /// + public void Stop() + { + CheckDisposed(); + if (State != StrategyState.Working && State != StrategyState.WaitingForConnection) + { + return; + } + bool num = State != StrategyState.WaitingForConnection; + State = StrategyState.Stopped; + ?? = Core.Instance.TimeUtils.DateTimeUtcNow; + if (!num) + { + return; + } + try + { + OnStop(); + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + catch (Exception ex) + { + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (ex.InnerException?.Message ?? ex.Message), StrategyLoggingLevel.Error); + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + /// + /// Remove the strategy + /// + public void Remove() + { + CheckDisposed(); + if (State == StrategyState.Removed) + { + return; + } + if (State == StrategyState.Working) + { + Stop(); + } + try + { + string dataFolderPath = DataFolderPath; + if (Directory.Exists(dataFolderPath)) + { + Directory.Delete(dataFolderPath, recursive: true); + } + } + catch (Exception ex) + { + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.GetFullMessageRecursive(), StrategyLoggingLevel.Error); + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + State = StrategyState.Removed; + try + { + OnRemove(); + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + catch (Exception ex2) + { + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (ex2.InnerException?.Message ?? ex2.Message), StrategyLoggingLevel.Error); + Core.Instance.Loggers.Log(ex2, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + finally + { + ???.Dispose(); + ?? = null; + } + } + + /// + /// Get current metrics from the strategy + /// + /// + public List GetMetrics() + { + CheckDisposed(); + List result = null; + try + { + result = OnGetMetrics(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return result; + } + + /// + /// Get logs from the strategy for specified date range + /// + /// + /// + /// + public LoggerEvent[] GetLogs(DateTime from, DateTime to) + { + return ???.GetHistory(from, to)?.OfType().ToArray() ?? Array.Empty(); + } + + protected virtual void OnCreated() + { + } + + protected virtual void OnRun() + { + } + + protected virtual void OnStop() + { + } + + protected virtual void OnRemove() + { + } + + [Obsolete("Use OnInitializeMetrics() method to initialize System.Diagnostics.Metrics")] + protected virtual List OnGetMetrics() + { + return new List + { + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + (?? == default(DateTime)) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() : Core.Instance.TimeUtils.GetFormatedDateTime(Core.Instance.TimeUtils.ConvertFromUTCToSelectedTimeZone(??)) + }, + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + (?? == default(DateTime)) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() : ((State == StrategyState.Working) ? (Core.Instance.TimeUtils.GetFormatedLongTime(Core.Instance.TimeUtils.DateTimeUtcNow) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Core.Instance.TimeUtils.GetFormatedLongTime(??)) : (Core.Instance.TimeUtils.GetFormatedLongTime(??) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Core.Instance.TimeUtils.GetFormatedLongTime(??))) + } + }; + } + + protected virtual void OnInitializeMetrics(Meter meter) + { + } + + /// + /// Write log message + /// + /// + /// + protected internal void Log(string message, StrategyLoggingLevel level = StrategyLoggingLevel.Info) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + LoggingLevel loggingLevel = level switch + { + StrategyLoggingLevel.Trading => LoggingLevel.Trading, + StrategyLoggingLevel.Error => LoggingLevel.Error, + _ => LoggingLevel.System, + }; + ???.Log(message, dateTimeUtcNow, loggingLevel); + if (?? != null) + { + LoggerEvent loggerEvent = new LoggerEvent + { + Date = dateTimeUtcNow, + Event = message, + Type = loggingLevel + }; + ?(loggerEvent); + } + } + + [NotPublished] + public override void Dispose() + { + ??.Dispose(); + ???.Dispose(); + if (State == StrategyState.Working) + { + Stop(); + } + base.Dispose(); + } + + protected Strategy() + { + Id = Guid.NewGuid().ToString(); + ?? = new ConnectionStateObserver(this, ConnectionStateObserverPriority.Normal, ConnectionState.Connected, ConnectionState.Disconnected, ConnectionState.ConnectionLost); + } + + private void ?(LoggerEvent P_0) + { + ???.Invoke(this, new StrategyEventArgs(State, P_0)); + } + + [NotPublished] + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Key.ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)State)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (SettingItem setting in Settings) + { + xElement2.Add(setting.ToXElement()); + } + xElement.Add(xElement2); + return xElement; + } + + [NotPublished] + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + string stringKey = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value; + base.Key = ScriptKey.CreateScriptKeyFromString(stringKey); + Id = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value; + base.Name = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value; + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + List settings = Serializer.DeserializeXML(xElement, deserializationInfo).OfType().ToList(); + Settings = settings; + } + ?? = (StrategyState)(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToInt() ?? 10); + } + + internal void ?() + { + bool flag; + switch (??) + { + case StrategyState.Working: + case StrategyState.WaitingForConnection: + flag = true; + break; + default: + flag = false; + break; + } + if (flag) + { + Task.Factory.StartNew(Run); + } + ?? = null; + } + + public ConnectionDependency GetConnectionStateDependency() + { + return new ConnectionDependency + { + Behavior = ConnectionDependencyBehavior.PartialDependency, + DependentConnectionsIds = MonitoringConnectionsIds + }; + } + + private void ?(Connection P_0, ConnectionStateChangedEventArgs P_1) + { + if (P_1.NewState == ConnectionState.Connected) + { + if (State == StrategyState.WaitingForConnection) + { + Task.Factory.StartNew(Run); + } + } + else if (State == StrategyState.Working) + { + Task.Factory.StartNew(Stop).ContinueWith((Task task) => State = StrategyState.WaitingForConnection); + } + } + + void IConnectionStateDependent.OnConnectionStateChanged(Connection P_0, ConnectionStateChangedEventArgs P_1) + { + //ILSpy generated this explicit interface implementation from .override directive in ? + this.?(P_0, P_1); + } + + [CompilerGenerated] + private StrategyState ?(Task P_0) + { + return State = StrategyState.WaitingForConnection; + } + } + public class StrategyEventArgs : EventArgs + { + [CompilerGenerated] + private StrategyState ??; + + [CompilerGenerated] + private StrategyState ??; + + [CompilerGenerated] + private LoggerEvent ??; + + public StrategyState StrategyState + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = strategyState; + } + } + + public StrategyState StrategyPreviousState + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = strategyState; + } + } + + public LoggerEvent LoggerEvent + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = loggerEvent; + } + } + + public StrategyEventArgs(StrategyState strategyState, LoggerEvent loggerEvent = null) + { + StrategyState = strategyState; + LoggerEvent = loggerEvent; + } + } + public class StrategyInfo : ScriptInfo + { + internal StrategyInfo(ConstructorInfo P_0, ScriptCreationType P_1, string P_2, string P_3) + : base(P_0, P_1, P_2, P_3) + { + } + + protected override void Initialize(string relativePath, string assemblyName) + { + using Strategy strategy = ctor.Invoke(null) as Strategy; + base.Name = strategy.Name; + base.Description = strategy.Description; + base.Version = strategy.Version; + base.Key = new ScriptKey(base.ScriptCreationType, relativePath, assemblyName, base.Name); + strategy.Key = base.Key; + base.Settings = strategy.Settings as List; + } + + internal Strategy ?() + { + Strategy strategy = ctor?.Invoke(null) as Strategy; + if (strategy != null) + { + strategy.Key = base.Key; + } + return strategy; + } + + public override string ToString() + { + return base.Name; + } + } + public sealed class StrategyManager : ScriptManager + { + [CompilerGenerated] + private new sealed class ? + { + public Strategy ??; + + public StrategyManager ??; + + internal void ?() + { + ??.?(??); + } + } + + private readonly List ??; + + [CompilerGenerated] + private StrategyEventHandler ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private bool ??; + + public Strategy[] Created => ??.ToArray(); + + protected override string DefaultScriptsPath => Const.DEFAULT_STRATEGIES_RELATIVE_PATH; + + public override string CustomScriptsPath => Const.CUSTOM_STRATEGIES_PATH; + + public bool RestoreStateAfterShutdown + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public event StrategyEventHandler StrategyStateChanged + { + [CompilerGenerated] + add + { + StrategyEventHandler strategyEventHandler = ??; + StrategyEventHandler strategyEventHandler2; + do + { + strategyEventHandler2 = strategyEventHandler; + StrategyEventHandler value2 = (StrategyEventHandler)Delegate.Combine(strategyEventHandler2, value); + strategyEventHandler = Interlocked.CompareExchange(ref ??, value2, strategyEventHandler2); + } + while ((object)strategyEventHandler != strategyEventHandler2); + } + [CompilerGenerated] + remove + { + StrategyEventHandler strategyEventHandler = ??; + StrategyEventHandler strategyEventHandler2; + do + { + strategyEventHandler2 = strategyEventHandler; + StrategyEventHandler value2 = (StrategyEventHandler)Delegate.Remove(strategyEventHandler2, value); + strategyEventHandler = Interlocked.CompareExchange(ref ??, value2, strategyEventHandler2); + } + while ((object)strategyEventHandler != strategyEventHandler2); + } + } + + public event Action StrategyCreated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action StrategyRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + internal StrategyManager() + { + ?? = new List(); + RestoreStateAfterShutdown = false; + } + + internal override void ?() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + try + { + base.?(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + public Strategy CreateStrategy(string strategyName, string assemblyName = "", string relativePath = "", ScriptCreationType scriptCreationType = ScriptCreationType.Default) + { + if (string.IsNullOrEmpty(strategyName)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ScriptKey scriptKey = SearchScriptKey(strategyName, assemblyName, relativePath, scriptCreationType); + return CreateStrategy(scriptKey); + } + + public Strategy CreateStrategy(ScriptKey scriptKey) + { + if (scriptsInfoCache.TryGetValue(scriptKey, out var value)) + { + return CreateStrategy(value); + } + return null; + } + + public Strategy CreateStrategy(StrategyInfo strategyInfo) + { + Strategy strategy = strategyInfo.?(); + ?(strategy); + return strategy; + } + + private void ?(Strategy P_0) + { + P_0.?(); + ??.Add(P_0); + ???.Invoke(P_0); + } + + public void DeleteStrategy(Strategy strategy) + { + if (strategy == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??.Remove(strategy); + strategy.Remove(); + strategy.Dispose(); + ???.Invoke(strategy); + } + + public void OnSettingsLoaded() + { + if (RestoreStateAfterShutdown) + { + ?(); + } + } + + public void SaveStrategies() + { + if (?? == null) + { + return; + } + foreach (Strategy item in ??) + { + try + { + Serializer.SerializeXML(Path.Combine(item.DataFolderPath, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), new List { item }); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + public void LoadStrategies() + { + if (!Directory.Exists(Const.SCRIPTS_DATA_PATH)) + { + return; + } + foreach (string item in Directory.EnumerateFiles(Const.SCRIPTS_DATA_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchOption.AllDirectories)) + { + try + { + double version; + Strategy ?? = Serializer.DeserializeXML(item, out version, ?).FirstOrDefault() as Strategy; + if (?? != null) + { + Task.Run(delegate + { + ?(??); + }); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + private void ?() + { + Strategy[] created = Created; + for (int i = 0; i < created.Length; i++) + { + created[i].?(); + } + } + + protected override string GetScriptsFolderPath(ScriptCreationType scriptCreationType) + { + if (scriptCreationType != ScriptCreationType.Default) + { + return Const.CUSTOM_STRATEGIES_PATH; + } + return Path.Combine(Const.EXECUTING_FOLDER, Const.DEFAULT_STRATEGIES_RELATIVE_PATH); + } + + protected override StrategyInfo CreateScriptInfo(ConstructorInfo ctor, ScriptCreationType scriptCreationType, string relativePath, string assemblyName) + { + return new StrategyInfo(ctor, scriptCreationType, relativePath, assemblyName); + } + + public override void Dispose() + { + if (?? != null) + { + foreach (Strategy item in ??) + { + item.Stop(); + item.Dispose(); + } + ??.Clear(); + } + base.Dispose(); + } + + internal void ?(Strategy P_0, StrategyState P_1, StrategyState P_2) + { + ???.Invoke(P_0, new StrategyEventArgs(P_1) + { + StrategyPreviousState = P_2 + }); + } + + protected override void OnScriptUpdated(ScriptInfo scriptInfo) + { + Strategy[] created = Created; + foreach (Strategy strategy in created) + { + if (!(strategy.Key != scriptInfo.Key)) + { + strategy.NewVersionAvailable = true; + } + } + base.OnScriptUpdated(scriptInfo); + } + + private IXElementSerialization ?(XElement P_0) + { + if (P_0 == null) + { + return null; + } + string text = P_0.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value; + if (string.IsNullOrEmpty(text)) + { + return SettingItem.DesserrializationFabric(P_0); + } + ScriptKey key = ScriptKey.CreateScriptKeyFromString(text); + if (!scriptsInfoCache.TryGetValue(key, out var value)) + { + return null; + } + return value.?(); + } + } + public delegate void StrategyEventHandler(Strategy strategy, StrategyEventArgs e); + [ProtoContract] + [Published] + public class StrategyMetric : IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [ProtoMember(1)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public string FormattedValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Name = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + FormattedValue = xElement2.Value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(GetType().Name); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), FormattedValue)); + return xElement; + } + } + public class UpdateArgs + { + [CompilerGenerated] + private UpdateReason ??; + + [CompilerGenerated] + private MessageQuote ??; + + public UpdateReason Reason + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = updateReason; + } + } + + public MessageQuote MessageQuote + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = messageQuote; + } + } + + internal UpdateArgs(UpdateReason P_0, MessageQuote P_1 = null) + { + Reason = P_0; + MessageQuote = P_1; + } + + internal UpdateArgs ?() + { + return new UpdateArgs(Reason, MessageQuote); + } + } + public abstract class CachedRequestParameters : RequestParameters + { + public abstract int GetCacheKey(); + + protected CachedRequestParameters() + { + } + + protected CachedRequestParameters(CachedRequestParameters origin) + : base(origin) + { + } + } + [ProtoContract] + public class GetFutureContractsRequestParameters : CachedRequestParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public override RequestType Type => RequestType.FutureContracts; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(1)] + public string Root + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public string ExchangeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GetFutureContractsRequestParameters() + { + } + + public GetFutureContractsRequestParameters(GetFutureContractsRequestParameters origin) + : base(origin) + { + ConnectionId = origin.ConnectionId; + Root = origin.Root; + ExchangeId = origin.ExchangeId; + UnderlierId = origin.UnderlierId; + } + + public override int GetCacheKey() + { + if (!string.IsNullOrEmpty(UnderlierId)) + { + return UnderlierId.GetHashCode(); + } + HashCode hashCode = default(HashCode); + if (Root != null) + { + hashCode.Add(Root); + } + if (ExchangeId != null) + { + hashCode.Add(ExchangeId); + } + if (UnderlierId != null) + { + hashCode.Add(UnderlierId); + } + return hashCode.ToHashCode(); + } + } + [Published] + [ProtoContract] + public class GetSymbolRequestParameters : CachedRequestParameters + { + [CompilerGenerated] + private string ??; + + public override RequestType Type => RequestType.Symbol; + + [ProtoMember(1)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override int GetCacheKey() + { + return SymbolId.GetHashCode(); + } + + public GetSymbolRequestParameters() + { + } + + public GetSymbolRequestParameters(GetSymbolRequestParameters origin) + : base(origin) + { + SymbolId = origin.SymbolId; + } + } + public sealed class GetNewsArticleContentRequestParameters : RequestParameters + { + [CompilerGenerated] + private string ??; + + public override RequestType Type + { + get + { + throw new NotImplementedException(); + } + } + + public string ArticleId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GetNewsArticleContentRequestParameters() + { + } + + public GetNewsArticleContentRequestParameters(GetNewsArticleContentRequestParameters original) + : base(original) + { + ArticleId = original.ArticleId; + } + } + public abstract class NewsRequestParametersBase : RequestParameters + { + [CompilerGenerated] + private IEnumerable ??; + + public IEnumerable AdditionalParameters + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public NewsRequestParametersBase() + { + } + + public NewsRequestParametersBase(NewsRequestParametersBase original) + : base(original) + { + AdditionalParameters = original.AdditionalParameters; + } + } + public sealed class GetNewsRequestParameters : NewsRequestParametersBase + { + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + public override RequestType Type + { + get + { + throw new NotImplementedException(); + } + } + + public DateTime From + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime To + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GetNewsRequestParameters() + { + } + + public GetNewsRequestParameters(GetNewsRequestParameters original) + : base(original) + { + From = original.From; + To = original.To; + } + } + public sealed class SubscribeNewsRequestParameters : NewsRequestParametersBase + { + [CompilerGenerated] + private string ??; + + public override RequestType Type + { + get + { + throw new NotImplementedException(); + } + } + + public string SubscribeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SubscribeNewsRequestParameters() + { + } + + public SubscribeNewsRequestParameters(SubscribeNewsRequestParameters original) + : base(original) + { + SubscribeId = original.SubscribeId; + } + } + [ProtoContract] + public class GetOptionSeriesRequestParameters : CachedRequestParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public override RequestType Type => RequestType.OptionSeries; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(1)] + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public string ExchangeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GetOptionSeriesRequestParameters() + { + } + + public GetOptionSeriesRequestParameters(GetOptionSeriesRequestParameters origin) + : base(origin) + { + ConnectionId = origin.ConnectionId; + UnderlierId = origin.UnderlierId; + ExchangeId = origin.ExchangeId; + } + + internal GetOptionSeriesRequestParameters(Symbol P_0) + { + ConnectionId = P_0.ConnectionId; + UnderlierId = P_0.Id; + ExchangeId = P_0.ExchangeId; + } + + public override int GetCacheKey() + { + HashCode hashCode = default(HashCode); + if (UnderlierId != null) + { + hashCode.Add(UnderlierId); + } + if (ExchangeId != null) + { + hashCode.Add(ExchangeId); + } + return hashCode.ToHashCode(); + } + } + [ProtoContract] + public class GetStrikesRequestParameters : CachedRequestParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + public override RequestType Type => RequestType.Strikes; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(1)] + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public string SerieId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public DateTime ExpirationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GetStrikesRequestParameters() + { + } + + public GetStrikesRequestParameters(GetStrikesRequestParameters origin) + : base(origin) + { + ConnectionId = origin.ConnectionId; + UnderlierId = origin.UnderlierId; + SerieId = origin.SerieId; + ExpirationDate = origin.ExpirationDate; + } + + internal GetStrikesRequestParameters(OptionSerie P_0) + { + ConnectionId = P_0.ConnectionId; + UnderlierId = P_0.UnderlierId; + SerieId = P_0.Id; + ExpirationDate = P_0.ExpirationDate; + } + + public override int GetCacheKey() + { + HashCode hashCode = default(HashCode); + if (UnderlierId != null) + { + hashCode.Add(UnderlierId); + } + if (SerieId != null) + { + hashCode.Add(SerieId); + } + hashCode.Add(ExpirationDate); + return hashCode.ToHashCode(); + } + } + [Published] + [ProtoContract] + public class OrdersHistoryRequestParameters : ProgressRequestParameters, IXElementSerialization + { + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + public override RequestType Type => RequestType.OrdersHistory; + + [ProtoMember(1)] + public DateTime From + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public DateTime To + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), From)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), To)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + From = xElement.ToDateTime(toUTC: true); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + From = xElement2.ToDateTime(toUTC: true); + } + } + } + [Published] + public class PnLRequestParameters : RequestParameters + { + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Account ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + public override RequestType Type => RequestType.PnL; + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double OpenPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double ClosePrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public PnLRequestParameters() + { + OpenPrice = double.NaN; + ClosePrice = double.NaN; + Quantity = double.NaN; + } + + public PnLRequestParameters(PnLRequestParameters original) + { + Symbol = original.Symbol; + Account = original.Account; + OpenPrice = original.OpenPrice; + ClosePrice = original.ClosePrice; + Side = original.Side; + Quantity = original.Quantity; + PositionId = original.PositionId; + } + } + public abstract class ProgressRequestParameters : RequestParameters + { + [CompilerGenerated] + private IProgress ??; + + public IProgress Progress + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ProgressRequestParameters() + { + Progress = new Progress(); + } + + protected ProgressRequestParameters(ProgressRequestParameters origin) + : base(origin) + { + Progress = origin.Progress; + } + } + [Published] + public class ReportRequestParameters : ProgressRequestParameters + { + [CompilerGenerated] + private ReportType ??; + + public override RequestType Type => RequestType.Report; + + public ReportType ReportType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ReportRequestParameters() + { + } + + public ReportRequestParameters(ReportRequestParameters origin) + : base((ProgressRequestParameters)origin) + { + ReportType = origin.ReportType.?(); + } + } + [Published] + public abstract class RequestParameters : IEquatable + { + [CompilerGenerated] + private CancellationToken ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private readonly long ??; + + private static long ??; + + public abstract RequestType Type { get; } + + public CancellationToken CancellationToken + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string SendingSource + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public long RequestId + { + [CompilerGenerated] + get + { + return ??; + } + } + + protected RequestParameters() + { + ?? = Interlocked.Increment(ref ??); + } + + protected RequestParameters(RequestParameters origin) + { + CancellationToken = origin.CancellationToken; + SendingSource = origin.SendingSource; + ?? = origin.RequestId; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(41, 3); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SendingSource); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public bool Equals(RequestParameters other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + return RequestId == other.RequestId; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((RequestParameters)obj); + } + + public override int GetHashCode() + { + return RequestId.GetHashCode(); + } + } + [ProtoContract] + public class SearchSymbolsRequestParameters : CachedRequestParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IList ?? = new List(); + + [CompilerGenerated] + private IList ?? = new List(); + + [CompilerGenerated] + private Func ??; + + public override RequestType Type => RequestType.SearchSymbol; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(1)] + public string FilterName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public IList ExchangeIds + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public IList SymbolTypes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Func GetSynonyms + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SearchSymbolsRequestParameters() + { + } + + public SearchSymbolsRequestParameters(SearchSymbolsRequestParameters origin) + : base(origin) + { + ConnectionId = origin.ConnectionId; + FilterName = origin.FilterName; + ExchangeIds = new List(origin.ExchangeIds); + SymbolTypes = new List(origin.SymbolTypes); + GetSynonyms = origin.GetSynonyms; + } + + public override int GetCacheKey() + { + HashCode hashCode = default(HashCode); + hashCode.Add(FilterName ?? string.Empty); + hashCode.Add(((IStructuralEquatable)ExchangeIds.ToArray()).GetHashCode((IEqualityComparer)EqualityComparer.Default)); + hashCode.Add(((IStructuralEquatable)SymbolTypes.Cast().ToArray()).GetHashCode((IEqualityComparer)EqualityComparer.Default)); + return hashCode.ToHashCode(); + } + } + /// + /// Defines quote parameters for subscribtion + /// + [ProtoContract] + public class SubscribeQuotesParameters : RequestParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private SubscribeQuoteType ??; + + public override RequestType Type => RequestType.QuoteSubscribe; + + /// + /// Symbol Id + /// + [ProtoMember(1)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + /// + /// Quote type + /// + [ProtoMember(2)] + public SubscribeQuoteType SubscribeType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = subscribeQuoteType; + } + } + + /// + /// SubscribeQuotesParameters constructor + /// + public SubscribeQuotesParameters(string symbolId, SubscribeQuoteType subscribeQuoteType) + { + SymbolId = symbolId; + SubscribeType = subscribeQuoteType; + } + + internal SubscribeQuotesParameters() + { + } + } + [Published] + [ProtoContract] + public class TradesHistoryRequestParameters : ProgressRequestParameters, IXElementSerialization + { + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + public override RequestType Type => RequestType.TradesHistory; + + public Interval Interval => new Interval(From, To); + + [ProtoMember(1)] + public DateTime From + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public DateTime To + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + public bool ForceReload + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), From)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), To)); + if (!string.IsNullOrEmpty(SymbolId)) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SymbolId)); + } + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ForceReload)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + From = xElement.ToDateTime(toUTC: true); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + From = xElement2.ToDateTime(toUTC: true); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + SymbolId = xElement3.ToString(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + ForceReload = xElement4.ToBool(); + } + } + + public TradesHistoryRequestParameters() + { + } + + public TradesHistoryRequestParameters(TradesHistoryRequestParameters origin) + : base((ProgressRequestParameters)origin) + { + From = origin.From; + To = origin.To; + SymbolId = origin.SymbolId; + ForceReload = origin.ForceReload; + } + } + [Published] + public sealed class CancelOrderRequestParameters : TradingRequestParameters, ILoggable + { + [CompilerGenerated] + private IOrder ??; + + private string ??; + + public override RequestType Type => RequestType.CancelOrder; + + public IOrder Order + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string OrderId + { + get + { + string id = ??; + if (id == null) + { + IOrder order = Order; + if (order == null) + { + return null; + } + id = order.Id; + } + return id; + } + set + { + ?? = value; + } + } + + public override string ConnectionId => Order.Symbol?.ConnectionId; + + public override string Event + { + get + { + try + { + return OrderType.Format(Order) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Order.OrderTypeId; + } + } + + public override string Message + { + get + { + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler; + if (Order is Order order) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(14, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(order.Connection.Name); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder3.Append(ref handler); + } + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(10, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.Symbol.Name); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder4.Append(ref handler); + string text = Core.Instance.CustomAccountPropertiesProvider.GetProperty(Order.Account, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as string; + string value = (string.IsNullOrEmpty(text) ? Order.Account.Name : (Order.Account.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder5 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(value); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder5.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder6 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.Symbol.FormatQuantity(Order.RemainingQuantity)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder6.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder7 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.Id); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder7.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder8 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.Side); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder8.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder9 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(14, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(OrderType.Format(Order)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder9.Append(ref handler); + string orderTypeId = Order.OrderTypeId; + if (!(orderTypeId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && !(orderTypeId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(orderTypeId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (orderTypeId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder10 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(17, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.Symbol.FormatOffset(Order.TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + stringBuilder10.Append(ref handler); + } + } + else + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder11 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(17, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.Symbol.FormatPrice(Order.TriggerPrice)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder11.Append(ref handler); + } + } + else + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder12 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + handler.AppendFormatted(Order.Symbol.FormatPrice(Order.Price)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder12.Append(ref handler); + } + if (Order.StopLoss != null) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder13 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.StopLoss.Format(Order.Symbol)); + stringBuilder13.Append(ref handler); + } + if (Order.TakeProfit != null) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder14 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Order.TakeProfit.Format(Order.Symbol)); + stringBuilder14.Append(ref handler); + } + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder15 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Core.Instance.TimeUtils.DateTimeUtcNow); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder15.Append(ref handler); + if (!string.IsNullOrEmpty(base.SendingSource)) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder16 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.SendingSource); + stringBuilder16.Append(ref handler); + } + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder17 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.RequestId); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder17.Append(ref handler); + return stringBuilder.ToString(); + } + } + + public CancelOrderRequestParameters() + { + } + + public CancelOrderRequestParameters(CancelOrderRequestParameters original) + : base(original) + { + OrderId = original.OrderId; + Order = original.Order; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 2); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Order); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override Account GetAccount() + { + return Order?.Account; + } + } + [Published] + public class ClosePositionRequestParameters : TradingRequestParameters, ILoggable + { + [CompilerGenerated] + private Position ??; + + [CompilerGenerated] + private double ??; + + public override RequestType Type => RequestType.ClosePosition; + + public Position Position + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double CloseQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ConnectionId => Position?.Symbol?.ConnectionId; + + public override string Event => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Message + { + get + { + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(14, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Position.Connection.Name); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder3.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(10, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Position.Symbol.Name); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder4.Append(ref handler); + string text = Core.Instance.CustomAccountPropertiesProvider.GetProperty(Position.Account, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as string; + string value = (string.IsNullOrEmpty(text) ? Position.Account.Name : (Position.Account.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder5 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(value); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder5.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder6 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Position.Symbol.FormatQuantity(Position.Quantity)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder6.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder7 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Position.Id); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder7.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder8 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Position.Side); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder8.Append(ref handler); + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder9 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + handler.AppendFormatted(Position.Symbol.FormatPrice(Position.CurrentPrice)); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder9.Append(ref handler); + Order stopLoss = Position.StopLoss; + if (stopLoss != null) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder10 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted((stopLoss.OrderTypeId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ? Position.Symbol.FormatOffset(stopLoss.TrailOffset, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) : Position.Symbol.FormatPrice(stopLoss.Price)); + stringBuilder10.Append(ref handler); + } + Order takeProfit = Position.TakeProfit; + if (takeProfit != null) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder11 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Position.Symbol.FormatPrice(takeProfit.Price)); + stringBuilder11.Append(ref handler); + } + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder12 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(Core.Instance.TimeUtils.DateTimeUtcNow.ToString()); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder12.Append(ref handler); + if (!string.IsNullOrEmpty(base.SendingSource)) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder13 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.SendingSource); + stringBuilder13.Append(ref handler); + } + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder14 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.RequestId); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder14.Append(ref handler); + return stringBuilder.ToString(); + } + } + + public ClosePositionRequestParameters() + { + } + + public ClosePositionRequestParameters(ClosePositionRequestParameters origin) + : base(origin) + { + Position = origin.Position; + CloseQuantity = origin.CloseQuantity; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 3); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(CloseQuantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Position); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected override Account GetAccount() + { + return Position?.Account; + } + } + public class ConvertPositionRequestParameters : ClosePositionRequestParameters + { + [CompilerGenerated] + private string ??; + + public override RequestType Type => RequestType.ConvertPosition; + + public string ProductCode + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public class LinkOCORequestParameters : TradingRequestParameters + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal string ?(IOrder P_0) + { + return P_0.Id; + } + } + + [CompilerGenerated] + private List ??; + + public override RequestType Type => RequestType.Custom; + + public override string Event => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Message + { + get + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(21, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.RequestId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + + public override string ConnectionId => OrdersToLink?.FirstOrDefault()?.ConnectionId; + + public List OrdersToLink + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + protected override Account GetAccount() + { + return OrdersToLink.FirstOrDefault()?.Account; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 2); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrdersToLink?.Select((IOrder P_0) => P_0.Id).ToArray()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [Published] + public class ModifyOrderRequestParameters : OrderRequestParameters + { + [CompilerGenerated] + private string ??; + + public override RequestType Type => RequestType.ModifyOrder; + + public override string Event + { + get + { + if (base.OrderType == null) + { + return string.Empty; + } + return base.OrderType.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + + /// + /// Id of the order + /// + public string OrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [NotPublished] + public ModifyOrderRequestParameters() + { + } + + public ModifyOrderRequestParameters(IOrder order) + : base(order) + { + OrderId = order.Id; + base.Quantity = order.RemainingQuantity; + } + + public ModifyOrderRequestParameters(ModifyOrderRequestParameters original) + : base(original) + { + OrderId = original.OrderId; + } + + public override object Clone() + { + return new ModifyOrderRequestParameters(this); + } + + public override string ToString() + { + return OrderId + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + base.ToString() + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + } + [Published] + public abstract class OrderRequestParameters : TradingRequestParameters, ICloneable, IXElementSerialization, IEquatable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal int ?(DealTicketItem P_0) + { + return P_0.SortIndex; + } + } + + private string ??; + + private Symbol ??; + + private string ??; + + [CompilerGenerated] + private Account ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + private string ??; + + private OrderType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private TimeInForce ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + private List ??; + + private readonly LocalOrder ??; + + private static readonly ListEqualityComparer ?? = new ListEqualityComparer(EqualityComparer.Default); + + private static readonly ListEqualityComparer ?? = new ListEqualityComparer(EqualityComparer.Default); + + public override string ConnectionId => Symbol?.ConnectionId; + + public string SymbolId + { + get + { + return Symbol?.Id ?? ??; + } + set + { + ?? = value; + } + } + + public Symbol Symbol + { + get + { + return ??; + } + set + { + ?? = value; + ?? = null; + } + } + + public string AccountId + { + get + { + return Account?.Id ?? ??; + } + set + { + ?? = value; + } + } + + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Total + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string QuantityDefinitionSettingName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string OrderTypeId + { + get + { + return ??; + } + set + { + ?? = value; + ?? = null; + } + } + + public OrderType OrderType + { + get + { + if (?? != null) + { + return ??.OrderType; + } + if (?? == null && Symbol != null && !string.IsNullOrEmpty(OrderTypeId)) + { + ?? = Symbol.GetAlowedOrderTypes(null)?.FirstOrDefault((OrderType P_0) => P_0.Id == OrderTypeId); + } + return ??; + } + } + + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TriggerPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TrailOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeInForce TimeInForce + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime ExpirationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Slippage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SlTpHolder StopLoss + { + get + { + return StopLossItems.FirstOrDefault(); + } + set + { + StopLossItems.Clear(); + if (value != null) + { + StopLossItems.Add(value); + } + } + } + + public SlTpHolder TakeProfit + { + get + { + return TakeProfitItems.FirstOrDefault(); + } + set + { + TakeProfitItems.Clear(); + if (value != null) + { + TakeProfitItems.Add(value); + } + } + } + + public List StopLossItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = list; + } + } + + public List TakeProfitItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = list; + } + } + + public string GroupId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Comment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList AdditionalParameters + { + get + { + List list = new List(??); + if (TimeInForce != TimeInForce.Default) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TimeInForce, force: true); + } + if (ExpirationTime != default(DateTime)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationTime, force: true); + } + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Side, force: true); + if (!double.IsNaN(Quantity)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity, force: true); + } + if (!double.IsNaN(Total)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Total, force: true); + } + if (!double.IsNaN(Price)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Price, force: true); + } + if (!double.IsNaN(TriggerPrice)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TriggerPrice, force: true); + } + if (!double.IsNaN(TrailOffset)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TrailOffset, force: true); + } + if (!string.IsNullOrEmpty(Comment)) + { + list.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Comment, force: true); + } + return list; + } + set + { + if (value == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??.Clear(); + foreach (SettingItem item in value) + { + string name = item.Name; + if (name != null) + { + switch (name.Length) + { + case 5: + switch (name[0]) + { + case 'T': + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Total = (double)item.Value; + } + break; + case 'P': + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Price = (double)item.Value; + } + break; + } + break; + case 13: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() && item.Value is SelectItem selectItem) + { + TimeInForce = (TimeInForce)(object)selectItem.Value; + } + break; + case 10: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ExpirationTime = (DateTime)item.Value; + } + break; + case 4: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() && item.Value is SelectItem selectItem2) + { + Side = (Side)(object)selectItem2.Value; + } + break; + case 8: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Quantity = (double)item.Value; + } + break; + case 12: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + TriggerPrice = (double)item.Value; + } + break; + case 11: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + TrailOffset = (int)item.Value; + } + break; + case 7: + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Comment = item.Value?.ToString(); + } + break; + } + } + ??.Add(item.GetCopy()); + } + } + } + + public override string Message + { + get + { + IOrderedEnumerable orderedEnumerable = OrderType?.GetDealTicketItems(this)?.OrderBy((DealTicketItem P_0) => P_0.SortIndex); + if (orderedEnumerable == null) + { + return string.Empty; + } + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler; + foreach (DealTicketItem item in orderedEnumerable) + { + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(4, 2, stringBuilder2); + handler.AppendFormatted(item.Key); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(item.FormattedValue); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder3.Append(ref handler); + } + stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(base.RequestId); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + stringBuilder4.Append(ref handler); + return stringBuilder.ToString(); + } + } + + protected OrderRequestParameters() + { + ?(); + } + + protected OrderRequestParameters(IOrder order) + : this() + { + Symbol = order.Symbol; + Account = order.Account; + Side = order.Side; + Quantity = order.TotalQuantity; + OrderTypeId = order.OrderTypeId; + ?? = order as LocalOrder; + Price = order.Price; + TriggerPrice = order.TriggerPrice; + TrailOffset = order.TrailOffset; + TimeInForce = order.TimeInForce; + ExpirationTime = order.ExpirationTime; + PositionId = order.PositionId; + GroupId = order.GroupId; + Comment = order.Comment; + SlTpHolder[] stopLossItems = order.StopLossItems; + foreach (SlTpHolder slTpHolder in stopLossItems) + { + StopLossItems.Add(slTpHolder.Clone() as SlTpHolder); + } + stopLossItems = order.TakeProfitItems; + foreach (SlTpHolder slTpHolder2 in stopLossItems) + { + TakeProfitItems.Add(slTpHolder2.Clone() as SlTpHolder); + } + try + { + if (OrderType == null) + { + return; + } + IList orderSettings = OrderType.GetOrderSettings(this, new FormatSettings + { + DisplayQuantityInLots = true + }); + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TimeInForce); + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationTime); + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Side); + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity); + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Price); + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TriggerPrice); + if (!double.IsNaN(TrailOffset)) + { + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TrailOffset); + } + orderSettings.UpdateItemValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Comment); + if (order.AdditionalInfo != null) + { + foreach (AdditionalInfoItem item in order.AdditionalInfo) + { + orderSettings.UpdateItemValue(item.Id, item.Value); + } + } + AdditionalParameters = orderSettings; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + protected OrderRequestParameters(OrderRequestParameters origin) + : base(origin) + { + ?(); + UpdateFrom(origin); + } + + private void ?() + { + ?? = new List(); + Price = double.NaN; + TriggerPrice = double.NaN; + TrailOffset = double.NaN; + StopLossItems = new List(); + TakeProfitItems = new List(); + } + + protected override Account GetAccount() + { + return Account; + } + + public abstract object Clone(); + + public void UpdateFrom(OrderRequestParameters origin) + { + if (origin == null) + { + return; + } + Symbol = origin.Symbol; + Account = origin.Account; + Side = origin.Side; + Quantity = origin.Quantity; + Total = origin.Total; + OrderTypeId = origin.OrderTypeId; + Price = origin.Price; + TriggerPrice = origin.TriggerPrice; + TrailOffset = origin.TrailOffset; + TimeInForce = origin.TimeInForce; + ExpirationTime = origin.ExpirationTime; + Slippage = origin.Slippage; + PositionId = origin.PositionId; + GroupId = origin.GroupId; + Comment = origin.Comment; + AdditionalParameters = origin.AdditionalParameters; + base.SendingSource = origin.SendingSource; + QuantityDefinitionSettingName = origin.QuantityDefinitionSettingName; + base.CancellationToken = origin.CancellationToken; + foreach (SlTpHolder stopLossItem in origin.StopLossItems) + { + StopLossItems.Add(stopLossItem.Clone() as SlTpHolder); + } + foreach (SlTpHolder takeProfitItem in origin.TakeProfitItems) + { + TakeProfitItems.Add(takeProfitItem.Clone() as SlTpHolder); + } + } + + public void ApplyValuesFrom(OrderRequestParameters other) + { + if (other != null) + { + if (other.Symbol != null) + { + Symbol = other.Symbol; + } + if (other.Account != null) + { + Account = other.Account; + } + if (!string.IsNullOrEmpty(other.OrderTypeId)) + { + OrderTypeId = other.OrderTypeId; + } + if (other.Slippage != 0) + { + Slippage = other.Slippage; + } + if (!string.IsNullOrEmpty(other.PositionId)) + { + PositionId = other.PositionId; + } + if (!string.IsNullOrEmpty(other.GroupId)) + { + GroupId = other.GroupId; + } + if (!string.IsNullOrEmpty(other.SendingSource)) + { + base.SendingSource = other.SendingSource; + } + if (!string.IsNullOrEmpty(other.QuantityDefinitionSettingName)) + { + QuantityDefinitionSettingName = other.QuantityDefinitionSettingName; + } + if (other.CancellationToken != CancellationToken.None) + { + base.CancellationToken = other.CancellationToken; + } + if (other.StopLossItems.Any()) + { + StopLossItems = other.StopLossItems; + } + if (other.TakeProfitItems.Any()) + { + TakeProfitItems = other.TakeProfitItems; + } + IList additionalParameters = AdditionalParameters; + IList additionalParameters2 = other.AdditionalParameters; + additionalParameters.MergeWith(additionalParameters2); + AdditionalParameters = additionalParameters; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 7); + defaultInterpolatedStringHandler.AppendFormatted(base.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderTypeId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Quantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType?.GetFillPrice(this)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (Symbol != null) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Symbol.CreateInfo().ToXElement())); + } + if (Account != null) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Account.CreateInfo().ToXElement())); + } + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)Side).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Total)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuantityDefinitionSettingName)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OrderTypeId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Price)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TriggerPrice)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TrailOffset)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)TimeInForce).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationTime)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Slippage)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PositionId)); + if (StopLossItems.Count > 0) + { + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (SlTpHolder stopLossItem in StopLossItems) + { + xElement2.Add(stopLossItem.ToXElement()); + } + xElement.Add(xElement2); + } + if (TakeProfitItems.Count > 0) + { + XElement xElement3 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (SlTpHolder takeProfitItem in TakeProfitItems) + { + xElement3.Add(takeProfitItem.ToXElement()); + } + xElement.Add(xElement3); + } + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GroupId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Comment)); + if (AdditionalParameters != null) + { + XElement xElement4 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (SettingItem additionalParameter in AdditionalParameters) + { + xElement4.Add(additionalParameter.ToXElement()); + } + xElement.Add(xElement4); + } + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement == null) + { + return; + } + XElement xElement2 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + XElement xElement3 = xElement2.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + SymbolInfo symbolInfo = new SymbolInfo(); + symbolInfo.FromXElement(xElement3, deserializationInfo); + Symbol = Core.Instance.GetSymbol(symbolInfo); + } + } + XElement xElement4 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + XElement xElement5 = xElement4.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + ? ? = new ?(); + ?.FromXElement(xElement5, deserializationInfo); + Account = Core.Instance.GetAccount(?); + } + } + XElement xElement6 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + Side = (Side)xElement6.ToInt(); + } + XElement xElement7 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + Quantity = xElement7.ToDouble(); + } + XElement xElement8 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + Total = xElement8.ToDouble(); + } + XElement xElement9 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + QuantityDefinitionSettingName = xElement9.ToString(); + } + XElement xElement10 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + OrderTypeId = xElement10.Value; + } + XElement xElement11 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + Price = xElement11.ToDouble(); + } + XElement xElement12 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + TriggerPrice = xElement12.ToDouble(); + } + XElement xElement13 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement13 != null) + { + TrailOffset = xElement13.ToDouble(); + } + XElement xElement14 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement14 != null) + { + TimeInForce = (TimeInForce)xElement14.ToInt(); + } + XElement xElement15 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement15 != null) + { + ExpirationTime = xElement15.ToDateTime(); + } + XElement xElement16 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement16 != null) + { + Slippage = xElement16.ToInt(); + } + XElement xElement17 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement17 != null) + { + PositionId = xElement17.Value; + } + XElement xElement18 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement18 != null) + { + foreach (XElement item2 in xElement18.Elements()) + { + SlTpHolder slTpHolder = new SlTpHolder(); + slTpHolder.FromXElement(item2, deserializationInfo); + StopLossItems.Add(slTpHolder); + } + } + XElement xElement19 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement19 != null) + { + foreach (XElement item3 in xElement19.Elements()) + { + SlTpHolder slTpHolder2 = new SlTpHolder(); + slTpHolder2.FromXElement(item3, deserializationInfo); + TakeProfitItems.Add(slTpHolder2); + } + } + XElement xElement20 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement20 == null) + { + return; + } + List list = new List(); + foreach (XElement item4 in xElement20.Elements()) + { + if (Serializer.DeserializeNode(item4, deserializationInfo) is SettingItem item) + { + list.Add(item); + } + } + AdditionalParameters = list; + } + + public bool Equals(OrderRequestParameters other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (?? == other.?? && object.Equals(??, other.??) && object.Equals(Account, other.Account) && Side == other.Side && Quantity.Equals(other.Quantity) && Total.Equals(other.Total) && QuantityDefinitionSettingName == other.QuantityDefinitionSettingName && Price.Equals(other.Price) && TriggerPrice.Equals(other.TriggerPrice) && TrailOffset.Equals(other.TrailOffset) && TimeInForce == other.TimeInForce && ExpirationTime.Equals(other.ExpirationTime) && Slippage == other.Slippage && PositionId == other.PositionId && GroupId == other.GroupId && Comment == other.Comment && ??.Equals(StopLossItems, other.StopLossItems) && ??.Equals(TakeProfitItems, other.TakeProfitItems)) + { + return ??.Equals(??, other.??); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((OrderRequestParameters)obj); + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(??); + hashCode.Add(??); + hashCode.Add(??); + hashCode.Add(Account); + hashCode.Add((int)Side); + hashCode.Add(Quantity); + hashCode.Add(Total); + hashCode.Add(QuantityDefinitionSettingName); + hashCode.Add(Price); + hashCode.Add(TriggerPrice); + hashCode.Add(TrailOffset); + hashCode.Add((int)TimeInForce); + hashCode.Add(ExpirationTime); + hashCode.Add(Slippage); + hashCode.Add(PositionId); + hashCode.Add(StopLossItems); + hashCode.Add(TakeProfitItems); + hashCode.Add(GroupId); + hashCode.Add(Comment); + return hashCode.ToHashCode(); + } + + [CompilerGenerated] + private bool ?(OrderType P_0) + { + return P_0.Id == OrderTypeId; + } + } + public class PaperRequest : PlaceOrderRequestParameters + { + public PaperRequest() + { + } + + public PaperRequest(PaperRequest request) + : base(request) + { + } + } + public class PlaceMultiOrderOrderRequestParameters : TradingRequestParameters + { + [CompilerGenerated] + private PlaceOrderRequestParameters[] ??; + + [CompilerGenerated] + private GroupOrderType ??; + + public override string ConnectionId => OrderParameters?.FirstOrDefault()?.Symbol?.ConnectionId; + + public override string Event => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override string Message + { + get + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(25, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.RequestId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + + public override RequestType Type => RequestType.PlaceMultiOrderOrder; + + public PlaceOrderRequestParameters[] OrderParameters + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GroupOrderType GroupOrderType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + protected override Account GetAccount() + { + return null; + } + + public PlaceMultiOrderOrderRequestParameters() + { + } + + public PlaceMultiOrderOrderRequestParameters(PlaceMultiOrderOrderRequestParameters original) + : base(original) + { + OrderParameters = original.OrderParameters; + GroupOrderType = original.GroupOrderType; + } + } + [Published] + public class PlaceOrderRequestParameters : OrderRequestParameters + { + public override RequestType Type => RequestType.PlaceOrder; + + public override string Event => (base.OrderType?.Name ?? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public PlaceOrderRequestParameters() + { + } + + public PlaceOrderRequestParameters(IOrder order) + : base(order) + { + } + + public PlaceOrderRequestParameters(OrderRequestParameters original) + : base(original) + { + } + + public override object Clone() + { + return new PlaceOrderRequestParameters(this); + } + } + public class TradingOperationParameters + { + [CompilerGenerated] + private Account ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private IOrder ??; + + [CompilerGenerated] + private Position ??; + + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IOrder Order + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Position Position + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + [Published] + public abstract class TradingRequestParameters : RequestParameters, IConnectionBindedObject, ILoggable, ICurrentAccount, ISubTradingOperation + { + [CompilerGenerated] + private readonly GroupTradingOperation ??; + + public abstract string ConnectionId { get; } + + public abstract string Event { get; } + + public abstract string Message { get; } + + public GroupTradingOperation ParentOperation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + Account ICurrentAccount.CurrentAccount + { + get + { + return GetAccount(); + } + set + { + } + } + + protected abstract Account GetAccount(); + + public TradingRequestParameters() + { + } + + public TradingRequestParameters(TradingRequestParameters origin) + : base(origin) + { + ParentOperation = origin.ParentOperation; + } + } + /// + /// SettingItem cast type + /// + public enum SettingItemType + { + Undefined, + String, + Boolean, + BooleanSwitcher, + Integer, + Double, + Selector, + SelectorLocalized, + DateTime, + Account, + Symbol, + Password, + Period, + File, + Group, + RadioLocalized, + Action, + Font, + TimeZone, + Rss, + HotkeyList, + Object, + ConditionSet, + Alignment, + PairColor, + Color, + Sound, + LineOptions, + TimeZoneManager, + FibonacciLevelOptions, + RangeSelector, + DrawingPoints, + TimeFrameConfig, + BooleanLocalized, + OAuth, + Label, + ClusterColoringLevels, + ArbitageSymbols, + TextArea, + OrderRequestParameters, + IconedAction, + PnlAlertsContainer, + TimeInTradeContainer, + SymbolsList, + Slider, + DoubleWithLink, + Custom, + Long, + MinotauroFibonacciLevelOptions, + OTP, + Condition, + BigTextArea + } + /// + /// SettingItem state + /// + public enum VisibilityMode + { + Visible, + Hidden + } + public enum MultipleRelationCondition + { + IfAny, + IfAll + } + /// + /// Specifies the DatePicker time format. + /// + public enum DatePickerFormat + { + /// + /// Date only + /// + Date, + /// + /// Date and time + /// + DateTime, + /// + /// Time only + /// + Time, + /// + /// Time with seconds + /// + LongTime, + /// + /// + /// + LongDateTime + } + public enum SettingItemValueChangingBehavior + { + Default, + WithConfirmation + } + public enum SettingItemValueChangingReason + { + Unknown, + Manually, + Programmatically + } + public enum IconType + { + Plus, + Trash, + Duplicate + } + public enum IconDisplayType + { + Visible, + VisibleOnHover + } + public class GroupActionInfo + { + [CompilerGenerated] + private Func ??; + + [CompilerGenerated] + private IconType ??; + + [CompilerGenerated] + private object ?? = new object(); + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private ManualChangesApplyingType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public Func Action + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = func; + } + } + + public IconType IconType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object Tag + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool NeedActionConfirmation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ManualChangesApplyingType ManualChangesApplyingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ConfirmationText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Marker + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Tooltip + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GroupActionInfo(Func action) + { + Action = action; + } + } + public enum ManualChangesApplyingType + { + Discard, + Apply, + Confirm + } + public interface ISettingsGroup + { + string Text { get; } + + int SortIndex { get; } + + ISettingsGroup ParentGroup { get; } + + IList ChildGroups { get; } + + GroupActionInfo FirstActionInfo { get; } + + GroupActionInfo SecondActionInfo { get; } + } + public interface ISettingsGroupCollapseBehaviour + { + SettingsGroupCollapseBehaviour CollapseBehaviour { get; set; } + } + public enum SettingsGroupCollapseBehaviour + { + Normal, + AlwaysExpanded + } + /// + /// Typecasts setting as TabControl item + /// + [Serializable] + [Published] + [DataContract] + public sealed class SettingItemGroup : SettingItemList, ISettingsGroup + { + public bool AllowCreateEmptyGroup; + + [CompilerGenerated] + private GroupActionInfo ??; + + [CompilerGenerated] + private GroupActionInfo ??; + + public override SettingItemType Type => SettingItemType.Group; + + public GroupActionInfo FirstActionInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GroupActionInfo SecondActionInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + string ISettingsGroup.Text => Text; + + int ISettingsGroup.SortIndex => base.SortIndex; + + ISettingsGroup ISettingsGroup.ParentGroup => base.Group; + + IList ISettingsGroup.ChildGroups => (Value as IList)?.OfType().ToList() ?? new List(); + + protected override List Items + { + get + { + return base.Items; + } + set + { + if (value != null) + { + foreach (SettingItem item in value) + { + item.Group = this; + } + } + base.Items = value; + } + } + + public SettingItemGroup() + : base(string.Empty, new List()) + { + } + + public SettingItemGroup(string name, IList items, int sortIndex = 0) + : base(name, items, sortIndex) + { + foreach (SettingItem item in items) + { + ?(item); + } + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemGroup(base.Name, CopyItems(), base.SortIndex) + { + Text = Text + }; + } + + public void AddItem(SettingItem item) + { + Items.Add(item); + ?(item); + } + + public override int GetHashCode() + { + return SettingItemVisualGroup.?(this); + } + + private void ?(SettingItem P_0) + { + P_0.Group = this; + } + + [NotPublished] + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), base.Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + for (int i = 0; i < Items.Count; i++) + { + try + { + xElement.Add(Items[i].ToXElement()); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + return xElement; + } + + [NotPublished] + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.Name = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + Items.Clear(); + foreach (XElement item in element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (Serializer.DeserializeNode(item, deserializationInfo) is SettingItem settingItem) + { + settingItem.Group = this; + Items.Add(settingItem); + } + } + } + } + [Serializable] + [DataContract] + public abstract class SettingItemList : SettingItem + { + private static readonly ListEqualityComparer ?? = new ListEqualityComparer(EqualityComparer.Default); + + [DataMember(Name = "Items")] + protected virtual List Items + { + get + { + return Value as List; + } + set + { + Value = value; + } + } + + protected SettingItemList(string name, IList items, int sortIndex = 0) + : base(name, items, sortIndex) + { + if (items == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public SettingItemList() + { + } + + protected SettingItemList(SettingItemList settingItem) + : base(settingItem) + { + Items = settingItem.CopyItems() as List; + } + + protected override bool IsValueTypeValid(object value) + { + return value is IList; + } + + protected IList CopyItems() + { + List list = new List(); + if (Value is IList list2) + { + foreach (SettingItem item in list2) + { + list.Add(item.GetCopy()); + } + } + return list; + } + + protected override bool ValueEquals(object other) + { + return ??.Equals(Items, other as IList); + } + } + [Serializable] + [DataContract] + public class SettingItemSymbolsList : SettingItemList + { + public override SettingItemType Type => SettingItemType.SymbolsList; + + [DataMember(Name = "Items")] + protected override List Items + { + get + { + List list = new List(); + foreach (SettingItemSymbol item in Value as List) + { + if (item.Value is Symbol) + { + list.Add(item); + } + } + return list; + } + set + { + Value = ?(value); + } + } + + public SettingItemSymbolsList(string name, IList items, int sortIndex = 0) + : base(name, new List(), sortIndex) + { + Value = ?(items); + } + + public SettingItemSymbolsList() + { + } + + protected SettingItemSymbolsList(SettingItemSymbolsList settingItem) + : base(settingItem) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemSymbolsList(this); + } + + private new IList ?(IList P_0) + { + List list = new List(); + foreach (SettingItem item in P_0) + { + if (item.Value is Symbol) + { + list.Add(item); + } + } + return list; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (SettingItem item in Items) + { + xElement.Add(item.ToXElement()); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + foreach (XElement item in xElement.Elements()) + { + SettingItemSymbol settingItemSymbol = new SettingItemSymbol(); + settingItemSymbol.FromXElement(item, deserializationInfo); + list.Add(settingItemSymbol); + } + } + Items = list; + } + } + /// + /// Typecasts setting as GroupBox item + /// + [Published] + public sealed class SettingItemSeparatorGroup : SettingItemVisualGroup + { + private string ??; + + public string Key + { + get + { + if (string.IsNullOrEmpty(??)) + { + return base.Text; + } + return ??; + } + set + { + ?? = value; + } + } + + public SettingItemSeparatorGroup(string text = "", int sortIndex = 0) + : base(text, sortIndex) + { + } + } + public class SettingItemVisualGroup : ISettingsGroup, ISettingsGroupCollapseBehaviour + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private ISettingsGroup ??; + + [CompilerGenerated] + private GroupActionInfo ??; + + [CompilerGenerated] + private GroupActionInfo ??; + + [CompilerGenerated] + private IList ??; + + [CompilerGenerated] + private SettingsGroupCollapseBehaviour ??; + + public string Text + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public ISettingsGroup ParentGroup + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = settingsGroup; + } + } + + public GroupActionInfo FirstActionInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GroupActionInfo SecondActionInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList ChildGroups + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = list; + } + } + + public SettingsGroupCollapseBehaviour CollapseBehaviour + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemVisualGroup(string text, int sortIndex = 0, ISettingsGroup parentGroup = null) + { + Text = text; + SortIndex = sortIndex; + ParentGroup = parentGroup; + ChildGroups = new List(); + if (ParentGroup != null) + { + ParentGroup.ChildGroups.Add(this); + } + } + + public override bool Equals(object obj) + { + return GetHashCode() == obj.GetHashCode(); + } + + public override int GetHashCode() + { + return ?(this); + } + + public override string ToString() + { + return Text; + } + + internal static int ?(ISettingsGroup P_0) + { + int num = 17; + num = num * 23 + P_0.Text.GetHashCode(); + num = num * 23 + P_0.SortIndex.GetHashCode(); + foreach (ISettingsGroup childGroup in P_0.ChildGroups) + { + num = num * 23 + childGroup.GetHashCode(); + } + return num; + } + } + [Serializable] + [DataContract] + public class OAuthResult : IXElementSerialization, ICloneable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + public string AccessToken + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal string RefreshToken + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal string IdentityToken + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal LoginResult RequestTokenResult + { + set + { + AccessToken = loginResult.AccessToken; + RefreshToken = loginResult.RefreshToken; + IdentityToken = loginResult.IdentityToken; + } + } + + internal RefreshTokenResult RequestRefreshResult + { + set + { + AccessToken = refreshTokenResult.AccessToken; + RefreshToken = refreshTokenResult.RefreshToken; + IdentityToken = refreshTokenResult.IdentityToken; + } + } + + internal TokenResponse TokenResponce + { + set + { + AccessToken = tokenResponse.AccessToken; + RefreshToken = tokenResponse.RefreshToken; + IdentityToken = tokenResponse.IdentityToken; + } + } + + public bool UseSavedTokens + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "EncryptedRefreshToken")] + private string EncryptedRefreshToken + { + get + { + if (!UseSavedTokens) + { + return string.Empty; + } + return Encryptor.?(RefreshToken); + } + set + { + RefreshToken = Encryptor.?(text); + } + } + + public OAuthResult() + { + AccessToken = string.Empty; + UseSavedTokens = true; + } + + public OAuthResult(string accessToken) + { + AccessToken = accessToken; + UseSavedTokens = true; + } + + internal OAuthResult(string P_0, string P_1) + { + AccessToken = P_0; + RefreshToken = P_1; + UseSavedTokens = true; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), EncryptedRefreshToken)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), UseSavedTokens)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + EncryptedRefreshToken = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + UseSavedTokens = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + } + + public object Clone() + { + return new OAuthResult + { + UseSavedTokens = UseSavedTokens, + AccessToken = AccessToken, + RefreshToken = RefreshToken, + IdentityToken = IdentityToken + }; + } + } + [DataContract] + public class SettingItemOAuth : SettingItem + { + [CompilerGenerated] + private readonly OidcClientOptions ??; + + [CompilerGenerated] + private readonly UpdateAuthorityUrlDelegate ??; + + [CompilerGenerated] + private readonly bool ??; + + [CompilerGenerated] + private readonly Parameters ??; + + public override SettingItemType Type => SettingItemType.OAuth; + + [DataMember(Name = "Value")] + private OAuthResult OAuthResultHolder + { + get + { + return (OAuthResult)Value; + } + set + { + Value = oAuthResult; + } + } + + public OidcClientOptions OidcOptions + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal UpdateAuthorityUrlDelegate UpdateIdentityAuthorityUrl + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal bool AllowOpenNewWindow + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal Parameters BackChannelExtraParameters + { + [CompilerGenerated] + get + { + return ??; + } + } + + public SettingItemOAuth() + { + } + + public SettingItemOAuth(string name, OAuthResult passwordHolder, OidcClientOptions oidcClientOptions, int sortIndex = 0, UpdateAuthorityUrlDelegate updateIdentityAuthorityUrl = null, bool allowOpenNewWindow = false, Parameters backChannelExtraParameters = null) + : base(name, passwordHolder, sortIndex) + { + ?? = oidcClientOptions; + ?? = updateIdentityAuthorityUrl; + ?? = allowOpenNewWindow; + ?? = backChannelExtraParameters; + } + + protected SettingItemOAuth(SettingItemOAuth settingItem) + : base(settingItem) + { + ?? = settingItem.OidcOptions; + ?? = settingItem.UpdateIdentityAuthorityUrl; + ?? = settingItem.AllowOpenNewWindow; + ?? = settingItem.BackChannelExtraParameters; + } + + public override SettingItem GetCopy() + { + return new SettingItemOAuth(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is OAuthResult; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + OAuthResult oAuthResult = new OAuthResult(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + oAuthResult.FromXElement(xElement, deserializationInfo); + OAuthResultHolder = oAuthResult; + } + } + } + public delegate string UpdateAuthorityUrlDelegate(IEnumerable settings, CancellationToken token); + public class SettingItemMultipleRelation : SettingItemRelation + { + [Serializable] + [CompilerGenerated] + private new sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func>>> ??; + + public static Func>, string> ??; + + public static Func>, IEnumerable> ??; + + internal IEnumerable>> ?(SettingItemRelation P_0) + { + return P_0.??; + } + + internal string ?(KeyValuePair> P_0) + { + return P_0.Key; + } + + internal IEnumerable ?(KeyValuePair> P_0) + { + return P_0.Value; + } + } + + private readonly List ??; + + public SettingItemMultipleRelation(params SettingItemRelation[] relations) + : base(relations.SelectMany((SettingItemRelation P_0) => P_0.??).ToDictionary((KeyValuePair> P_0) => P_0.Key, (KeyValuePair> P_0) => P_0.Value)) + { + ?? = relations.ToList(); + } + + public void AddRelation(SettingItemRelation relation) + { + foreach (KeyValuePair> item in relation.??) + { + ??.Add(item.Key, item.Value); + } + ??.Add(relation); + } + + public void InsertRelation(int index, SettingItemRelation relation) + { + foreach (KeyValuePair> item in relation.??) + { + ??.Add(item.Key, item.Value); + } + ??.Insert(0, relation); + } + + public override bool CheckRelation(SettingItem dependentItem, SettingItem changedItem, bool isPopulating, params SettingItem[] parentItems) + { + bool flag = false; + foreach (SettingItemRelation item in ??) + { + flag = ((base.MultipleRelationCondition != MultipleRelationCondition.IfAll) ? (flag | item.CheckRelation(dependentItem, changedItem, isPopulating, parentItems)) : (flag & item.CheckRelation(dependentItem, changedItem, isPopulating, parentItems))); + } + return flag; + } + } + public class SettingItemRelation + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func>, bool> ??; + + internal bool ?(KeyValuePair> P_0) + { + ? ? = new ? + { + ?? = P_0.Key + }; + IEnumerable value = P_0.Value; + if (!?.??.Visible) + { + return false; + } + return value.Any(?.?); + } + } + + [CompilerGenerated] + private sealed class ? + { + public SettingItem ??; + + internal bool ?(object P_0) + { + if (P_0 != null) + { + return SettingItemRelation.?(P_0, ??.Value); + } + return false; + } + } + + [CompilerGenerated] + private MultipleRelationCondition ??; + + internal readonly IDictionary> ??; + + protected SettingItemRelationDelegate RelationDelegate; + + public string[] ParentSettingsNames => ??.Keys.ToArray(); + + public MultipleRelationCondition MultipleRelationCondition + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemRelation(IDictionary> relationValuesByParentItemName, SettingItemRelationDelegate relationDelegate = null) + { + if (relationValuesByParentItemName.Keys.Count == 0) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + RelationDelegate = relationDelegate; + ?? = relationValuesByParentItemName; + MultipleRelationCondition = MultipleRelationCondition.IfAny; + } + + public virtual bool CheckRelation(SettingItem dependentItem, SettingItem changedItem, bool isPopulating, params SettingItem[] parentItems) + { + if (dependentItem == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (parentItems.Length == 0) + { + throw new AggregateException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SettingItemRelationParameters settingItemRelationParameters = new SettingItemRelationParameters + { + DependentItem = dependentItem, + ChangedItem = changedItem, + RelationValuesByParentItem = new Dictionary>(), + MultipleRelationCondition = MultipleRelationCondition, + IsPopulating = isPopulating + }; + foreach (SettingItem settingItem in parentItems) + { + if (??.TryGetValue(settingItem.Name, out var value) && !settingItemRelationParameters.RelationValuesByParentItem.ContainsKey(settingItem)) + { + settingItemRelationParameters.RelationValuesByParentItem.Add(settingItem, value); + } + } + return RelationDelegate(settingItemRelationParameters); + } + + protected static bool CheckEnabilityRelation(SettingItemRelationParameters relationParameters) + { + SettingItem dependentItem = relationParameters.DependentItem; + bool flag = CheckValues(relationParameters.RelationValuesByParentItem, relationParameters.MultipleRelationCondition); + bool result = dependentItem.Enabled != flag; + dependentItem.Enabled = flag; + return result; + } + + protected static bool CheckVisibilityRelation(SettingItemRelationParameters relationParameters) + { + SettingItem dependentItem = relationParameters.DependentItem; + bool flag = CheckValues(relationParameters.RelationValuesByParentItem, relationParameters.MultipleRelationCondition); + bool result = dependentItem.Visible != flag; + dependentItem.Visible = flag; + return result; + } + + protected static bool CheckValues(IDictionary> relationValuesByParentItem, MultipleRelationCondition condition) + { + Func>, bool> predicate = delegate(KeyValuePair> P_0) + { + ? ? = new ?(); + ?.?? = P_0.Key; + IEnumerable value = P_0.Value; + return ?.??.Visible && value.Any(?.?); + }; + if (condition == MultipleRelationCondition.IfAny) + { + return relationValuesByParentItem.Any(predicate); + } + return relationValuesByParentItem.All(predicate); + } + + [CompilerGenerated] + internal static bool ?(object P_0, object P_1) + { + if (P_0.Equals(P_1) || P_0 == P_1) + { + return true; + } + if (P_1 is SelectItem selectItem) + { + return ?(P_0, selectItem.Value); + } + return false; + } + } + public delegate bool SettingItemRelationDelegate(SettingItemRelationParameters relationParameters); + public class SettingItemRelationAction : SettingItemRelation + { + [Serializable] + [CompilerGenerated] + private new sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, string> ??; + + public static Func, IEnumerable> ??; + + internal string ?(KeyValuePair P_0) + { + return P_0.Key; + } + + internal IEnumerable ?(KeyValuePair P_0) + { + return Enumerable.Empty(); + } + } + + private readonly IDictionary ??; + + public SettingItemRelationAction(IDictionary callbacks) + : base(callbacks.ToDictionary((KeyValuePair P_0) => P_0.Key, (KeyValuePair P_0) => Enumerable.Empty())) + { + ?? = callbacks; + RelationDelegate = ?; + } + + private bool ?(SettingItemRelationParameters P_0) + { + if (!??.TryGetValue(P_0.ChangedItem.Name, out var value)) + { + return false; + } + try + { + return value(P_0.ChangedItem, P_0.DependentItem); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return false; + } + } + public delegate bool SettingItemRelationCallback(SettingItem changedItem, SettingItem dependentItem); + public class SettingItemRelationEnability : SettingItemRelation + { + [CompilerGenerated] + private new static class ? + { + public static SettingItemRelationDelegate ??; + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal string ?(string P_0) + { + return P_0; + } + } + + [CompilerGenerated] + private sealed class ? + { + public object ??; + + internal IEnumerable ?(string P_0) + { + return new List { ?? }; + } + } + + public SettingItemRelationEnability(string parentSettingsName, params object[] relationValues) + : base(new Dictionary> { + { + parentSettingsName, + new List(relationValues) + } }, SettingItemRelation.CheckEnabilityRelation) + { + } + + public SettingItemRelationEnability(string[] parentSettingsNames, object relationValue) + : base(((IEnumerable)parentSettingsNames).ToDictionary((Func)((string P_0) => P_0), (Func>)((string P_0) => new List { relationValue })), SettingItemRelation.CheckEnabilityRelation) + { + } + + public SettingItemRelationEnability(IDictionary> relationValuesByParentItemName) + : base(relationValuesByParentItemName, SettingItemRelation.CheckEnabilityRelation) + { + } + } + public class SettingItemRelationParameters + { + [CompilerGenerated] + private SettingItem ??; + + [CompilerGenerated] + private SettingItem ??; + + [CompilerGenerated] + private IDictionary> ??; + + [CompilerGenerated] + private MultipleRelationCondition ??; + + [CompilerGenerated] + private bool ??; + + public SettingItem DependentItem + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItem ChangedItem + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IDictionary> RelationValuesByParentItem + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MultipleRelationCondition MultipleRelationCondition + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool IsPopulating + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public class SettingItemRelationVisibility : SettingItemRelation + { + [CompilerGenerated] + private new static class ? + { + public static SettingItemRelationDelegate ??; + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal string ?(string P_0) + { + return P_0; + } + } + + [CompilerGenerated] + private sealed class ? + { + public object ??; + + internal IEnumerable ?(string P_0) + { + return new List { ?? }; + } + } + + public SettingItemRelationVisibility(string parentSettingsName, params object[] relationValues) + : base(new Dictionary> { + { + parentSettingsName, + new List(relationValues) + } }, SettingItemRelation.CheckVisibilityRelation) + { + } + + public SettingItemRelationVisibility(string[] parentSettingsNames, object relationValue) + : base(((IEnumerable)parentSettingsNames).ToDictionary((Func)((string P_0) => P_0), (Func>)((string P_0) => new List { relationValue })), SettingItemRelation.CheckVisibilityRelation) + { + } + + public SettingItemRelationVisibility(IDictionary> relationValuesByParentItemName) + : base(relationValuesByParentItemName, SettingItemRelation.CheckVisibilityRelation) + { + } + } + [Serializable] + [DataContract] + [KnownType(typeof(SettingItemAccount))] + [KnownType(typeof(SettingItemBoolean))] + [KnownType(typeof(SettingItemBooleanSwitcher))] + [KnownType(typeof(SettingItemDateTime))] + [KnownType(typeof(SettingItemSymbol))] + [KnownType(typeof(SettingItemPassword))] + [KnownType(typeof(SettingItemPeriod))] + [KnownType(typeof(SettingItemSelector))] + [KnownType(typeof(SettingItemSelectorLocalized))] + [KnownType(typeof(SettingItemString))] + [KnownType(typeof(SettingItemFile))] + [KnownType(typeof(SettingItemGroup))] + [KnownType(typeof(SettingItemRadioLocalized))] + [KnownType(typeof(SettingItemAction))] + [KnownType(typeof(SettingItemFont))] + [KnownType(typeof(SettingItemTimeZone))] + [KnownType(typeof(SettingItemRss))] + [KnownType(typeof(SettingItemAlignment))] + [KnownType(typeof(SettingItemPairColor))] + [KnownType(typeof(SettingItemColor))] + [KnownType(typeof(SettingItemSound))] + [KnownType(typeof(SettingItemLineOptions))] + [KnownType(typeof(SettingItemTimeZoneManager))] + [KnownType(typeof(SettingItemAlert))] + [KnownType(typeof(SettingItemFibonacciLevelOptions))] + [KnownType(typeof(SettingItemMinotauroFibonacciLevelOptions))] + [KnownType(typeof(SettingItemRangeSelector))] + [KnownType(typeof(SettingitemPoints))] + [KnownType(typeof(SettingItemTimeFrameConfig))] + [KnownType(typeof(SettingItemBooleanLocalized))] + [KnownType(typeof(SettingItemNumber))] + [KnownType(typeof(SettingItemNumber))] + [KnownType(typeof(SettingItemNumber))] + [KnownType(typeof(SettingItemClusterColoringLevel))] + [KnownType(typeof(SettingItemOrderRequestParameters))] + [KnownType(typeof(SettingItemIconedAction))] + [KnownType(typeof(SettingItemSlider))] + [KnownType(typeof(SettingItemDoubleWithLink))] + [KnownType(typeof(SettingItemCondition))] + [ProtoContract] + [ProtoInclude(2, typeof(SettingItemAccount))] + [ProtoInclude(3, typeof(SettingItemBoolean))] + [ProtoInclude(4, typeof(SettingItemBooleanSwitcher))] + [ProtoInclude(5, typeof(SettingItemDateTime))] + [ProtoInclude(6, typeof(SettingItemNumber))] + [ProtoInclude(7, typeof(SettingItemSymbol))] + [ProtoInclude(8, typeof(SettingItemNumber))] + [ProtoInclude(9, typeof(SettingItemPassword))] + [ProtoInclude(10, typeof(SettingItemPeriod))] + [ProtoInclude(11, typeof(SettingItemSelector))] + [ProtoInclude(12, typeof(SettingItemSelectorLocalized))] + [ProtoInclude(13, typeof(SettingItemString))] + [ProtoInclude(14, typeof(SettingItemFile))] + [ProtoInclude(15, typeof(SettingItemGroup))] + [ProtoInclude(16, typeof(SettingItemRadioLocalized))] + [ProtoInclude(17, typeof(SettingItemAction))] + [ProtoInclude(18, typeof(SettingItemFont))] + [ProtoInclude(19, typeof(SettingItemTimeZone))] + [ProtoInclude(20, typeof(SettingItemRss))] + [ProtoInclude(21, typeof(SettingItemAlignment))] + [ProtoInclude(22, typeof(SettingItemPairColor))] + [ProtoInclude(23, typeof(SettingItemColor))] + [ProtoInclude(24, typeof(SettingItemSound))] + [ProtoInclude(25, typeof(SettingItemLineOptions))] + [ProtoInclude(26, typeof(SettingItemTimeZoneManager))] + [ProtoInclude(27, typeof(SettingItemAlert))] + [ProtoInclude(28, typeof(SettingItemFibonacciLevelOptions))] + [ProtoInclude(29, typeof(SettingItemRangeSelector))] + [ProtoInclude(30, typeof(SettingitemPoints))] + [ProtoInclude(31, typeof(SettingItemTimeFrameConfig))] + [ProtoInclude(32, typeof(SettingItemBooleanLocalized))] + [ProtoInclude(33, typeof(SettingItemClusterColoringLevel))] + [ProtoInclude(34, typeof(SettingItemArbitageSymbols))] + [ProtoInclude(36, typeof(SettingItemOrderRequestParameters))] + [ProtoInclude(38, typeof(SettingItemIconedAction))] + [ProtoInclude(39, typeof(SettingItemSlider))] + [ProtoInclude(40, typeof(SettingItemDoubleWithLink))] + [ProtoInclude(41, typeof(SettingItemNumber))] + [ProtoInclude(42, typeof(SettingItemCondition))] + public abstract class SettingItem : BindableEntity, IComparable, IEquatable, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + private string ??; + + protected object value; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private VisibilityMode ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private SettingItemGroup ??; + + [CompilerGenerated] + private SettingItemSeparatorGroup ??; + + [CompilerGenerated] + private ISettingsGroup ??; + + private bool ??; + + [CompilerGenerated] + private SettingItemValueChangingBehavior ??; + + [CompilerGenerated] + private SettingItemValueChangingReason ??; + + private bool ??; + + [CompilerGenerated] + private SettingItemEventHandler ??; + + [CompilerGenerated] + private SettingItemRelation ??; + + [CompilerGenerated] + private bool ??; + + public abstract SettingItemType Type { get; } + + [DataMember(Name = "Name")] + [ProtoMember(1)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [Bindable("text")] + public virtual string Text + { + get + { + if (string.IsNullOrEmpty(??)) + { + return Name; + } + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [Bindable("value")] + public virtual object Value + { + get + { + return value; + } + set + { + if (this.value == value) + { + return; + } + if (value == null) + { + SetValue(ref this.value, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return; + } + if (IsValueTypeValid(value)) + { + SetValue(ref this.value, ValidateValue(value), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return; + } + throw new InvalidCastException(); + } + } + + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VisibilityMode VisibilityMode + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemGroup Group + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemSeparatorGroup SeparatorGroup + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ISettingsGroup VisualGroup + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [Bindable("enabled")] + public bool Enabled + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public SettingItemValueChangingBehavior ValueChangingBehavior + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemValueChangingReason ValueChangingReason + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [Bindable("visible")] + public bool Visible + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public bool IsVisualizationAllowed + { + get + { + if (VisibilityMode == VisibilityMode.Hidden) + { + return false; + } + if (Group != null) + { + return Group.IsVisualizationAllowed; + } + return true; + } + } + + public SettingItemRelation Relation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool UseEnabilityToggler + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public event SettingItemEventHandler Updated + { + [CompilerGenerated] + add + { + SettingItemEventHandler settingItemEventHandler = ??; + SettingItemEventHandler settingItemEventHandler2; + do + { + settingItemEventHandler2 = settingItemEventHandler; + SettingItemEventHandler settingItemEventHandler3 = (SettingItemEventHandler)Delegate.Combine(settingItemEventHandler2, value); + settingItemEventHandler = Interlocked.CompareExchange(ref ??, settingItemEventHandler3, settingItemEventHandler2); + } + while ((object)settingItemEventHandler != settingItemEventHandler2); + } + [CompilerGenerated] + remove + { + SettingItemEventHandler settingItemEventHandler = ??; + SettingItemEventHandler settingItemEventHandler2; + do + { + settingItemEventHandler2 = settingItemEventHandler; + SettingItemEventHandler settingItemEventHandler3 = (SettingItemEventHandler)Delegate.Remove(settingItemEventHandler2, value); + settingItemEventHandler = Interlocked.CompareExchange(ref ??, settingItemEventHandler3, settingItemEventHandler2); + } + while ((object)settingItemEventHandler != settingItemEventHandler2); + } + } + + public static IXElementSerialization DesserrializationFabric(XElement node) + { + string text = node?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value; + if (text != null) + { + switch (text.Length) + { + case 18: + switch (text[11]) + { + case 'A': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemAccount(); + case 'B': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemBoolean(); + case 'I': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemInteger(); + } + break; + case 26: + switch (text[15]) + { + case 'e': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemBooleanSwitcher(); + case 'Z': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemTimeZoneManager(); + case 'F': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemTimeFrameConfig(); + } + break; + case 19: + switch (text[13]) + { + case 't': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemDateTime(); + case 's': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemPassword(); + case 'l': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemSelector(); + case 'm': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemTimeZone(); + case 'x': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemTextArea(); + } + break; + case 17: + switch (text[16]) + { + case 'l': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemSymbol(); + case 'd': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemPeriod(); + case 'g': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemString(); + case 'n': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemAction(); + case 's': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingitemPoints(); + case 'e': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemDouble(); + case 'r': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemSlider(); + } + break; + case 15: + switch (text[14]) + { + case 'e': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemFile(); + case 't': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemFont(); + case 'g': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemLong(); + } + break; + case 16: + switch (text[11]) + { + case 'G': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemGroup(); + case 'C': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemColor(); + case 'S': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemSound(); + case 'A': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemAlert(); + case 'O': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemOAuth(); + } + break; + case 25: + switch (text[11]) + { + case 'R': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemRadioLocalized(); + case 'D': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemDoubleWithLink(); + } + break; + case 20: + switch (text[11]) + { + case 'A': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemAlignment(); + case 'P': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemPairColor(); + case 'C': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemCondition(); + } + break; + case 22: + switch (text[11]) + { + case 'L': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemLineOptions(); + case 'B': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemBigTextArea(); + } + break; + case 28: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemSelectorLocalized(); + case 14: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemRss(); + case 32: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemFibonacciLevelOptions(); + case 41: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemMinotauroFibonacciLevelOptions(); + case 24: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemRangeSelector(); + case 27: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemBooleanLocalized(); + case 31: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemClusterColoringLevel(); + case 33: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemOrderRequestParameters(); + case 23: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new SettingItemIconedAction(); + } + } + return null; + } + + public void Update() + { + ???.Invoke(this, SettingItemEventArgs.Empty); + } + + protected SettingItem(string name, object value, int sortIndex = 0) + : this() + { + Name = name; + this.value = value; + SortIndex = sortIndex; + VisibilityMode = VisibilityMode.Visible; + ValueChangingBehavior = SettingItemValueChangingBehavior.Default; + Enabled = true; + Visible = true; + } + + protected SettingItem() + { + ValueChangingReason = SettingItemValueChangingReason.Unknown; + } + + protected SettingItem(SettingItem settingItem) + : this() + { + Name = settingItem.Name; + SortIndex = settingItem.SortIndex; + Text = settingItem.Text; + Description = settingItem.Description; + Enabled = settingItem.Enabled; + Group = settingItem.Group; + Relation = settingItem.Relation; + SeparatorGroup = settingItem.SeparatorGroup; + VisibilityMode = settingItem.VisibilityMode; + Visible = settingItem.Visible; + VisualGroup = settingItem.VisualGroup; + if (settingItem.value is ICloneable cloneable) + { + value = cloneable.Clone(); + } + else + { + value = settingItem.Value; + } + ValueChangingBehavior = settingItem.ValueChangingBehavior; + UseEnabilityToggler = settingItem.UseEnabilityToggler; + } + + public abstract SettingItem GetCopy(); + + protected abstract bool IsValueTypeValid(object value); + + protected virtual object ValidateValue(object value) + { + return value; + } + + internal bool ?(IList P_0) + { + if (P_0 == null) + { + return false; + } + SettingItem itemByName = P_0.GetItemByName(Name); + if (itemByName != null) + { + Value = itemByName.Value; + return true; + } + return false; + } + + internal virtual void ?(object P_0, bool P_1 = false) + { + if (P_1) + { + SetValue(ref value, P_0, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + else + { + Value = P_0; + } + } + + internal virtual void ?(SettingItem P_0) + { + ?(P_0.Value); + VisibilityMode = P_0.VisibilityMode; + SortIndex = P_0.SortIndex; + } + + public int CompareTo(SettingItem other) + { + return SortIndex.CompareTo(other.SortIndex); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Value); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public virtual XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + if (UseEnabilityToggler) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Enabled)); + } + xElement.Add(ValueToXElement()); + return xElement; + } + + protected virtual XElement ValueToXElement() + { + if (Value is IXElementSerialization iXElementSerialization) + { + return iXElementSerialization.ToXElement(); + } + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Value); + } + + public virtual void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Name = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + UseEnabilityToggler = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) != null; + Enabled = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToBool() ?? false; + ValueFromXElement(element, deserializationInfo); + } + + protected virtual void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Value = xElement.Value; + } + } + + public virtual bool Equals(SettingItem other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Text == other.Text && ValueEquals(other.Value) && Enabled == other.Enabled && Visible == other.Visible && Type == other.Type && Name == other.Name && SortIndex == other.SortIndex && VisibilityMode == other.VisibilityMode && Description == other.Description && object.Equals(SeparatorGroup, other.SeparatorGroup) && object.Equals(VisualGroup, other.VisualGroup) && ValueChangingReason == other.ValueChangingReason && ValueChangingBehavior == other.ValueChangingBehavior) + { + return UseEnabilityToggler == other.UseEnabilityToggler; + } + return false; + } + + protected virtual bool ValueEquals(object other) + { + return object.Equals(Value, other); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((SettingItem)obj); + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(Text); + hashCode.Add(Value); + hashCode.Add(Enabled); + hashCode.Add(Visible); + hashCode.Add((int)Type); + hashCode.Add(Name); + hashCode.Add(SortIndex); + hashCode.Add((int)VisibilityMode); + hashCode.Add(Description); + hashCode.Add(SeparatorGroup); + hashCode.Add(VisualGroup); + hashCode.Add(ValueChangingReason); + hashCode.Add((int)ValueChangingBehavior); + hashCode.Add(UseEnabilityToggler); + return hashCode.ToHashCode(); + } + } + /// + /// Typecasts setting as AccountLookup item + /// + [Serializable] + [DataContract] + public sealed class SettingItemAccount : SettingItem + { + public override SettingItemType Type => SettingItemType.Account; + + [DataMember(Name = "Value")] + private BusinessObjectInfo ValueInfo + { + get + { + return (Value as Account)?.CreateInfo() ?? BusinessObjectInfo.Empty; + } + set + { + Value = Core.Instance.GetAccount(accountInfo); + } + } + + public SettingItemAccount() + { + } + + public SettingItemAccount(string name, Account value = null, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemAccount(SettingItemAccount P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemAccount(this); + } + + public static implicit operator Account(SettingItemAccount item) + { + return item.Value as Account; + } + + protected override bool IsValueTypeValid(object value) + { + return value is Account; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ? ? = new ?(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ?.FromXElement(xElement, deserializationInfo); + if (!string.IsNullOrEmpty(?.Id)) + { + ValueInfo = ?; + } + } + } + + protected override XElement ValueToXElement() + { + return ValueInfo.ToXElement(); + } + } + /// + /// Typecasts setting as Button item + /// + [Serializable] + [Published] + [DataContract] + public sealed class SettingItemAction : SettingItem + { + [CompilerGenerated] + private string ??; + + public override SettingItemType Type => SettingItemType.Action; + + public string LabelText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemAction() + { + } + + public SettingItemAction(string name, SettingItemActionDelegate value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + public SettingItemAction(SettingItemAction settingItem) + : base(settingItem) + { + LabelText = settingItem.LabelText; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemAction(this); + } + + [NotPublished] + public static implicit operator SettingItemActionDelegate(SettingItemAction item) + { + return item.Value as SettingItemActionDelegate; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is SettingItemActionDelegate; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + } + } + public delegate object SettingItemActionDelegate(object args = null); + [Serializable] + [DataContract] + public class SettingItemAlert : SettingItem + { + public override SettingItemType Type => SettingItemType.ConditionSet; + + [DataMember(Name = "Value")] + private AlertData ValueAlert + { + get + { + return Value as AlertData; + } + set + { + Value = alertData; + } + } + + public SettingItemAlert() + { + } + + public SettingItemAlert(string name, object value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemAlert(SettingItemAlert P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemAlert(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is AlertData; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + AlertData alertData = new AlertData(); + alertData.FromXElement(element, deserializationInfo); + value = alertData; + } + } + [Serializable] + [DataContract] + public class SettingItemAlignment : SettingItem + { + public override SettingItemType Type => SettingItemType.Alignment; + + [DataMember(Name = "Value")] + private NativeAlignment ValueAlignment + { + get + { + return (NativeAlignment)Value; + } + set + { + Value = nativeAlignment; + } + } + + public SettingItemAlignment() + { + } + + public SettingItemAlignment(string name, NativeAlignment value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemAlignment(SettingItemAlignment P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemAlignment(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is NativeAlignment; + } + + protected override XElement ValueToXElement() + { + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)ValueAlignment); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueAlignment = (NativeAlignment)xElement.ToInt(); + } + } + } + [Serializable] + [DataContract] + public class SettingItemArbitageSymbols : SettingItem + { + [CompilerGenerated] + private ArbitrageSymbol ??; + + [CompilerGenerated] + private decimal ??; + + [CompilerGenerated] + private decimal ??; + + [CompilerGenerated] + private ArbitrageSymbol ??; + + [CompilerGenerated] + private ArbitrageSymbol ??; + + [CompilerGenerated] + private ArbitrageSymbol ??; + + [DataMember(Name = "Value")] + private List ArbitrageSymbols + { + get + { + return Value as List; + } + set + { + Value = list; + } + } + + public override SettingItemType Type => SettingItemType.ArbitageSymbols; + + public ArbitrageSymbol FirstArbitrageSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public decimal BaseMaxTradingQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public decimal QuotingMaxTradingQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ArbitrageSymbol AddedSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ArbitrageSymbol RemovedSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ArbitrageSymbol ModifiedSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemArbitageSymbols() + { + } + + public SettingItemArbitageSymbols(string name, List symbols, int sortIndex = 0) + : base(name, symbols, sortIndex) + { + BaseMaxTradingQuantity = 0m; + QuotingMaxTradingQuantity = 0m; + } + + private SettingItemArbitageSymbols(SettingItemArbitageSymbols P_0) + : base(P_0) + { + BaseMaxTradingQuantity = P_0.BaseMaxTradingQuantity; + QuotingMaxTradingQuantity = P_0.QuotingMaxTradingQuantity; + } + + public override SettingItem GetCopy() + { + return new SettingItemArbitageSymbols(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is List; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + BaseMaxTradingQuantity = xElement.ToDecimal(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + QuotingMaxTradingQuantity = xElement2.ToDecimal(); + } + base.FromXElement(element, deserializationInfo); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + IEnumerable enumerable = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements(); + if (enumerable != null) + { + foreach (XElement item in enumerable) + { + ArbitrageSymbol arbitrageSymbol = new ArbitrageSymbol(); + arbitrageSymbol.FromXElement(item, deserializationInfo); + list.Add(arbitrageSymbol); + } + } + Value = list; + base.ValueFromXElement(element, deserializationInfo); + } + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BaseMaxTradingQuantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuotingMaxTradingQuantity)); + return xElement; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (ArbitrageSymbol arbitrageSymbol in ArbitrageSymbols) + { + xElement.Add(arbitrageSymbol.ToXElement()); + } + return xElement; + } + } + /// + /// Typecasts setting as TextBox item + /// + [Serializable] + [DataContract] + [ProtoContract] + public sealed class SettingItemBigTextArea : SettingItem + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public override SettingItemType Type => SettingItemType.BigTextArea; + + public string HelpLink + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string HelpLinkTitle + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemBigTextArea() + { + } + + public SettingItemBigTextArea(string name, string value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemBigTextArea(SettingItemBigTextArea P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemBigTextArea(this); + } + + public static implicit operator string(SettingItemBigTextArea item) + { + return item.Value as string; + } + + protected override bool IsValueTypeValid(object value) + { + return value is string; + } + } + /// + /// Typecasts setting as CheckBox item + /// + [Serializable] + [Published] + [DataContract] + public sealed class SettingItemBoolean : SettingItem + { + public override SettingItemType Type => SettingItemType.Boolean; + + [DataMember(Name = "Value")] + [ProtoMember(1, IsRequired = true)] + private bool ValueBool + { + get + { + return (bool)value; + } + set + { + value = flag; + } + } + + public SettingItemBoolean() + { + } + + public SettingItemBoolean(string name, bool value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemBoolean(SettingItemBoolean P_0) + : base(P_0) + { + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemBoolean(this); + } + + [NotPublished] + public static implicit operator bool(SettingItemBoolean item) + { + return (bool)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is bool; + } + + [NotPublished] + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueBool = xElement.ToBool(); + } + } + } + [Serializable] + [DataContract] + public class SettingItemBooleanLocalized : SettingItemList + { + [Serializable] + [CompilerGenerated] + private new sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Predicate ??; + + internal bool ?(SettingItem P_0) + { + return P_0 is SettingItemBoolean; + } + } + + public override SettingItemType Type => SettingItemType.BooleanLocalized; + + public SettingItemBooleanLocalized() + { + } + + public SettingItemBooleanLocalized(string name, IList items, int sortIndex = 0) + : base(name, items, sortIndex) + { + } + + private SettingItemBooleanLocalized(SettingItemBooleanLocalized P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemBooleanLocalized(this); + } + + protected override bool IsValueTypeValid(object value) + { + if (value is List list) + { + return list.TrueForAll((SettingItem P_0) => P_0 is SettingItemBoolean); + } + return false; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + List items = Items; + for (int i = 0; i < items.Count; i++) + { + xElement.Add(items[i].ToXElement()); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (XElement item in xElement.Elements()) + { + SettingItemBoolean settingItemBoolean = new SettingItemBoolean(); + settingItemBoolean.FromXElement(item, deserializationInfo); + list.Add(settingItemBoolean); + } + Items = list; + } + } + /// + /// Typecasts setting as CheckBox item + /// + [Serializable] + [DataContract] + public sealed class SettingItemBooleanSwitcher : SettingItem + { + public override SettingItemType Type => SettingItemType.BooleanSwitcher; + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private bool ValueBool + { + get + { + return (bool)value; + } + set + { + value = flag; + } + } + + public SettingItemBooleanSwitcher() + { + } + + public SettingItemBooleanSwitcher(string name, bool value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemBooleanSwitcher(SettingItemBooleanSwitcher P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemBooleanSwitcher(this); + } + + public static implicit operator bool(SettingItemBooleanSwitcher item) + { + return (bool)item.Value; + } + + protected override bool IsValueTypeValid(object value) + { + return value is bool; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueBool = xElement.ToBool(); + } + } + } + [Serializable] + [DataContract] + public class SettingItemClusterColoringLevel : SettingItem + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private decimal ?? = 1m; + + [CompilerGenerated] + private decimal ?? = decimal.MinValue; + + [CompilerGenerated] + private decimal ?? = decimal.MaxValue; + + [CompilerGenerated] + private bool ?? = true; + + public int NumericPrecision + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public decimal Increment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public decimal Minimum + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public decimal Maximum + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithRightColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override SettingItemType Type => SettingItemType.ClusterColoringLevels; + + [DataMember(Name = "Value")] + private ClusterCustomColoringLevel Level + { + get + { + return Value as ClusterCustomColoringLevel; + } + set + { + Value = clusterCustomColoringLevel; + } + } + + public SettingItemClusterColoringLevel() + { + } + + public SettingItemClusterColoringLevel(string name, ClusterCustomColoringLevel level, int sortIndex = 0) + : base(name, level, sortIndex) + { + NumericPrecision = 0; + } + + public SettingItemClusterColoringLevel(SettingItemClusterColoringLevel settingItem) + : base(settingItem) + { + NumericPrecision = settingItem.NumericPrecision; + Increment = settingItem.Increment; + Minimum = settingItem.Minimum; + Maximum = settingItem.Maximum; + } + + public override SettingItem GetCopy() + { + return new SettingItemClusterColoringLevel(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is ClusterCustomColoringLevel; + } + + protected override XElement ValueToXElement() + { + return Level.ToXElement(); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ClusterCustomColoringLevel clusterCustomColoringLevel = new ClusterCustomColoringLevel(); + clusterCustomColoringLevel.FromXElement(element, deserializationInfo); + Value = clusterCustomColoringLevel; + } + } + /// + /// Typecasts setting as Color item + /// + [Serializable] + [Published] + [DataContract] + public sealed class SettingItemColor : SettingItem + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + public override SettingItemType Type => SettingItemType.Color; + + public string ColorText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool Checked + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithCheckBox + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AllowDisableColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + private Color ValueColor + { + get + { + return (Color)Value; + } + set + { + Value = color; + } + } + + public SettingItemColor() + { + } + + public SettingItemColor(string name, Color value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemColor(SettingItemColor P_0) + : base(P_0) + { + ColorText = P_0.ColorText; + Checked = P_0.Checked; + WithCheckBox = P_0.WithCheckBox; + AllowDisableColor = P_0.AllowDisableColor; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemColor(this); + } + + [NotPublished] + public static implicit operator Color(SettingItemColor item) + { + return (Color)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is Color; + } + + [NotPublished] + protected override XElement ValueToXElement() + { + return ValueColor.ToXElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + [NotPublished] + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueColor = xElement.ToColor(); + } + } + + [NotPublished] + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + WithCheckBox = xElement.ToBool(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Checked = xElement2.ToBool(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + AllowDisableColor = xElement3.ToBool(); + } + } + + [NotPublished] + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Checked)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), WithCheckBox)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowDisableColor)); + return xElement; + } + } + /// + /// Typecasts setting as DateTimePicker item + /// + [Serializable] + [DataContract] + public sealed class SettingItemDateTime : SettingItem + { + private const string ?? = "ddMMyyyy HH:mm:ss.ffffff"; + + [CompilerGenerated] + private bool ??; + + private DatePickerFormat ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + public override SettingItemType Type => SettingItemType.DateTime; + + public bool ApplyOnEachInput + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [Bindable("format")] + public DatePickerFormat Format + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public DateTime MinDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime MaxDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private DateTime ValueDateTime + { + get + { + return (DateTime)Value; + } + set + { + Value = dateTime; + } + } + + public SettingItemDateTime() + { + } + + public SettingItemDateTime(string name, DateTime value = default(DateTime), int sortIndex = 0) + : base(name, value, sortIndex) + { + Format = DatePickerFormat.DateTime; + ApplyOnEachInput = false; + MinDate = DateTime.MinValue; + MaxDate = DateTime.MaxValue; + } + + private SettingItemDateTime(SettingItemDateTime P_0) + : base(P_0) + { + Format = P_0.Format; + ApplyOnEachInput = P_0.ApplyOnEachInput; + MinDate = P_0.MinDate; + MaxDate = P_0.MaxDate; + } + + public override SettingItem GetCopy() + { + return new SettingItemDateTime(this); + } + + public static implicit operator DateTime(SettingItemDateTime item) + { + return (DateTime)item.Value; + } + + protected override bool IsValueTypeValid(object value) + { + return value is DateTime; + } + + protected override XElement ValueToXElement() + { + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ValueDateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture)); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement == null) + { + return; + } + if (deserializationInfo.Version < 1.3) + { + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null && xElement2.Value == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ValueDateTime = xElement.ToDateTime(toUTC: true); + } + else + { + ValueDateTime = xElement.ToDateTime(); + } + } + else + { + ValueDateTime = xElement.ToDateTime(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + } + /// + /// Typecasts setting as NumericUpDown item + /// + [Serializable] + [Published] + [DataContract] + [ProtoContract] + public class SettingItemDouble : SettingItemNumber + { + private int ??; + + public override SettingItemType Type => SettingItemType.Double; + + [Bindable("decimalPlaces")] + public int DecimalPlaces + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private double ValueDouble + { + get + { + return (double)value; + } + set + { + value = num; + } + } + + public SettingItemDouble() + { + } + + public SettingItemDouble(string name, double value, int sortIndex = 0) + : base(name, value, sortIndex) + { + base.Maximum = 2147483647.0; + base.Minimum = -2147483648.0; + DecimalPlaces = 0; + base.Increment = 1.0; + } + + private protected SettingItemDouble(SettingItemDouble P_0) + : base((SettingItemNumber)P_0) + { + DecimalPlaces = P_0.DecimalPlaces; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemDouble(this); + } + + [NotPublished] + public static implicit operator double(SettingItemDouble item) + { + return (double)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is double; + } + + [NotPublished] + protected override object ValidateValue(object value) + { + value = base.ValidateValue(value); + double num = (double)value; + if (double.IsNaN(num)) + { + num = 0.0; + } + else if (num > base.Maximum) + { + num = base.Maximum; + } + else if (num < base.Minimum) + { + num = base.Minimum; + } + else if (base.Increment != 0.0) + { + num -= (double)((decimal)num % (decimal)base.Increment); + } + return num; + } + + [NotPublished] + protected override XElement ValueToXElement() + { + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ValueDouble.ToString(CultureInfo.InvariantCulture)); + } + + [NotPublished] + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueDouble = xElement.ToDouble(); + } + } + + public override bool Equals(SettingItem other) + { + if (!base.Equals(other)) + { + return false; + } + if (!(other is SettingItemDouble settingItemDouble)) + { + return false; + } + return DecimalPlaces == settingItemDouble.DecimalPlaces; + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(base.GetHashCode()); + hashCode.Add(DecimalPlaces); + return hashCode.ToHashCode(); + } + } + public class SettingItemDoubleWithLink : SettingItemDouble + { + private string ??; + + [CompilerGenerated] + private Action ??; + + public override SettingItemType Type => SettingItemType.DoubleWithLink; + + [Bindable("linkText")] + public string LinkText + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public Action LinkAction + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemDoubleWithLink() + { + } + + public SettingItemDoubleWithLink(string name, double value, Action linkAction, int sortIndex = 0) + : base(name, value, sortIndex) + { + LinkAction = linkAction; + } + + private SettingItemDoubleWithLink(SettingItemDoubleWithLink P_0) + : base(P_0) + { + LinkText = P_0.LinkText; + LinkAction = P_0.LinkAction; + } + + public override SettingItem GetCopy() + { + return new SettingItemDoubleWithLink(this); + } + } + public class SettingItemFibonacciLevelOptions : SettingItem + { + [CompilerGenerated] + private Font ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private decimal ??; + + public override SettingItemType Type => SettingItemType.FibonacciLevelOptions; + + public Font DefaultFont + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int DecimalPlaces + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public decimal Increment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + private List ValuelevelOptions + { + get + { + return Value as List; + } + set + { + Value = list; + } + } + + public SettingItemFibonacciLevelOptions() + { + ?(); + } + + public SettingItemFibonacciLevelOptions(string name, List value, int sortIndex = 0) + : base(name, value, sortIndex) + { + ?(); + } + + protected SettingItemFibonacciLevelOptions(SettingItemFibonacciLevelOptions settingItem) + : base(settingItem) + { + ?(); + } + + private void ?() + { + DecimalPlaces = 2; + Increment = 0.01m; + } + + public override SettingItem GetCopy() + { + return new SettingItemFibonacciLevelOptions(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is List; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (FibonacciLevelOptions valuelevelOption in ValuelevelOptions) + { + xElement.Add(valuelevelOption.ToXElement()); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + foreach (XElement item in element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements()) + { + FibonacciLevelOptions fibonacciLevelOptions = CreateFibonaccilevel(); + fibonacciLevelOptions.FromXElement(item, deserializationInfo); + list.Add(fibonacciLevelOptions); + } + Value = list; + } + + protected virtual FibonacciLevelOptions CreateFibonaccilevel() + { + return new FibonacciLevelOptions(); + } + } + [Serializable] + [DataContract] + public class SettingItemFile : SettingItem + { + public string Filter; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + public override SettingItemType Type => SettingItemType.File; + + public bool Checked + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithCheckBox + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string DefaultFolder + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemFile() + { + } + + public SettingItemFile(string name, string value, string filter, int sortIndex = 0) + : base(name, value, sortIndex) + { + Filter = filter; + } + + private SettingItemFile(SettingItemFile P_0) + : base(P_0) + { + Filter = P_0.Filter; + } + + public override SettingItem GetCopy() + { + return new SettingItemFile(this); + } + + public static implicit operator string(SettingItemFile item) + { + return item.Value as string; + } + + protected override bool IsValueTypeValid(object value) + { + return value is string; + } + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Checked)); + return xElement; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + Checked = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToBool() ?? false; + } + } + [Serializable] + [DataContract] + [KnownType(typeof(FontStyle))] + [KnownType(typeof(GraphicsUnit))] + public sealed class SettingItemFont : SettingItem + { + public bool UseGeneral; + + public override SettingItemType Type => SettingItemType.Font; + + [DataMember(Name = "Value")] + private Font ValueFont + { + get + { + return Value as Font; + } + set + { + if (font != null) + { + Value = font; + } + } + } + + public SettingItemFont() + { + } + + public SettingItemFont(string name, Font value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemFont(SettingItemFont P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemFont(this); + } + + public static implicit operator Font(SettingItemFont item) + { + return item.Value as Font; + } + + protected override bool IsValueTypeValid(object value) + { + if (!(value is Font)) + { + return value == null; + } + return true; + } + + protected override XElement ValueToXElement() + { + return ValueFont.ToXElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueFont = xElement.ToFont(); + } + } + } + [Serializable] + [DataContract] + public sealed class SettingItemIconedAction : SettingItem + { + [CompilerGenerated] + private SettingItemIconedActionType ??; + + public override SettingItemType Type => SettingItemType.IconedAction; + + public SettingItemIconedActionType IconType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemIconedAction() + { + } + + public SettingItemIconedAction(string name, SettingItemActionDelegate value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemIconedAction(SettingItemIconedAction P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemIconedAction(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is SettingItemActionDelegate; + } + + public static implicit operator SettingItemActionDelegate(SettingItemIconedAction item) + { + return item.Value as SettingItemActionDelegate; + } + } + public enum SettingItemIconedActionType + { + Setting, + Trash + } + /// + /// Typecasts setting as NumericUpDown item + /// + [Serializable] + [Published] + [DataContract] + [ProtoContract] + public sealed class SettingItemInteger : SettingItemNumber + { + public override SettingItemType Type => SettingItemType.Integer; + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private int ValueInt + { + get + { + return (int)value; + } + set + { + value = num; + } + } + + public SettingItemInteger() + { + } + + public SettingItemInteger(string name, int value, int sortIndex = 0) + : base(name, value, sortIndex) + { + base.Maximum = int.MaxValue; + base.Minimum = int.MinValue; + base.Increment = 1; + } + + private SettingItemInteger(SettingItemInteger P_0) + : base((SettingItemNumber)P_0) + { + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemInteger(this); + } + + [NotPublished] + public static implicit operator int(SettingItemInteger item) + { + return (int)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is int; + } + + [NotPublished] + protected override object ValidateValue(object value) + { + value = base.ValidateValue(value); + int num = (int)value; + if (num > base.Maximum) + { + num = base.Maximum; + } + else if (num < base.Minimum) + { + num = base.Minimum; + } + else if (base.Increment != 0) + { + num -= num % base.Increment; + } + return num; + } + + [NotPublished] + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueInt = xElement.ToInt(); + } + } + } + public class SettingItemLabel : SettingItem + { + public override SettingItemType Type => SettingItemType.Label; + + [DataMember(Name = "Value")] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemLabel() + { + } + + public SettingItemLabel(string name, string value = null, int sortIndex = 0) + : base(name, value ?? string.Empty, sortIndex) + { + } + + private SettingItemLabel(SettingItemLabel P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemLabel(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is string; + } + } + [Serializable] + [DataContract] + public class SettingItemLineOptions : SettingItem + { + [CompilerGenerated] + private LineStyle[] ??; + + public override SettingItemType Type => SettingItemType.LineOptions; + + public LineStyle[] ExcludedStyles + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + private LineOptions ValueColor + { + get + { + return (LineOptions)Value; + } + set + { + Value = lineOptions; + } + } + + public SettingItemLineOptions() + { + } + + public SettingItemLineOptions(string name, LineOptions value, int sortIndex = 0) + : base(name, value?.Clone(), sortIndex) + { + } + + private SettingItemLineOptions(SettingItemLineOptions P_0) + : base(P_0) + { + if (P_0.Value is ICloneable cloneable) + { + value = cloneable.Clone() as LineOptions; + } + ExcludedStyles = P_0.ExcludedStyles; + } + + public override SettingItem GetCopy() + { + return new SettingItemLineOptions(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is LineOptions; + } + + protected override object ValidateValue(object value) + { + LineOptions lineOptions = (LineOptions)value; + LineStyle[] excludedStyles = ExcludedStyles; + if (excludedStyles != null && excludedStyles.Contains(lineOptions.LineStyle)) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return base.ValidateValue(value); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + LineOptions lineOptions = new LineOptions(); + XElement element2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + lineOptions.FromXElement(element2, deserializationInfo); + ValueColor = lineOptions; + } + } + [Serializable] + [Published] + [DataContract] + [ProtoContract] + public sealed class SettingItemLong : SettingItemNumber + { + public override SettingItemType Type => SettingItemType.Long; + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private long ValueLong + { + get + { + return (long)value; + } + set + { + value = num; + } + } + + public SettingItemLong() + { + } + + public SettingItemLong(string name, long value, int sortIndex = 0) + : base(name, value, sortIndex) + { + base.Maximum = long.MaxValue; + base.Minimum = long.MinValue; + base.Increment = 1L; + } + + private SettingItemLong(SettingItemLong P_0) + : base((SettingItemNumber)P_0) + { + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemLong(this); + } + + [NotPublished] + public static implicit operator long(SettingItemLong item) + { + return (long)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is long; + } + + [NotPublished] + protected override object ValidateValue(object value) + { + value = base.ValidateValue(value); + long num = (long)value; + if (num > base.Maximum) + { + num = base.Maximum; + } + else if (num < base.Minimum) + { + num = base.Minimum; + } + else if (base.Increment != 0L) + { + num -= num % base.Increment; + } + return num; + } + + [NotPublished] + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ValueLong = xElement.ToLong(); + } + } + } + public class SettingItemMinotauroFibonacciLevelOptions : SettingItemFibonacciLevelOptions + { + public override SettingItemType Type => SettingItemType.MinotauroFibonacciLevelOptions; + + protected override FibonacciLevelOptions CreateFibonaccilevel() + { + return new MinotauroFibonacciLevelOptions(); + } + + private SettingItemMinotauroFibonacciLevelOptions(SettingItemFibonacciLevelOptions P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemMinotauroFibonacciLevelOptions(this); + } + + public SettingItemMinotauroFibonacciLevelOptions() + { + } + + public SettingItemMinotauroFibonacciLevelOptions(string name, List value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + } + [Serializable] + [KnownType(typeof(SettingItemDouble))] + [KnownType(typeof(SettingItemInteger))] + [KnownType(typeof(SettingItemLong))] + [ProtoInclude(1, typeof(SettingItemDouble))] + [ProtoInclude(2, typeof(SettingItemInteger))] + [ProtoInclude(3, typeof(SettingItemLong))] + [DataContract] + [ProtoContract] + public abstract class SettingItemNumber : SettingItem where T : struct + { + private T ??; + + private T ??; + + private T ??; + + private string ??; + + [CompilerGenerated] + private bool ??; + + [Bindable("maximum")] + public T Maximum + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [Bindable("minimum")] + public T Minimum + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [Bindable("increment")] + public T Increment + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [Bindable("dimension")] + public string Dimension + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public bool UseTradingNumeric + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemNumber() + { + } + + public SettingItemNumber(string name, T value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + protected SettingItemNumber(SettingItemNumber settingItem) + : base(settingItem) + { + Maximum = settingItem.Maximum; + Minimum = settingItem.Minimum; + Increment = settingItem.Increment; + Dimension = settingItem.Dimension; + UseTradingNumeric = settingItem.UseTradingNumeric; + } + + public override bool Equals(SettingItem other) + { + if (!base.Equals(other)) + { + return false; + } + if (!(other is SettingItemNumber settingItemNumber)) + { + return false; + } + if (EqualityComparer.Default.Equals(Maximum, settingItemNumber.Maximum) && EqualityComparer.Default.Equals(Minimum, settingItemNumber.Minimum) && EqualityComparer.Default.Equals(Increment, settingItemNumber.Increment) && Dimension == settingItemNumber.Dimension) + { + return UseTradingNumeric == settingItemNumber.UseTradingNumeric; + } + return false; + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(base.GetHashCode()); + hashCode.Add(Maximum); + hashCode.Add(Minimum); + hashCode.Add(Increment); + hashCode.Add(Dimension); + hashCode.Add(UseTradingNumeric); + return hashCode.ToHashCode(); + } + } + /// + /// Typecasts setting as AccountLookup item + /// + [Serializable] + [DataContract] + public sealed class SettingItemObject : SettingItem + { + public override SettingItemType Type => SettingItemType.Object; + + public SettingItemObject() + { + } + + public SettingItemObject(string name, object value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemObject(SettingItemObject P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemObject(this); + } + + protected override bool IsValueTypeValid(object value) + { + return true; + } + } + [Serializable] + [DataContract] + public class SettingItemOrderRequestParameters : SettingItem + { + public override SettingItemType Type => SettingItemType.OrderRequestParameters; + + [DataMember(Name = "Value")] + private OrderRequestParameters ValueInfo + { + get + { + return Value as OrderRequestParameters; + } + set + { + Value = orderRequestParameters; + } + } + + public SettingItemOrderRequestParameters() + { + } + + public SettingItemOrderRequestParameters(string name, OrderRequestParameters value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemOrderRequestParameters(SettingItemOrderRequestParameters P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemOrderRequestParameters(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is OrderRequestParameters; + } + + protected override XElement ValueToXElement() + { + return ValueInfo.ToXElement(); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters(); + placeOrderRequestParameters.FromXElement(element, deserializationInfo); + value = placeOrderRequestParameters; + } + } + [Serializable] + [DataContract] + public sealed class SettingItemPairColor : SettingItem + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + public override SettingItemType Type => SettingItemType.PairColor; + + public bool Checked + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithCheckBox + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AllowDisableColor1 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AllowDisableColor2 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + private PairColor ValueColor + { + get + { + return (PairColor)Value; + } + set + { + Value = pairColor; + } + } + + public SettingItemPairColor() + { + } + + public SettingItemPairColor(string name, PairColor value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemPairColor(SettingItemPairColor P_0) + : base(P_0) + { + Checked = P_0.Checked; + WithCheckBox = P_0.WithCheckBox; + AllowDisableColor1 = P_0.AllowDisableColor1; + AllowDisableColor2 = P_0.AllowDisableColor2; + } + + public override SettingItem GetCopy() + { + return new SettingItemPairColor(this); + } + + public static implicit operator PairColor(SettingItemPairColor item) + { + return (PairColor)item.Value; + } + + protected override bool IsValueTypeValid(object value) + { + return value is PairColor; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + value = new PairColor(); + ValueColor.FromXElement(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), deserializationInfo); + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + WithCheckBox = xElement.ToBool(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Checked = xElement2.ToBool(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + AllowDisableColor1 = xElement3.ToBool(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + AllowDisableColor2 = xElement4.ToBool(); + } + } + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Checked)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), WithCheckBox)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowDisableColor1)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowDisableColor2)); + return xElement; + } + } + /// + /// Typecasts setting as Password item + /// + [Serializable] + [DataContract] + public sealed class SettingItemPassword : SettingItem + { + public override SettingItemType Type => SettingItemType.Password; + + [DataMember(Name = "Value")] + private PasswordHolder PasswordHolder + { + get + { + return (PasswordHolder)Value; + } + set + { + Value = passwordHolder; + } + } + + public SettingItemPassword() + { + } + + public SettingItemPassword(string name, PasswordHolder passwordHolder, int sortIndex = 0) + : base(name, passwordHolder, sortIndex) + { + } + + private SettingItemPassword(SettingItemPassword P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemPassword(this); + } + + public static implicit operator PasswordHolder(SettingItemPassword item) + { + return (PasswordHolder)item.Value; + } + + protected override bool IsValueTypeValid(object value) + { + return value is PasswordHolder; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + PasswordHolder passwordHolder = new PasswordHolder(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), SavePassword: true, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + passwordHolder.FromXElement(xElement, deserializationInfo); + PasswordHolder = passwordHolder; + } + } + + internal override void ?(object P_0, bool P_1 = false) + { + PasswordHolder passwordHolder = this; + base.?(P_0, P_1); + ((PasswordHolder)Value).RecoverUrl = passwordHolder.RecoverUrl; + } + } + [Serializable] + [DataContract] + public class PasswordHolder : IXElementSerialization, ICloneable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + public string Password + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Password")] + private string EncryptedPassword + { + get + { + if (!SavePassword) + { + return string.Empty; + } + return Encryptor.?(Password); + } + set + { + Password = Encryptor.?(text); + } + } + + [DataMember(Name = "SavePassword")] + public bool SavePassword + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string RecoverUrl + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public bool FailedToRestorePassword + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public PasswordHolder(string Password = "", bool SavePassword = true, string recoverUrl = "") + { + this.Password = Password; + this.SavePassword = SavePassword; + RecoverUrl = recoverUrl; + } + + public object Clone() + { + return new PasswordHolder(Password, SavePassword, RecoverUrl); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), EncryptedPassword)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SavePassword)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + EncryptedPassword = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + SavePassword = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + if (!string.IsNullOrEmpty(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value) && string.IsNullOrEmpty(EncryptedPassword)) + { + FailedToRestorePassword = true; + } + } + } + /// + /// Typecasts setting as Period item + /// + [Serializable] + [Published] + [DataContract] + [ProtoContract] + public sealed class SettingItemPeriod : SettingItem + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private BasePeriod[] ??; + + public override SettingItemType Type => SettingItemType.Period; + + public int MultiplierMinimum + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int MultiplierMaximum + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public BasePeriod[] ExcludedPeriods + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private Period ValuePeriod + { + get + { + if (value != null) + { + return (Period)value; + } + return default(Period); + } + set + { + value = period; + } + } + + public SettingItemPeriod() + { + } + + public SettingItemPeriod(string name, Period value, int sortIndex = 0) + : base(name, value, sortIndex) + { + MultiplierMinimum = 1; + MultiplierMaximum = int.MaxValue; + } + + private SettingItemPeriod(SettingItemPeriod P_0) + : base(P_0) + { + MultiplierMinimum = P_0.MultiplierMinimum; + MultiplierMaximum = P_0.MultiplierMaximum; + ExcludedPeriods = P_0.ExcludedPeriods; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemPeriod(this); + } + + [NotPublished] + public static implicit operator Period(SettingItemPeriod item) + { + return (Period)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is Period; + } + + [NotPublished] + protected override object ValidateValue(object value) + { + Period period = (Period)value; + if (period.PeriodMultiplier < MultiplierMinimum) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 3); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(MultiplierMinimum); + throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + if (period.PeriodMultiplier > MultiplierMaximum) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 3); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(MultiplierMaximum); + throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + BasePeriod[] excludedPeriods = ExcludedPeriods; + if (excludedPeriods != null && excludedPeriods.Contains(period.BasePeriod)) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return value; + } + + [NotPublished] + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((IXElementSerialization)Value).ToXElement())); + return xElement; + } + + [NotPublished] + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + if (xElement != null) + { + XElement xElement2 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Period period = default(Period); + period.FromXElement(xElement2.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()), deserializationInfo); + value = period; + } + } + } + } + public class SettingItemPnlAlertsContainer : SettingItem + { + public override SettingItemType Type => SettingItemType.PnlAlertsContainer; + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private PnlAlertsContainer PnlAlertsContainer + { + get + { + return (PnlAlertsContainer)Value; + } + set + { + Value = pnlAlertsContainer; + } + } + + public SettingItemPnlAlertsContainer() + { + } + + public SettingItemPnlAlertsContainer(string name, PnlAlertsContainer pnLAlertsCollection, int sortIndex = 0) + : base(name, pnLAlertsCollection, sortIndex) + { + } + + public SettingItemPnlAlertsContainer(SettingItemPnlAlertsContainer settingItem) + : base(settingItem) + { + value = ((PnlAlertsContainer)settingItem.Value).Clone(); + } + + public override SettingItem GetCopy() + { + return new SettingItemPnlAlertsContainer(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is PnlAlertsContainer; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + PnlAlertItem[] pnlAlerts = PnlAlertsContainer.PnlAlerts; + foreach (PnlAlertItem pnlAlertItem in pnlAlerts) + { + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), pnlAlertItem.IsChecked)); + if (pnlAlertItem.Symbol != null) + { + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), pnlAlertItem.Symbol.CreateInfo().ToXElement())); + } + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), pnlAlertItem.TargetValue)); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), pnlAlertItem.Increment)); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), pnlAlertItem.Precision)); + xElement.Add(xElement2); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + element = xElement; + } + List list = new List(); + IEnumerable enumerable = element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (enumerable != null) + { + foreach (XElement item in enumerable) + { + PnlAlertItem pnlAlertItem = new PnlAlertItem + { + IsChecked = (item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToBool() ?? false), + TargetValue = (item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToDouble() ?? 0.0), + Increment = (item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToDouble() ?? 1.0), + Precision = (item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToInt() ?? 0) + }; + XElement xElement2 = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + XElement xElement3 = xElement2.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + BusinessObjectInfo businessObjectInfo = new BusinessObjectInfo(); + businessObjectInfo.FromXElement(xElement3, deserializationInfo); + pnlAlertItem.Symbol = Core.Instance.GetSymbol(businessObjectInfo); + } + } + list.Add(pnlAlertItem); + } + } + Value = new PnlAlertsContainer + { + PnlAlerts = list.ToArray() + }; + } + } + public class SettingitemPoints : SettingItem + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private Func ??; + + [CompilerGenerated] + private bool ??; + + public override SettingItemType Type => SettingItemType.DrawingPoints; + + public int PointsInitialized + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Func FindVariableTick + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool EnablePriceSelection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingitemPoints() + { + } + + public SettingitemPoints(string name, double[][] Points, int sortIndex = 0) + : base(name, Points, sortIndex) + { + EnablePriceSelection = true; + Value = ?(Points); + } + + private SettingitemPoints(SettingitemPoints P_0) + { + EnablePriceSelection = P_0.EnablePriceSelection; + Value = ?((double[][])P_0.value); + } + + public override SettingItem GetCopy() + { + return new SettingitemPoints(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is double[][]; + } + + protected override XElement ValueToXElement() + { + double[][] array = (double[][])Value; + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), array.Length)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + double[][] array2 = array; + foreach (double[] array3 in array2) + { + XElement xElement3 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement3.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), array3[0])); + xElement3.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), array3[1])); + xElement2.Add(xElement3); + } + xElement.Add(xElement2); + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement? xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + int level = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + double[][] array = InitPoints(level); + int num = 0; + foreach (XElement item in xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements()) + { + array[num][0] = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(); + array[num][1] = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(); + num++; + } + value = array; + } + + protected double[][] InitPoints(int level) + { + double[][] array = new double[level][]; + for (int i = 0; i < array.Length; i++) + { + array[i] = new double[2]; + } + return array; + } + + private double[][] ?(double[][] P_0) + { + double[][] array = InitPoints(P_0.Length); + for (int i = 0; i < P_0.GetLength(0); i++) + { + double[] array2 = P_0[i]; + for (int j = 0; j < array2.Length; j++) + { + array[i][j] = array2[j]; + } + } + return array; + } + } + [Serializable] + [DataContract] + public sealed class SettingItemRadioLocalized : SettingItem + { + [CompilerGenerated] + private new sealed class ? + { + public object ??; + + internal bool ?(SelectItem P_0) + { + return P_0.Value.CompareTo(??) == 0; + } + } + + private List ??; + + public override SettingItemType Type => SettingItemType.RadioLocalized; + + [Bindable("items")] + public List Items + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [DataMember(Name = "Value")] + private SelectItem SeletedItem + { + get + { + return Value as SelectItem; + } + set + { + Value = selectItem; + } + } + + public SettingItemRadioLocalized() + { + } + + public SettingItemRadioLocalized(string name, SelectItem value, List items, int sortIndex = 0) + : base(name, value, sortIndex) + { + Items = items; + } + + private SettingItemRadioLocalized(SettingItemRadioLocalized P_0) + : base(P_0) + { + Items = P_0.Items; + } + + public override SettingItem GetCopy() + { + return new SettingItemRadioLocalized(this); + } + + public static implicit operator SelectItem(SettingItemRadioLocalized item) + { + return item.Value as SelectItem; + } + + protected override bool IsValueTypeValid(object value) + { + return value is SelectItem; + } + + internal override void ?(object P_0, bool P_1 = false) + { + if (!(P_0 is SelectItem)) + { + SelectItem selectItem = Items?.FirstOrDefault((SelectItem selectItem2) => selectItem2.Value.CompareTo(P_0) == 0); + P_0 = selectItem ?? new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), (IComparable)P_0); + } + base.?(P_0, P_1); + } + + protected override XElement ValueToXElement() + { + string content = string.Empty; + if (SeletedItem != null) + { + if (SeletedItem.Value is int num) + { + content = num.ToString(); + } + else if (SeletedItem.Value != null) + { + content = SeletedItem.Value.ToString(); + } + } + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), content); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + if (int.TryParse(xElement.Value, out var result)) + { + SeletedItem = new SelectItem(string.Empty, result); + } + else + { + SeletedItem = new SelectItem(string.Empty, xElement.Value); + } + } + } + } + public class SettingItemRangeSelector : SettingItem + { + public override SettingItemType Type => SettingItemType.RangeSelector; + + [DataMember(Name = "Value")] + [ProtoMember(29)] + private DateTimeRange ValueSelector + { + get + { + return (DateTimeRange)value; + } + set + { + value = dateTimeRange; + } + } + + public SettingItemRangeSelector() + { + } + + public SettingItemRangeSelector(string name, DateTimeRange value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemRangeSelector(SettingItemRangeSelector P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemRangeSelector(this); + } + + protected override bool IsValueTypeValid(object value) + { + return Value is DateTimeRange; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.ValueFromXElement(element, deserializationInfo); + DateTimeRange dateTimeRange = new DateTimeRange(); + dateTimeRange.FromXElement(element, deserializationInfo); + ValueSelector = dateTimeRange; + } + } + [Serializable] + [DataContract] + public sealed class SettingItemRss : SettingItem + { + public override SettingItemType Type => SettingItemType.Rss; + + [DataMember(Name = "Value")] + private Rss ValueRss + { + get + { + return Value as Rss; + } + set + { + Value = rss; + } + } + + public SettingItemRss() + { + } + + public SettingItemRss(string name, Rss value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemRss(SettingItemRss P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemRss(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is Rss; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Rss rss = new Rss(); + rss.FromXElement(element, deserializationInfo); + Value = rss; + } + } + /// + /// Typecasts setting as ComboBox item + /// + [Serializable] + [Published] + [DataContract] + [ProtoContract] + public sealed class SettingItemSelector : SettingItem + { + private IEnumerable ??; + + public override SettingItemType Type => SettingItemType.Selector; + + [Bindable("items")] + public IEnumerable Items + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemSelector() + { + } + + public SettingItemSelector(string name, string value, IEnumerable items, int sortIndex = 0) + : base(name, value, sortIndex) + { + Items = items; + } + + private SettingItemSelector(SettingItemSelector P_0) + : base(P_0) + { + Items = P_0.Items; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemSelector(this); + } + + [NotPublished] + public static implicit operator string(SettingItemSelector item) + { + return item.Value as string; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is string; + } + } + [Serializable] + [DataContract] + [ProtoContract] + public sealed class SettingItemSelectorLocalized : SettingItem + { + [CompilerGenerated] + private new sealed class ? + { + public SelectItem ??; + + internal bool ?(SelectItem P_0) + { + IComparable value = P_0.Value; + if (value == null) + { + return false; + } + return value.CompareTo(??.Value) == 0; + } + } + + [CompilerGenerated] + private sealed class ? + { + public object ??; + + internal bool ?(SelectItem P_0) + { + return P_0.Value.CompareTo(??) == 0; + } + } + + [CompilerGenerated] + private sealed class ? + { + public IComparable ??; + + internal bool ?(SelectItem P_0) + { + return P_0.Value.CompareTo(??) == 0; + } + } + + private List ??; + + public override SettingItemType Type => SettingItemType.SelectorLocalized; + + [Bindable("items")] + public List Items + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + private SelectItem SeletedItem + { + get + { + return Value as SelectItem; + } + set + { + Value = selectItem; + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private string SerializeValue + { + get + { + string result = string.Empty; + if (SeletedItem == null) + { + return result; + } + if (SeletedItem.Value is int || SeletedItem.Value is Enum) + { + result = ((int)(object)SeletedItem.Value).ToString(); + } + else if (SeletedItem.Value != null) + { + result = SeletedItem.Value.ToString(); + } + return result; + } + set + { + if (int.TryParse(s, out var result)) + { + SeletedItem = new SelectItem(string.Empty, result); + } + else + { + SeletedItem = new SelectItem(string.Empty, s); + } + } + } + + public SettingItemSelectorLocalized() + { + } + + public SettingItemSelectorLocalized(string name, SelectItem value, List items, int sortIndex = 0) + : base(name, value, sortIndex) + { + Items = items; + } + + public SettingItemSelectorLocalized(string name, IComparable value, List items, int sortIndex = 0) + : this(name, items?.FirstOrDefault((SelectItem P_0) => P_0.Value.CompareTo(value) == 0), items, sortIndex) + { + } + + private SettingItemSelectorLocalized(SettingItemSelectorLocalized P_0) + : base(P_0) + { + Items = P_0.Items; + } + + public override SettingItem GetCopy() + { + return new SettingItemSelectorLocalized(this); + } + + public static implicit operator SelectItem(SettingItemSelectorLocalized item) + { + return item.Value as SelectItem; + } + + protected override bool IsValueTypeValid(object value) + { + return value is SelectItem; + } + + protected override object ValidateValue(object value) + { + SelectItem ?? = value as SelectItem; + if (?? == null) + { + return Value; + } + if (Items == null || Items.Count == 0) + { + return value; + } + if (Items.Any(delegate(SelectItem P_0) + { + IComparable comparable = P_0.Value; + return comparable != null && comparable.CompareTo(??.Value) == 0; + })) + { + return value; + } + return Value; + } + + internal override void ?(object P_0, bool P_1 = false) + { + if (P_0 is SelectItem selectItem) + { + P_0 = selectItem.Value; + } + SelectItem selectItem2 = Items?.FirstOrDefault((SelectItem selectItem3) => selectItem3.Value.CompareTo(P_0) == 0); + P_0 = selectItem2 ?? new SelectItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), (IComparable)P_0); + base.?(P_0, P_1); + } + + internal override void ?(SettingItem P_0) + { + if (P_0 is SettingItemSelectorLocalized { Items: not null } settingItemSelectorLocalized) + { + Items = settingItemSelectorLocalized.Items; + } + base.?(P_0); + } + + protected override XElement ValueToXElement() + { + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SerializeValue); + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + SerializeValue = xElement.Value; + } + } + } + [Serializable] + [DataContract] + [ProtoContract] + public class SettingItemSlider : SettingItem + { + private ulong ??; + + public override SettingItemType Type => SettingItemType.Slider; + + [Bindable("stepsCount")] + public ulong StepsCount + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private ulong ValueUlong + { + get + { + return (ulong)Value; + } + set + { + Value = num; + } + } + + public SettingItemSlider() + { + } + + public SettingItemSlider(string name, ulong value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemSlider(SettingItemSlider P_0) + : base(P_0) + { + StepsCount = P_0.StepsCount; + } + + [NotPublished] + public static implicit operator ulong(SettingItemSlider item) + { + return (ulong)item.Value; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemSlider(this); + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is ulong; + } + + [NotPublished] + protected override object ValidateValue(object value) + { + value = base.ValidateValue(value); + return Math.Min((ulong)value, StepsCount); + } + } + [Serializable] + [DataContract] + public class SettingItemSound : SettingItem + { + public bool EnableSounds; + + public override SettingItemType Type => SettingItemType.Sound; + + [DataMember(Name = "Value")] + private Dictionary ValuDictionrary + { + get + { + return value as Dictionary; + } + set + { + value = dictionary; + } + } + + public SettingItemSound() + { + } + + public SettingItemSound(string name, Dictionary value, bool enableSounds = true, int sortIndex = 0) + : base(name, value, sortIndex) + { + EnableSounds = enableSounds; + } + + private SettingItemSound(SettingItemSound P_0) + : base(P_0) + { + EnableSounds = P_0.EnableSounds; + } + + public override SettingItem GetCopy() + { + return new SettingItemSound(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is Dictionary; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), EnableSounds)); + foreach (KeyValuePair item in ValuDictionrary) + { + xElement.Add(item.Value.ToXElement()); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + EnableSounds = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + Dictionary dictionary = new Dictionary(); + foreach (XElement item in xElement.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + SoundItem soundItem = new SoundItem(); + soundItem.FromXElement(item, deserializationInfo); + dictionary[soundItem.Name] = soundItem; + } + ValuDictionrary = dictionary; + } + } + /// + /// Typecasts setting as TextBox item + /// + [Serializable] + [Published] + [DataContract] + [ProtoContract] + public sealed class SettingItemString : SettingItem + { + [CompilerGenerated] + private bool ??; + + public override SettingItemType Type => SettingItemType.String; + + public bool ApplyOnEachInput + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemString() + { + } + + public SettingItemString(string name, string value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemString(SettingItemString P_0) + : base(P_0) + { + } + + [NotPublished] + public static implicit operator string(SettingItemString item) + { + return item.Value as string; + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemString(this); + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is string; + } + } + /// + /// Typecasts setting as SymbolLookup item + /// + [Serializable] + [DataContract] + public sealed class SettingItemSymbol : SettingItem + { + public override SettingItemType Type => SettingItemType.Symbol; + + [DataMember(Name = "Value")] + private BusinessObjectInfo ValueInfo + { + get + { + return (Value as Symbol)?.CreateInfo() ?? BusinessObjectInfo.Empty; + } + set + { + if (!(businessObjectInfo == BusinessObjectInfo.Empty) && !(businessObjectInfo == SymbolInfo.Empty)) + { + Value = Core.Instance.GetSymbol(businessObjectInfo); + } + } + } + + public SettingItemSymbol() + { + } + + public SettingItemSymbol(string name, Symbol value = null, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemSymbol(SettingItemSymbol P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemSymbol(this); + } + + public static implicit operator Symbol(SettingItemSymbol item) + { + return item.Value as Symbol; + } + + protected override bool IsValueTypeValid(object value) + { + return value is Symbol; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + SymbolInfo empty = SymbolInfo.Empty; + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + empty.FromXElement(xElement, deserializationInfo); + ValueInfo = empty; + } + } + + protected override XElement ValueToXElement() + { + return ValueInfo.ToXElement(); + } + } + /// + /// Typecasts setting as TextBox item + /// + [Serializable] + [DataContract] + [ProtoContract] + public sealed class SettingItemTextArea : SettingItem + { + [CompilerGenerated] + private bool ??; + + public override SettingItemType Type => SettingItemType.TextArea; + + public bool ApplyOnEachInput + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + [ProtoMember(1)] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemTextArea() + { + } + + public SettingItemTextArea(string name, string value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemTextArea(SettingItemTextArea P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemTextArea(this); + } + + public static implicit operator string(SettingItemTextArea item) + { + return item.Value as string; + } + + protected override bool IsValueTypeValid(object value) + { + return value is string; + } + } + public class SettingItemTimeFrameConfig : SettingItem + { + public override SettingItemType Type => SettingItemType.TimeFrameConfig; + + [DataMember(Name = "Value")] + private string ValueString + { + get + { + return Value as string; + } + set + { + Value = text; + } + } + + public SettingItemTimeFrameConfig() + { + } + + public SettingItemTimeFrameConfig(string name, TimeFrameConfig value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemTimeFrameConfig(SettingItemTimeFrameConfig P_0) + : base(P_0) + { + } + + public override SettingItem GetCopy() + { + return new SettingItemTimeFrameConfig(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is TimeFrameConfig; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + TimeFrameConfig timeFrameConfig = new TimeFrameConfig(); + timeFrameConfig.FromXElement(element, deserializationInfo); + Value = timeFrameConfig; + } + } + public class SettingItemTimeInTradeContainer : SettingItem + { + [DataMember(Name = "Value")] + [ProtoMember(1)] + private TimeInTradeContainer TimeInTradeContainer + { + get + { + return (TimeInTradeContainer)Value; + } + set + { + Value = timeInTradeContainer; + } + } + + public override SettingItemType Type => SettingItemType.TimeInTradeContainer; + + public SettingItemTimeInTradeContainer() + { + } + + public SettingItemTimeInTradeContainer(string name, TimeInTradeContainer timeInTradeCollection, int sortIndex = 0) + : base(name, timeInTradeCollection, sortIndex) + { + } + + public SettingItemTimeInTradeContainer(SettingItemTimeInTradeContainer settingItem) + { + value = ((TimeInTradeContainer)settingItem.Value).Clone(); + } + + public override SettingItem GetCopy() + { + return new SettingItemTimeInTradeContainer(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is TimeInTradeContainer; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + TimeInTradeItem[] timeInTradeItems = TimeInTradeContainer.TimeInTradeItems; + foreach (TimeInTradeItem timeInTradeItem in timeInTradeItems) + { + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), timeInTradeItem.IsChecked)); + if (timeInTradeItem.Symbol != null) + { + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), timeInTradeItem.Symbol.CreateInfo().ToXElement())); + } + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), timeInTradeItem.TimeInSeconds)); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)timeInTradeItem.PLDirection)); + xElement.Add(xElement2); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + element = xElement; + } + List list = new List(); + IEnumerable enumerable = element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (enumerable != null) + { + foreach (XElement item in enumerable) + { + TimeInTradeItem timeInTradeItem = new TimeInTradeItem + { + IsChecked = (item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToBool() ?? false), + TimeInSeconds = (item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToInt() ?? 0), + PLDirection = (TimeInTradePlDirection)(item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToInt() ?? 0) + }; + XElement xElement2 = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + XElement xElement3 = xElement2.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + BusinessObjectInfo businessObjectInfo = new BusinessObjectInfo(); + businessObjectInfo.FromXElement(xElement3, deserializationInfo); + timeInTradeItem.Symbol = Core.Instance.GetSymbol(businessObjectInfo); + } + } + list.Add(timeInTradeItem); + } + } + Value = new TimeInTradeContainer + { + TimeInTradeItems = list.ToArray() + }; + } + } + [Serializable] + [DataContract] + [ProtoContract] + public sealed class SettingItemTimeZone : SettingItem + { + [CompilerGenerated] + private bool ??; + + [DataMember(Name = "Type")] + [ProtoMember(1)] + private TimeZoneType ??; + + [DataMember(Name = "InfoId")] + [ProtoMember(2)] + private string ??; + + [DataMember(Name = "BaseUtcOffset")] + [ProtoMember(3)] + private TimeSpan ??; + + [DataMember(Name = "DisplayName")] + [ProtoMember(4)] + private string ??; + + [DataMember(Name = "StandardDisplayName")] + [ProtoMember(5)] + private string ??; + + public override SettingItemType Type => SettingItemType.TimeZone; + + public bool IsFavorite + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override object Value + { + get + { + if (?? == TimeZoneType.Local) + { + return new TimeZone(??); + } + TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(??); + if (timeZoneInfo == null) + { + timeZoneInfo = TimeZoneInfo.CreateCustomTimeZone(??, ??, ??, ??); + } + return new TimeZone(??, timeZoneInfo); + } + set + { + base.Value = value; + } + } + + public SettingItemTimeZone() + { + } + + public SettingItemTimeZone(string name, TimeZone value, int sortIndex = 0) + : base(name, value, sortIndex) + { + ?? = value.Type; + ?? = value.TimeZoneInfo.Id; + ?? = value.TimeZoneInfo.BaseUtcOffset; + ?? = value.TimeZoneInfo.DisplayName; + ?? = value.TimeZoneInfo.StandardName; + } + + private SettingItemTimeZone(SettingItemTimeZone P_0) + : base(P_0) + { + ?? = P_0.??; + ?? = P_0.??; + ?? = P_0.??; + ?? = P_0.??; + ?? = P_0.??; + } + + public override SettingItem GetCopy() + { + return new SettingItemTimeZone(this); + } + + public static implicit operator TimeZone(SettingItemTimeZone item) + { + return (TimeZone)item.Value; + } + + protected override bool IsValueTypeValid(object value) + { + return value is TimeZone; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)??)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ??)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ??)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ??)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ??)); + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ?? = (TimeZoneType)xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + ?? = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + ?? = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToTimeSpan(); + ?? = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + ?? = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + } + } + } + [Serializable] + [DataContract] + public class SettingItemTimeZoneManager : SettingItemList + { + public override SettingItemType Type => SettingItemType.TimeZoneManager; + + public List FavoriteTimeZones + { + get + { + List list = new List(); + foreach (SettingItemTimeZone item in Value as List) + { + if (item.IsFavorite) + { + list.Add((TimeZone)item.Value); + } + } + return list; + } + } + + [DataMember(Name = "Items")] + protected override List Items + { + get + { + List list = new List(); + foreach (SettingItemTimeZone item in Value as List) + { + if (item.IsFavorite) + { + list.Add(item); + } + } + return list; + } + set + { + Value = ?(value); + } + } + + public SettingItemTimeZoneManager() + { + } + + public SettingItemTimeZoneManager(string name, IList items, int sortIndex = 0) + : base(name, new List(), sortIndex) + { + Value = ?(items); + } + + private SettingItemTimeZoneManager(SettingItemTimeZoneManager P_0) + : base(P_0) + { + Value = ?(CopyItems()); + } + + public override SettingItem GetCopy() + { + return new SettingItemTimeZoneManager(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is IList; + } + + private new List ?(IList P_0) + { + List list = new List(); + Dictionary dictionary = new Dictionary(); + foreach (SettingItem item in P_0) + { + if (item is SettingItemTimeZone settingItemTimeZone) + { + dictionary[((TimeZone)settingItemTimeZone.Value).TimeZoneInfo.Id] = settingItemTimeZone; + } + } + foreach (TimeZoneInfo systemTimeZone in TimeZoneInfo.GetSystemTimeZones()) + { + SettingItemTimeZone settingItemTimeZone2 = new SettingItemTimeZone(systemTimeZone.Id, new TimeZone(TimeZoneType.Specific, systemTimeZone)); + if (dictionary.ContainsKey(systemTimeZone.Id)) + { + settingItemTimeZone2.IsFavorite = true; + } + list.Add(settingItemTimeZone2); + } + return list; + } + + protected override XElement ValueToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + List items = Items; + for (int i = 0; i < items.Count; i++) + { + xElement.Add(items[i].ToXElement()); + } + return xElement; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + foreach (XElement item in xElement.Elements()) + { + SettingItemTimeZone settingItemTimeZone = new SettingItemTimeZone(); + settingItemTimeZone.FromXElement(item, deserializationInfo); + list.Add(settingItemTimeZone); + } + } + Items = list; + } + } + [Serializable] + public class SelectItem : IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IComparable ??; + + [CompilerGenerated] + private SettingItemSeparatorGroup ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private Action ??; + + public string Text + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IComparable Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SettingItemSeparatorGroup SeparatorGroup + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object SelectConfirmation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Action Action + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SelectItem(string text, IComparable value = null) + { + Text = text; + Value = value ?? Text; + } + + public SelectItem(string text, int value) + { + Text = text; + Value = value; + } + + public SelectItem(string text, string value) + { + Text = text; + Value = value; + } + + public override string ToString() + { + return Text; + } + + public bool Equals(SelectItem other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + return object.Equals(Value, other.Value); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((SelectItem)obj); + } + + public override int GetHashCode() + { + if (Value == null) + { + return 0; + } + return Value.GetHashCode(); + } + } + public class SettingItemEventArgs : EventArgs + { + public new static SettingItemEventArgs Empty => new SettingItemEventArgs(); + } + public delegate void SettingItemEventHandler(SettingItem sender, SettingItemEventArgs e); + public class SettingsHolder : Dictionary + { + public SettingsHolder(IList settings) + { + if (settings == null) + { + return; + } + foreach (SettingItem setting in settings) + { + if (!ContainsKey(setting.Name)) + { + Add(setting.Name, setting); + } + } + } + } + public sealed class SymbolMap : IDisposable, IUniqueID, ICustomizable, IConnectionStateDependent + { + [CompilerGenerated] + private sealed class ? + { + public SymbolMap ??; + + public Symbol ??; + + internal void ?() + { + ??.?(??.TradableSymbol); + ??.?? = ??; + ??.?(??.QuotesSymbol); + ??.?(??.TradableSymbol); + } + } + + [CompilerGenerated] + private sealed class ? + { + public SymbolMap ??; + + public bool ??; + + internal void ?() + { + ??.?(??.TradableSymbol); + ??.?? = ??; + ??.?(?? ? ??.QuotesSymbol : ??.TradableSymbol); + ??.?(??.TradableSymbol); + } + } + + [CompilerGenerated] + private sealed class ? + { + public SymbolMap ??; + + public Symbol ??; + + public Symbol ??; + + public Action ??; + + internal void ?() + { + ??.?(??); + ??.?(delegate + { + ??.?(??); + ??.?? = ??; + ??.?(??.QuotesSymbol); + ??.?(??); + }); + ??.?(??); + } + + internal void ?() + { + ??.?(??); + ??.?? = ??; + ??.?(??.QuotesSymbol); + ??.?(??); + } + } + + [CompilerGenerated] + private string ??; + + private Symbol ??; + + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + private bool ??; + + private readonly ConnectionStateObserver ??; + + public string UniqueId => Id; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public Symbol TradableSymbol + { + get + { + return ??; + } + private set + { + if (?? == symbol) + { + return; + } + Symbol ?? = TradableSymbol; + ??.?(delegate + { + ?(??); + symbol.?(delegate + { + ?(symbol); + ?? = symbol; + ?(QuotesSymbol); + ?(symbol); + }); + ?(??); + }); + } + } + + public Symbol QuotesSymbol + { + get + { + return ??; + } + private set + { + if (?? != symbol) + { + TradableSymbol.?(delegate + { + ?(TradableSymbol); + ?? = symbol; + ?(QuotesSymbol); + ?(TradableSymbol); + }); + } + } + } + + public Symbol TickHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbol; + } + } + + public Symbol MinuteHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbol; + } + } + + public Symbol DayHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbol; + } + } + + public Symbol VolumeAnalysisSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbol; + } + } + + public bool IsActive + { + get + { + return ??; + } + private set + { + if (?? == flag) + { + return; + } + if (TradableSymbol == null) + { + ?? = flag; + return; + } + TradableSymbol.?(delegate + { + ?(TradableSymbol); + ?? = flag; + ?(flag ? QuotesSymbol : TradableSymbol); + ?(TradableSymbol); + }); + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id), + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TradableSymbol), + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuotesSymbol), + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TickHistorySymbol), + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MinuteHistorySymbol), + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), DayHistorySymbol), + new SettingItemSymbol(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), VolumeAnalysisSymbol), + new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsActive) + }; + } + set + { + Id = value.GetValueOrDefault(Id, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?? = value.GetValueOrDefault(??, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?? = value.GetValueOrDefault(??, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + TickHistorySymbol = value.GetValueOrDefault(TickHistorySymbol, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + MinuteHistorySymbol = value.GetValueOrDefault(MinuteHistorySymbol, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DayHistorySymbol = value.GetValueOrDefault(DayHistorySymbol, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + VolumeAnalysisSymbol = value.GetValueOrDefault(VolumeAnalysisSymbol, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + IsActive = value.GetValueOrDefault(IsActive, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value2)) + { + VolumeAnalysisSymbol = value2; + } + else + { + VolumeAnalysisSymbol = DayHistorySymbol ?? MinuteHistorySymbol ?? TickHistorySymbol ?? QuotesSymbol; + } + } + } + + internal SymbolMap() + { + ?? = new ConnectionStateObserver(this, ConnectionStateObserverPriority.High, ConnectionState.Connected, ConnectionState.Disconnected, ConnectionState.ConnectionLost); + } + + internal SymbolMap(Symbol P_0) + : this() + { + Id = Guid.NewGuid().ToString(); + IsActive = true; + ?? = P_0; + } + + internal bool ?(Period P_0, out Symbol P_1) + { + P_1 = null; + if (P_0.BasePeriod >= BasePeriod.Day) + { + P_1 = DayHistorySymbol; + } + else if (P_0.BasePeriod >= BasePeriod.Minute) + { + P_1 = MinuteHistorySymbol; + } + else + { + P_1 = TickHistorySymbol; + } + return P_1 != null; + } + + internal void ?(SymbolMappingParameters P_0, bool P_1 = true) + { + IsActive = P_0.IsActive; + TradableSymbol = P_0.TradableSymbol; + if (P_1) + { + QuotesSymbol = P_0.QuotesSymbol; + } + else + { + ?? = P_0.QuotesSymbol; + } + TickHistorySymbol = P_0.TickHistorySymbol; + MinuteHistorySymbol = P_0.MinuteHistorySymbol; + DayHistorySymbol = P_0.DayHistorySymbol; + VolumeAnalysisSymbol = P_0.VolumeAnalysisSymbol; + } + + internal void ?() + { + QuotesSymbol = null; + TickHistorySymbol = null; + MinuteHistorySymbol = null; + DayHistorySymbol = null; + VolumeAnalysisSymbol = null; + } + + public SymbolMapState GetState() + { + return new SymbolMapState(this); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 6); + defaultInterpolatedStringHandler.AppendFormatted(TradableSymbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(QuotesSymbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TickHistorySymbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(MinuteHistorySymbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(DayHistorySymbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(VolumeAnalysisSymbol); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public void Dispose() + { + ??.Dispose(); + } + + public ConnectionDependency GetConnectionStateDependency() + { + List list = new List { TradableSymbol.ConnectionId }; + ?(QuotesSymbol, list); + ?(TickHistorySymbol, list); + ?(MinuteHistorySymbol, list); + ?(DayHistorySymbol, list); + ?(VolumeAnalysisSymbol, list); + return new ConnectionDependency + { + Behavior = ConnectionDependencyBehavior.PartialDependency, + DependentConnectionsIds = list.ToArray() + }; + } + + public void OnConnectionStateChanged(Connection connection, ConnectionStateChangedEventArgs e) + { + string id = connection.Id; + if (TradableSymbol.ConnectionId == id) + { + TradableSymbol = Core.Instance.GetSymbol(TradableSymbol.CreateInfo()); + } + if (QuotesSymbol?.ConnectionId == id) + { + QuotesSymbol = Core.Instance.GetSymbol(QuotesSymbol.CreateInfo()); + } + if (TickHistorySymbol?.ConnectionId == id) + { + TickHistorySymbol = Core.Instance.GetSymbol(TickHistorySymbol.CreateInfo()); + } + if (MinuteHistorySymbol?.ConnectionId == id) + { + MinuteHistorySymbol = Core.Instance.GetSymbol(MinuteHistorySymbol.CreateInfo()); + } + if (DayHistorySymbol?.ConnectionId == id) + { + DayHistorySymbol = Core.Instance.GetSymbol(DayHistorySymbol.CreateInfo()); + } + if (VolumeAnalysisSymbol?.ConnectionId == id) + { + VolumeAnalysisSymbol = Core.Instance.GetSymbol(VolumeAnalysisSymbol.CreateInfo()); + } + } + + private void ?(Symbol P_0, List P_1) + { + if (P_0 != null) + { + P_1.Add(P_0.ConnectionId); + } + } + + private void ?(Symbol P_0) + { + if (P_0.QuotesSubscribed) + { + P_0.SubscribeAction(SubscribeQuoteType.Quote); + } + if (P_0.Level2Subscribed) + { + P_0.SubscribeAction(SubscribeQuoteType.Level2); + } + if (P_0.LastsSubscribed) + { + P_0.SubscribeAction(SubscribeQuoteType.Last); + } + if (P_0.MarkSubscribed) + { + P_0.SubscribeAction(SubscribeQuoteType.Mark); + } + } + + private void ?(Symbol P_0) + { + if (P_0.QuotesSubscribed) + { + P_0.UnSubscribeAction(SubscribeQuoteType.Quote); + } + if (P_0.Level2Subscribed) + { + P_0.UnSubscribeAction(SubscribeQuoteType.Level2); + } + if (P_0.LastsSubscribed) + { + P_0.UnSubscribeAction(SubscribeQuoteType.Last); + } + if (P_0.MarkSubscribed) + { + P_0.UnSubscribeAction(SubscribeQuoteType.Mark); + } + } + + private void ?(Symbol P_0) + { + if (P_0 != null && TradableSymbol.HasAnySubscription) + { + DayBar dayBar = ?(P_0); + dayBar.FullRefresh = true; + TradableSymbol.?(dayBar); + } + } + + private DayBar ?(Symbol P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + } + public class SymbolMappingParameters + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Symbol ??; + + public bool IsActive + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol TradableSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol QuotesSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol TickHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol MinuteHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol DayHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol VolumeAnalysisSymbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SymbolMappingParameters(Symbol tradableSymbol) + { + TradableSymbol = tradableSymbol; + } + + public SymbolMappingParameters(SymbolMap symbolMap) + { + IsActive = symbolMap.IsActive; + TradableSymbol = symbolMap.TradableSymbol; + QuotesSymbol = symbolMap.QuotesSymbol; + TickHistorySymbol = symbolMap.TickHistorySymbol; + MinuteHistorySymbol = symbolMap.MinuteHistorySymbol; + DayHistorySymbol = symbolMap.DayHistorySymbol; + VolumeAnalysisSymbol = symbolMap.VolumeAnalysisSymbol; + } + } + public sealed class SymbolMapState + { + [CompilerGenerated] + private readonly bool ??; + + [CompilerGenerated] + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Symbol ??; + + public bool IsActive + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol TradableSymbol + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol QuotesSymbol + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol TickHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol MinuteHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol DayHistorySymbol + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Symbol VolumeAnalysisSymbol + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal SymbolMapState(SymbolMap P_0) + { + ?? = P_0.IsActive; + ?? = P_0.TradableSymbol; + ?? = P_0.QuotesSymbol; + ?? = P_0.TickHistorySymbol; + ?? = P_0.MinuteHistorySymbol; + ?? = P_0.DayHistorySymbol; + ?? = P_0.VolumeAnalysisSymbol; + } + } + public class SymbolsMappingEventArgs : EventArgs + { + [CompilerGenerated] + private SymbolMap ??; + + [CompilerGenerated] + private readonly SymbolMapState ??; + + public SymbolMap SymbolMap + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = symbolMap; + } + } + + public SymbolMapState PreviousState + { + [CompilerGenerated] + get + { + return ??; + } + } + + public SymbolsMappingEventArgs(SymbolMap symbolMap, SymbolMapState previousState = null) + { + SymbolMap = symbolMap; + ?? = previousState; + } + } + public class SymbolsMappingManager : ICustomizable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal Symbol ?(SymbolMapState P_0) + { + return P_0.QuotesSymbol; + } + + internal Symbol ?(SymbolMapState P_0) + { + return P_0.TickHistorySymbol; + } + + internal Symbol ?(SymbolMapState P_0) + { + return P_0.MinuteHistorySymbol; + } + + internal Symbol ?(SymbolMapState P_0) + { + return P_0.DayHistorySymbol; + } + + internal Symbol ?(SymbolMapState P_0) + { + return P_0.VolumeAnalysisSymbol; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(SymbolMap P_0) + { + return P_0.TradableSymbol.Equals(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(Symbol P_0) + { + return P_0.Equals(??); + } + } + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + private readonly Dictionary ??; + + private readonly object ??; + + public IList Settings + { + get + { + List list = new List(); + lock (??) + { + foreach (KeyValuePair item in ??) + { + list.Add(new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), item.Value.Settings)); + } + return list; + } + } + set + { + foreach (SettingItem item in value) + { + if (!(item.Name != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && item.Value is IList settings) + { + SymbolMap symbolMap = new SymbolMap + { + Settings = settings + }; + lock (??) + { + ??.Add(symbolMap.Id, symbolMap); + } + } + } + } + } + + public SymbolMap[] AllMaps + { + get + { + lock (??) + { + return ??.Values.ToArray(); + } + } + } + + public event EventHandler MapAdded + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler MapUpdating + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler MapUpdated + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler MapDeleting + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler MapDeleted + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + internal SymbolsMappingManager() + { + ?? = new Dictionary(); + ?? = new object(); + } + + internal void ?() + { + } + + public string AddSymbolMap(SymbolMappingParameters parameters) + { + SymbolMap symbolMap; + lock (??) + { + ?(parameters, null); + symbolMap = new SymbolMap(parameters.TradableSymbol); + ??.Add(symbolMap.Id, symbolMap); + symbolMap.?(parameters); + } + ?(symbolMap); + return symbolMap.Id; + } + + public void UpdateSymbolMap(string symbolMapId, SymbolMappingParameters parameters) + { + if (string.IsNullOrEmpty(symbolMapId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SymbolMap symbolMap; + SymbolMapState state; + lock (??) + { + symbolMap = ??[symbolMapId]; + ?(parameters, symbolMapId); + ?(symbolMap); + state = symbolMap.GetState(); + symbolMap.?(parameters, parameters.IsActive && state.IsActive == parameters.IsActive); + } + ?(symbolMap, state); + } + + public void DeleteSymbolMap(string symbolMapId) + { + if (string.IsNullOrEmpty(symbolMapId)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + SymbolMap symbolMap; + lock (??) + { + symbolMap = ??[symbolMapId]; + ?(symbolMap); + symbolMap.?(); + ??.Remove(symbolMapId); + } + symbolMap.Dispose(); + ?(symbolMap); + } + + public void DeleteAllMaps() + { + SymbolMap[] allMaps = AllMaps; + foreach (SymbolMap symbolMap in allMaps) + { + ?(symbolMap); + symbolMap.?(); + lock (??) + { + ??.Remove(symbolMap.Id); + } + ?(symbolMap); + } + } + + public bool TryGetSymbolMapState(Symbol symbol, out SymbolMapState mapState) + { + SymbolMap symbolMap = ?(symbol); + if (symbolMap != null) + { + mapState = new SymbolMapState(symbolMap); + } + else + { + mapState = null; + } + return mapState != null; + } + + public bool TryGetQuotesSymbol(Symbol tradableSymbol, out Symbol quotesSymbol) + { + quotesSymbol = null; + lock (??) + { + SymbolMap symbolMap = ?(tradableSymbol); + if (symbolMap == null || !symbolMap.IsActive) + { + return false; + } + quotesSymbol = symbolMap.QuotesSymbol; + } + return quotesSymbol != null; + } + + public bool TryGetHistorySymbol(Symbol tradableSymbol, Period period, out Symbol historySymbol) + { + lock (??) + { + int num = 0; + Symbol symbol = null; + while (?(tradableSymbol, period, out historySymbol)) + { + symbol = historySymbol; + num++; + if (historySymbol.Id == tradableSymbol.Id) + { + break; + } + tradableSymbol = historySymbol; + } + historySymbol = symbol; + return num > 0; + } + } + + public bool TryGetVolumeAnalysisSymbol(Symbol tradableSymbol, out Symbol volumeAnalysisSymbol) + { + lock (??) + { + int num = 0; + Symbol symbol = null; + while (?(tradableSymbol, out volumeAnalysisSymbol)) + { + symbol = volumeAnalysisSymbol; + num++; + if (volumeAnalysisSymbol.Id == tradableSymbol.Id) + { + break; + } + tradableSymbol = volumeAnalysisSymbol; + } + volumeAnalysisSymbol = symbol; + return num > 0; + } + } + + private bool ?(Symbol P_0, Period P_1, out Symbol P_2) + { + P_2 = null; + SymbolMap symbolMap = ?(P_0); + if (symbolMap == null || !symbolMap.IsActive) + { + return false; + } + return symbolMap.?(P_1, out P_2); + } + + private bool ?(Symbol P_0, out Symbol P_1) + { + P_1 = null; + SymbolMap symbolMap = ?(P_0); + if (symbolMap == null || !symbolMap.IsActive) + { + return false; + } + P_1 = symbolMap.VolumeAnalysisSymbol; + return true; + } + + private SymbolMap ?(Symbol P_0) + { + return ??.Values.SingleOrDefault((SymbolMap symbolMap) => symbolMap.TradableSymbol.Equals(P_0)); + } + + private void ?(SymbolMappingParameters P_0, string P_1 = null) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.TradableSymbol == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?(P_0, P_1); + ?(P_0); + } + + private void ?(SymbolMappingParameters P_0, string P_1 = null) + { + SymbolMap symbolMap = ?(P_0.TradableSymbol); + bool num; + if (!string.IsNullOrEmpty(P_1)) + { + if (symbolMap == null) + { + return; + } + num = symbolMap.Id != P_1; + } + else + { + num = symbolMap != null; + } + if (num) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.TradableSymbol.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + private void ?(SymbolMappingParameters P_0) + { + if (P_0.TradableSymbol.Equals(P_0.QuotesSymbol)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.TradableSymbol.Equals(P_0.TickHistorySymbol)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.TradableSymbol.Equals(P_0.MinuteHistorySymbol)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.TradableSymbol.Equals(P_0.DayHistorySymbol)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.TradableSymbol.Equals(P_0.VolumeAnalysisSymbol)) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + private void ?(SymbolMappingParameters P_0) + { + ?(P_0.TradableSymbol, P_0.QuotesSymbol, (SymbolMapState symbolMapState) => symbolMapState.QuotesSymbol); + ?(P_0.TradableSymbol, P_0.TickHistorySymbol, (SymbolMapState symbolMapState) => symbolMapState.TickHistorySymbol); + ?(P_0.TradableSymbol, P_0.MinuteHistorySymbol, (SymbolMapState symbolMapState) => symbolMapState.MinuteHistorySymbol); + ?(P_0.TradableSymbol, P_0.DayHistorySymbol, (SymbolMapState symbolMapState) => symbolMapState.DayHistorySymbol); + ?(P_0.TradableSymbol, P_0.VolumeAnalysisSymbol, (SymbolMapState symbolMapState) => symbolMapState.VolumeAnalysisSymbol); + } + + private void ?(Symbol P_0, Symbol P_1, Func P_2) + { + if (P_0.Equals(P_1)) + { + return; + } + Symbol[] array = GetSymbolsChainRecursive(P_1, P_2).ToArray(); + if (!array.Any((Symbol symbol2) => symbol2.Equals(P_0))) + { + return; + } + StringBuilder stringBuilder = new StringBuilder(P_0.Name); + Symbol[] array2 = array; + foreach (Symbol symbol in array2) + { + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(symbol.Name); + if (symbol.Equals(P_0)) + { + break; + } + } + string text = stringBuilder.ToString(); + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + + public IEnumerable GetSymbolsChainRecursive(Symbol mappedSymbol, Func getMappedSymbolFromMap) + { + yield return mappedSymbol; + SymbolMap symbolMap = ?(mappedSymbol); + if (symbolMap == null) + { + yield break; + } + Symbol symbol = getMappedSymbolFromMap(symbolMap.GetState()); + if (mappedSymbol.Equals(symbol)) + { + yield break; + } + foreach (Symbol item in GetSymbolsChainRecursive(symbol, getMappedSymbolFromMap)) + { + yield return item; + } + } + + private void ?(SymbolMap P_0) + { + ???.Invoke(this, new SymbolsMappingEventArgs(P_0)); + } + + private void ?(SymbolMap P_0) + { + ???.Invoke(this, new SymbolsMappingEventArgs(P_0)); + } + + private void ?(SymbolMap P_0, SymbolMapState P_1) + { + ???.Invoke(this, new SymbolsMappingEventArgs(P_0, P_1)); + } + + private void ?(SymbolMap P_0) + { + ???.Invoke(this, new SymbolsMappingEventArgs(P_0)); + } + + private void ?(SymbolMap P_0) + { + ???.Invoke(this, new SymbolsMappingEventArgs(P_0)); + } + } + public class AdvancedTradingOperations + { + private class ? + { + [CompilerGenerated] + private readonly Position ??; + + [CompilerGenerated] + private readonly IList ??; + + [CompilerGenerated] + private readonly SlTpHolder ??; + + public Position Position + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = position; + } + } + + public IList Brackets + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = list; + } + } + + public SlTpHolder InitialBracketParameters + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = slTpHolder; + } + } + } + + private class ?(Symbol, Account) : IEquatable + { + [CompilerGenerated] + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Account ??; + + [CompilerGenerated] + protected virtual Type EqualityContract + { + [CompilerGenerated] + get + { + return typeof(?); + } + } + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return P_0; + } + [CompilerGenerated] + init + { + P_0 = symbol; + } + } + + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = account; + } + } + + public ?(Symbol P_0, Account P_1) + { + ?? = P_0; + ?? = P_1; + base..ctor(); + } + + [CompilerGenerated] + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (?(stringBuilder)) + { + stringBuilder.Append(' '); + } + stringBuilder.Append('}'); + return stringBuilder.ToString(); + } + + [CompilerGenerated] + protected virtual bool ?(StringBuilder P_0) + { + RuntimeHelpers.EnsureSufficientExecutionStack(); + P_0.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + P_0.Append(Symbol); + P_0.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + P_0.Append(Account); + return true; + } + + [CompilerGenerated] + public static bool operator !=(?? P_0, ?? P_1) + { + return !(P_0 == P_1); + } + + [CompilerGenerated] + public static bool operator ==(?? P_0, ?? P_1) + { + if ((object)P_0 != P_1) + { + return P_0?.Equals(P_1) ?? false; + } + return true; + } + + [CompilerGenerated] + public override int GetHashCode() + { + return (EqualityComparer.Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer.Default.GetHashCode(P_0)) * -1521134295 + EqualityComparer.Default.GetHashCode(??); + } + + [CompilerGenerated] + public override bool Equals(object? obj) + { + return Equals(obj as ?); + } + + [CompilerGenerated] + public virtual bool Equals(?? other) + { + if ((object)this != other) + { + if ((object)other != null && EqualityContract == other.EqualityContract && EqualityComparer.Default.Equals(P_0, other.P_0)) + { + return EqualityComparer.Default.Equals(??, other.??); + } + return false; + } + return true; + } + + [CompilerGenerated] + public virtual ? ?() + { + return new ?(this); + } + + [CompilerGenerated] + protected ?(? original) + { + ?? = original.??; + ?? = original.??; + } + + [CompilerGenerated] + public void ?(out Symbol P_0, out Account P_1) + { + P_0 = Symbol; + P_1 = Account; + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal Symbol ?(IOrder P_0) + { + return P_0.Symbol; + } + + internal IOrder ?(IOrder P_0) + { + return P_0; + } + + internal Connection ?(IOrder P_0) + { + return P_0.Symbol.Connection; + } + + internal Symbol ?(IOrder P_0) + { + return P_0.Symbol; + } + + internal Account ?(IOrder P_0) + { + return P_0.Account; + } + + internal ? ?(IOrder P_0) + { + return new ?(P_0.Symbol, P_0.Account); + } + + internal string ?(IOrder P_0) + { + return P_0.Id; + } + + internal bool ?(Position P_0) + { + return true; + } + + internal bool ?(Position P_0) + { + return true; + } + + internal bool ?(Position P_0) + { + return true; + } + + internal bool ?(Position P_0) + { + return true; + } + + internal bool ?(OrderType P_0) + { + if (P_0.Behavior == OrderTypeBehavior.Market) + { + return (P_0.Usage & OrderTypeUsage.Order) == OrderTypeUsage.Order; + } + return false; + } + + internal bool ?(Order P_0) + { + OrderTypeBehavior behavior = P_0.OrderType.Behavior; + if ((uint)(behavior - 3) <= 1u) + { + return true; + } + return false; + } + + internal bool ?(OrderType P_0) + { + return P_0.Behavior == OrderTypeBehavior.Stop; + } + + internal bool ?(Order P_0) + { + return string.IsNullOrEmpty(P_0.GroupId); + } + + internal string ?(Order P_0) + { + return P_0.GroupId; + } + + internal bool ?(Order P_0) + { + return string.IsNullOrEmpty(P_0.GroupId); + } + + internal string ?(Order P_0) + { + return P_0.GroupId; + } + + internal double ?(Order P_0) + { + return P_0.GetExecutionPrice(); + } + + internal bool ?(Order P_0) + { + return string.IsNullOrEmpty(P_0.GroupId); + } + + internal Order ?(Order P_0, Order P_1) + { + if (!(P_0.RemainingQuantity > P_1.RemainingQuantity)) + { + return P_1; + } + return P_0; + } + + internal bool ?(Order P_0) + { + return string.IsNullOrEmpty(P_0.GroupId); + } + + internal Order ?(Order P_0, Order P_1) + { + if (!(P_0.RemainingQuantity > P_1.RemainingQuantity)) + { + return P_1; + } + return P_0; + } + + internal double ?(Order P_0) + { + return P_0.GetExecutionPrice(); + } + + internal double ?(Order P_0) + { + return P_0.GetExecutionPrice(); + } + + internal (double, double) ?(Order P_0) + { + return (P_0.GetExecutionPrice(), P_0.RemainingQuantity); + } + + internal string ?(Order P_0) + { + return P_0.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + public TimeInForce ??; + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(??)) + { + return P_0.TimeInForce == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public TimeInForce ??; + + internal bool ?(IOrder P_0) + { + return P_0.TimeInForce == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public OrderTypeBehavior ??; + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol)) + { + return P_0.OrderType.Behavior == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + public OrderTypeBehavior ??; + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(??)) + { + return P_0.OrderType.Behavior == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public OrderTypeBehavior ??; + + internal bool ?(IOrder P_0) + { + return P_0.OrderType.Behavior == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Connection ??; + + internal bool ?(IOrder P_0) + { + return P_0.ConnectionId == ??.Id; + } + + internal bool ?(IOrder P_0) + { + return P_0.ConnectionId == ??.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(IOrder P_0) + { + return ??.IsSameAs(P_0.Symbol); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + internal bool ?(Order P_0) + { + if (P_0.Symbol.Equals(??)) + { + return P_0.Account.Equals(??); + } + return false; + } + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol)) + { + return P_0.Account.Equals(??); + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Func ??; + + public Func ??; + + internal bool ?(IOrder P_0) + { + if (?? != null) + { + return ??(P_0); + } + return true; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Account ??; + + internal bool ?(Position P_0) + { + return P_0.Account.Equals(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Side ??; + + internal bool ?(Position P_0) + { + return P_0.Side == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Side ??; + + internal bool ?(Position P_0) + { + if (??.IsSameAs(P_0.Symbol)) + { + return P_0.Side == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(Position P_0) + { + return ??.IsSameAs(P_0.Symbol); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(Position P_0) + { + return ??.IsSameAs(P_0.Symbol); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(Position P_0) + { + return ??.IsSameAs(P_0.Symbol); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + internal bool ?(Position P_0) + { + if (??.IsSameAs(P_0.Symbol)) + { + return P_0.Account.Equals(??); + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Func ??; + + internal bool ?(Position P_0) + { + PnLItem pnLItem = P_0.NetPnL ?? P_0.GrossPnL; + if (pnLItem != null && pnLItem.Value > 0.0) + { + if (?? != null) + { + return ??(P_0); + } + return true; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Func ??; + + internal bool ?(Position P_0) + { + PnLItem pnLItem = P_0.NetPnL ?? P_0.GrossPnL; + if (pnLItem != null && pnLItem.Value < 0.0) + { + if (?? != null) + { + return ??(P_0); + } + return true; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Func ??; + + public Func ??; + + internal bool ?(Position P_0) + { + if (?? != null) + { + return ??(P_0); + } + return true; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + internal bool ?(Position P_0) + { + return P_0.Symbol.IsSameAs(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Account ??; + + internal bool ?(Position P_0) + { + return P_0.Account.Equals(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + internal bool ?(Position P_0) + { + if (P_0.Symbol.IsSameAs(??)) + { + return P_0.Account.Equals(??); + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + public Func ??; + + public Func ??; + + internal bool ?(Order P_0) + { + if (P_0.Symbol.Equals(??)) + { + return P_0.Account.Equals(??); + } + return false; + } + + internal bool ?(Order P_0) + { + return P_0.Symbol.Equals(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Position ??; + + internal bool ?(Order P_0) + { + return P_0.PositionId == ??.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Account ??; + + internal bool ?(IOrder P_0) + { + return P_0.Account.Equals(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + public Position ??; + + internal bool ?(Position P_0) + { + if (P_0.ConnectionId == ??.ConnectionId && ??.IsSameAs(P_0.Symbol)) + { + return P_0.Account.Id == ??.Id; + } + return false; + } + + internal bool ?(Order P_0) + { + if (P_0.ConnectionId == ??.ConnectionId && ??.IsSameAs(P_0.Symbol)) + { + return P_0.Account.Id == ??.Id; + } + return false; + } + + internal bool ?(Order P_0) + { + if (P_0.OrderType.Behavior == OrderTypeBehavior.Stop) + { + return P_0.Side != ??.Side; + } + return false; + } + + internal bool ?(Order P_0) + { + if (P_0.OrderType.Behavior == OrderTypeBehavior.Stop) + { + return P_0.Side != ??.Side; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public TaskCompletionSource ??; + + internal void ?(OrderHistory P_0) + { + OrderStatus status = P_0.Status; + if ((status == OrderStatus.Opened || status == OrderStatus.Refused) ? true : false) + { + ??.SetResult(P_0); + } + } + + internal void ?() + { + ??.TrySetCanceled(); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Position ??; + + internal bool ?(Order P_0) + { + if (??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(??.Account) && P_0.Side != ??.Side) + { + if (P_0.Side != Side.Buy) + { + return P_0.GetExecutionPrice() < ??.OpenPrice; + } + return P_0.GetExecutionPrice() > ??.OpenPrice; + } + return false; + } + + internal bool ?(Order P_0) + { + if (??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(??.Account) && P_0.Side != ??.Side) + { + if (P_0.Side != Side.Buy) + { + return P_0.GetExecutionPrice() > ??.OpenPrice; + } + return P_0.GetExecutionPrice() < ??.OpenPrice; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Order ??; + + internal bool ?(Order P_0) + { + return P_0.OrderTypeId != ??.OrderTypeId; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Order ??; + + internal bool ?(Order P_0) + { + return P_0.Id != ??.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Order ??; + + internal bool ?(Order P_0) + { + return P_0.Id != ??.Id; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ManualResetEventSlim ??; + + public string ??; + + public PlaceOrderRequestParameters ??; + + internal void ?(Order P_0) + { + if (!??.IsSet) + { + if (!string.IsNullOrEmpty(??) && P_0.Id == ??) + { + ??.Set(); + } + else if (??.IsCorrespondingOrder(P_0)) + { + ??.Set(); + } + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public ManualResetEventSlim ??; + + public ModifyOrderRequestParameters ??; + + internal void ?(Order P_0) + { + if (!??.IsSet && ??.IsCorrespondingOrder(P_0)) + { + ??.Set(); + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public HashSet ??; + + public ManualResetEvent ??; + + internal void ?(Order P_0) + { + ??.Remove(P_0.Id); + if (??.Count == 0) + { + ??.Set(); + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Side ??; + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol)) + { + return P_0.Side == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public Account ??; + + public Side ??; + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(??)) + { + return P_0.Side == ??; + } + return false; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Side ??; + + internal bool ?(IOrder P_0) + { + return P_0.Side == ??; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Symbol ??; + + public TimeInForce ??; + + internal bool ?(IOrder P_0) + { + if (??.IsSameAs(P_0.Symbol)) + { + return P_0.TimeInForce == ??; + } + return false; + } + } + + internal AdvancedTradingOperations() + { + } + + /// + /// Cancel all pending s + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders([CallerMemberName] string sendingSource = null) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + sendingSource); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.None); + return ?(sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s + /// + /// s to cancel + /// the name of the initiator of the call (optional) + /// + public AdvancedTradingOperationResult CancelOrders(IOrder[] orders, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(67, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(orders.Length); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.CertainOrders); + foreach (IGrouping item in from P_0 in orders + group P_0 by P_0.Symbol) + { + Symbol key = item.Key; + IOrder[] array = item.ToArray(); + advancedTradingOperationResult.?(?(key, array, sendingSource, groupTradingOperation)); + } + return advancedTradingOperationResult; + } + + /// + /// Cancel all pending s by + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(62, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol); + return ?(symbol, Array.Empty(), sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(63, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Account); + return ?((IOrder P_0) => P_0.Account.Equals(account), sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account); + return ?(symbol, account, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, Side side, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(71, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Side); + return ?((IOrder P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.Side == side, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by , and + /// + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, Account account, Side side, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(83, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account | GroupTradingOperationFilters.Side); + return ?((IOrder P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.Account.Equals(account) && P_0.Side == side, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Side side, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(60, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Side); + return ?((IOrder P_0) => P_0.Side == side, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, TimeInForce timeInForce, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(80, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(timeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.TimeInForce); + return ?((IOrder P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.TimeInForce == timeInForce, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by , and + /// + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, Account account, TimeInForce timeInForce, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(92, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(timeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account | GroupTradingOperationFilters.TimeInForce); + return ?((IOrder P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.Account.Equals(account) && P_0.TimeInForce == timeInForce, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(TimeInForce timeInForce, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(69, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(timeInForce); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.TimeInForce); + return ?((IOrder P_0) => P_0.TimeInForce == timeInForce, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, OrderTypeBehavior orderTypeBehavior, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(77, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(orderTypeBehavior); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.OrderType); + return ?((IOrder P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.OrderType.Behavior == orderTypeBehavior, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by , and + /// + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(Symbol symbol, Account account, OrderTypeBehavior orderTypeBehavior, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(98, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(orderTypeBehavior); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account | GroupTradingOperationFilters.OrderType); + return ?((IOrder P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.Account.Equals(account) && P_0.OrderType.Behavior == orderTypeBehavior, sendingSource, groupTradingOperation); + } + + /// + /// Cancel all pending s by + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult CancelOrders(OrderTypeBehavior orderTypeBehavior, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(75, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(orderTypeBehavior); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.OrderType); + return ?((IOrder P_0) => P_0.OrderType.Behavior == orderTypeBehavior, sendingSource, groupTradingOperation); + } + + private static AdvancedTradingOperationResult ?(string P_0, GroupTradingOperation P_1) + { + Connection[] array = (from order in ?() + select order.Symbol.Connection).Distinct().ToArray(); + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + Connection[] array2 = array; + foreach (Connection connection in array2) + { + advancedTradingOperationResult.?(?(connection, P_0, P_1)); + } + return advancedTradingOperationResult; + } + + private static AdvancedTradingOperationResult ?(Connection P_0, string P_1, GroupTradingOperation P_2 = null) + { + bool flag = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Id).Status == TradingOperationStatus.Allowed; + bool flag2 = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Id).Status == TradingOperationStatus.Allowed; + bool flag3 = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Id).Status == TradingOperationStatus.Allowed; + IOrder[] source = (from order in ?() + where order.ConnectionId == P_0.Id + select order).ToArray(); + Symbol[] array = source.Select((IOrder order) => order.Symbol).Distinct().ToArray(); + Account[] array2 = source.Select((IOrder order) => order.Account).Distinct().ToArray(); + if (flag && (!flag2 || array.Length <= array2.Length)) + { + Symbol[] array3 = array; + foreach (Symbol symbol in array3) + { + P_0.SendCustomRequest(new CancelAllOpenOrdersOnSymbolRequest(symbol.ComplexId) + { + ParentOperation = P_2, + SendingSource = P_1 + }); + } + return AdvancedTradingOperationResult.?(); + } + if (flag2 && (!flag || array.Length > array2.Length)) + { + Account[] array4 = array2; + foreach (Account account in array4) + { + P_0.SendCustomRequest(new CancelAllOpenOrdersOnAccountRequest(account.Id) + { + ParentOperation = P_2, + SendingSource = P_1 + }); + } + return AdvancedTradingOperationResult.?(); + } + if (flag3) + { + ?[] array5 = source.Select((IOrder order) => new ?(order.Symbol, order.Account)).Distinct().ToArray(); + foreach (? ? in array5) + { + P_0.SendCustomRequest(new CancelAllOpenOrdersOnSymbolAndAccountRequest(?.Symbol.ComplexId, ?.Account.Id) + { + ParentOperation = P_2, + SendingSource = P_1 + }); + } + return AdvancedTradingOperationResult.?(); + } + if ((object)P_2 == null) + { + P_2 = new GroupTradingOperation(GroupTradingOperationType.CancelOrders, GroupTradingOperationFilters.Connection); + } + return ?((IOrder order) => order.ConnectionId == P_0.Id, P_1, P_2); + } + + private static AdvancedTradingOperationResult ?(Symbol P_0, IOrder[] P_1, string P_2, GroupTradingOperation P_3) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0).Status == TradingOperationStatus.Allowed) + { + P_0.Connection.SendCustomRequest(new CancelAllOpenOrdersOnSymbolRequest(P_0.ComplexId, P_1?.Select((IOrder order) => order.Id).ToArray()) + { + ParentOperation = P_3, + SendingSource = P_2 + }); + return AdvancedTradingOperationResult.?(); + } + if (P_1 == null || P_1.Length == 0) + { + return ?((IOrder order) => P_0.IsSameAs(order.Symbol), P_2, P_3); + } + return ?(((IEnumerable)P_1).Contains, P_2, P_3); + } + + private static AdvancedTradingOperationResult ?(Symbol P_0, Account P_1, string P_2, GroupTradingOperation P_3) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (P_1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_1, P_0).Status == TradingOperationStatus.Allowed && Core.Instance.Orders.Any((Order order) => order.Symbol.Equals(P_0) && order.Account.Equals(P_1))) + { + P_0.Connection.SendCustomRequest(new CancelAllOpenOrdersOnSymbolAndAccountRequest(P_0.ComplexId, P_1.Id) + { + ParentOperation = P_3, + SendingSource = P_2 + }); + return AdvancedTradingOperationResult.?(); + } + return ?((IOrder order) => P_0.IsSameAs(order.Symbol) && order.Account.Equals(P_1), P_2, P_3); + } + + private static AdvancedTradingOperationResult ?(Func P_0, string P_1, GroupTradingOperation P_2) + { + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + foreach (IOrder item in from arg in ?() + where P_0 == null || P_0(arg) + select arg) + { + CancelOrderRequestParameters cancelOrderRequestParameters = new CancelOrderRequestParameters + { + Order = item, + SendingSource = P_1, + ParentOperation = P_2 + }; + item.Symbol.Connection.Limitation?.Wait(cancelOrderRequestParameters.Type, cancelOrderRequestParameters.CancellationToken); + TradingOperationResult tradingOperationResult = Core.Instance.CancelOrder(cancelOrderRequestParameters); + advancedTradingOperationResult.?(cancelOrderRequestParameters, tradingOperationResult); + } + return advancedTradingOperationResult; + } + + private static IEnumerable ?() + { + return Core.Instance.Orders.OfType().Concat(Core.Instance.LocalOrders); + } + + /// + /// Close all s + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositions([CallerMemberName] string sendingSource = null) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + sendingSource); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.None); + return ?(sendingSource, groupTradingOperation); + } + + /// + /// Close all s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositions(Symbol symbol, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(64, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Symbol); + return ?(symbol, sendingSource, groupTradingOperation); + } + + /// + /// Close all s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositions(Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(65, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Account); + return ?((Position P_0) => P_0.Account.Equals(account), sendingSource, groupTradingOperation); + } + + /// + /// Close all s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositions(Symbol symbol, Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(76, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account); + return ?(symbol, account, sendingSource, groupTradingOperation); + } + + /// + /// Close all s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositions(Side side, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(62, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Side); + return ?((Position P_0) => P_0.Side == side, sendingSource, groupTradingOperation); + } + + /// + /// Close all s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositions(Symbol symbol, Side side, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(73, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Side); + return ?((Position P_0) => symbol.IsSameAs(P_0.Symbol) && P_0.Side == side, sendingSource, groupTradingOperation); + } + + /// + /// Close all positive s + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositivePositions([CallerMemberName] string sendingSource = null) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + sendingSource); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.None); + return ?((Position P_0) => true, sendingSource, groupTradingOperation); + } + + /// + /// Close all positive s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ClosePositivePositions(Symbol symbol, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(73, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Symbol); + return ?((Position P_0) => symbol.IsSameAs(P_0.Symbol), sendingSource, groupTradingOperation); + } + + /// + /// Close all negative s + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult CloseNegativePositions([CallerMemberName] string sendingSource = null) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + sendingSource); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.None); + return ?((Position P_0) => true, sendingSource, groupTradingOperation); + } + + /// + /// Close all negative s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult CloseNegativePositions(Symbol symbol, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(73, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ClosePositions, GroupTradingOperationFilters.Symbol); + return ?((Position P_0) => symbol.IsSameAs(P_0.Symbol), sendingSource, groupTradingOperation); + } + + private static AdvancedTradingOperationResult ?(Symbol P_0, string P_1, GroupTradingOperation P_2) + { + return ?((Position position) => P_0.IsSameAs(position.Symbol), P_1, P_2); + } + + private static AdvancedTradingOperationResult ?(Symbol P_0, Account P_1, string P_2, GroupTradingOperation P_3) + { + return ?((Position position) => P_0.IsSameAs(position.Symbol) && position.Account.Equals(P_1), P_2, P_3); + } + + private static AdvancedTradingOperationResult ?(string P_0, GroupTradingOperation P_1) + { + return ?((Position position) => true, P_0, P_1); + } + + private static AdvancedTradingOperationResult ?(Func P_0, string P_1, GroupTradingOperation P_2) + { + return ?(delegate(Position position) + { + PnLItem pnLItem = position.NetPnL ?? position.GrossPnL; + return pnLItem != null && pnLItem.Value > 0.0 && (P_0 == null || P_0(position)); + }, P_1, P_2); + } + + private static AdvancedTradingOperationResult ?(Func P_0, string P_1, GroupTradingOperation P_2) + { + return ?(delegate(Position position) + { + PnLItem pnLItem = position.NetPnL ?? position.GrossPnL; + return pnLItem != null && pnLItem.Value < 0.0 && (P_0 == null || P_0(position)); + }, P_1, P_2); + } + + private static AdvancedTradingOperationResult ?(Func P_0, string P_1, GroupTradingOperation P_2) + { + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + foreach (Position item in Core.Instance.Positions.Where((Position arg) => P_0 == null || P_0(arg))) + { + ClosePositionRequestParameters closePositionRequestParameters = new ClosePositionRequestParameters + { + Position = item, + CloseQuantity = item.Quantity, + SendingSource = P_1, + ParentOperation = P_2 + }; + TradingOperationResult tradingOperationResult = Core.Instance.ClosePosition(closePositionRequestParameters); + advancedTradingOperationResult.?(closePositionRequestParameters, tradingOperationResult); + } + return advancedTradingOperationResult; + } + + /// + /// Reverse all s + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ReversePositions([CallerMemberName] string sendingSource = null) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + sendingSource); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ReversePositions, GroupTradingOperationFilters.None); + return ?((Position P_0) => true, sendingSource, groupTradingOperation); + } + + /// + /// Reverse all s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ReversePositions(Symbol symbol, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(66, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ReversePositions, GroupTradingOperationFilters.Symbol); + return ?((Position P_0) => P_0.Symbol.IsSameAs(symbol), sendingSource, groupTradingOperation); + } + + /// + /// Reverse all s by + /// + /// + /// the name of the initiator of the call (optional) + /// List of + public AdvancedTradingOperationResult ReversePositions(Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(67, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ReversePositions, GroupTradingOperationFilters.Account); + return ?((Position P_0) => P_0.Account.Equals(account), sendingSource, groupTradingOperation); + } + + /// + /// Reverse by and + /// + /// + /// + /// the name of the initiator of the call (optional) + /// + public AdvancedTradingOperationResult ReversePosition(Symbol symbol, Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(78, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.ReversePositions, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account); + return ?((Position P_0) => P_0.Symbol.IsSameAs(symbol) && P_0.Account.Equals(account), sendingSource, groupTradingOperation); + } + + private static AdvancedTradingOperationResult ?(Func P_0, string P_1, GroupTradingOperation P_2) + { + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + try + { + Position[] positions = Core.Instance.Positions; + foreach (Position position in positions) + { + if ((position.Symbol.NettingType == NettingType.OnePosition || position.Symbol.NettingType == NettingType.Undefined || position.Account.NettingType == NettingType.OnePosition) && (P_0 == null || P_0(position))) + { + OrderType orderType = (Core.Instance.Connections[position.ConnectionId]?.BusinessObjects?.OrderTypes)?.FirstOrDefault((OrderType orderType2) => orderType2.Behavior == OrderTypeBehavior.Market && (orderType2.Usage & OrderTypeUsage.Order) == OrderTypeUsage.Order); + if (orderType != null) + { + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters + { + Account = position.Account, + Symbol = position.Symbol, + OrderTypeId = orderType.Id, + Quantity = position.Quantity * 2.0, + TimeInForce = TimeInForce.Default, + Side = ((position.Side == Side.Buy) ? Side.Sell : Side.Buy), + SendingSource = P_1, + ParentOperation = P_2 + }; + TradingOperationResult tradingOperationResult = Core.Instance.PlaceOrder(placeOrderRequestParameters); + advancedTradingOperationResult.?(placeOrderRequestParameters, tradingOperationResult); + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return advancedTradingOperationResult; + } + + /// + /// Cancel all s and close all s + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult Flatten([CallerMemberName] string sendingSource = null) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + sendingSource); + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.Flatten, GroupTradingOperationFilters.None); + advancedTradingOperationResult.?(?(sendingSource, groupTradingOperation)); + ?((Symbol)null, (Account)null); + advancedTradingOperationResult.?(?(sendingSource, groupTradingOperation)); + return advancedTradingOperationResult; + } + + /// + /// Cancel all s and close all s by + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult Flatten(Symbol symbol, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(56, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.Flatten, GroupTradingOperationFilters.Symbol); + advancedTradingOperationResult.?(?(symbol, Array.Empty(), sendingSource, groupTradingOperation)); + ?(symbol); + advancedTradingOperationResult.?(?(symbol, sendingSource, groupTradingOperation)); + return advancedTradingOperationResult; + } + + /// + /// Cancel all s and close all s by and + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult Flatten(Symbol symbol, Account account, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(68, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(account); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + GroupTradingOperation groupTradingOperation = new GroupTradingOperation(GroupTradingOperationType.Flatten, GroupTradingOperationFilters.Symbol | GroupTradingOperationFilters.Account); + advancedTradingOperationResult.?(?(symbol, account, sendingSource, groupTradingOperation)); + ?(symbol, account); + advancedTradingOperationResult.?(?(symbol, account, sendingSource, groupTradingOperation)); + return advancedTradingOperationResult; + } + + private static void ?(Symbol P_0 = null, Account P_1 = null) + { + try + { + CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5.0)); + while (!cancellationTokenSource.IsCancellationRequested && ((P_0 != null && P_1 != null) ? Core.Instance.Orders.Count((Order order) => order.Symbol.Equals(P_0) && order.Account.Equals(P_1)) : ((P_0 == null) ? Core.Instance.Orders.Length : Core.Instance.Orders.Count((Order order) => order.Symbol.Equals(P_0)))) != 0) + { + Task.Delay(50, cancellationTokenSource.Token).Wait(cancellationTokenSource.Token); + } + if (cancellationTokenSource.IsCancellationRequested) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + /// + /// Modify SL to breakeven price + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult BreakEven(Position position, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(60, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(position); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return ?(position, 0, null, sendingSource); + } + + /// + /// Modify SL to breakeven price with certain additional offset + /// + /// + /// offset in ticks + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult BreakEven(Position position, int offset, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(71, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(position); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(offset); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return ?(position, offset, null, sendingSource); + } + + /// + /// Modify SL to breakeven price + /// + /// + /// list of s that will be used for order placing + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult BreakEven(Position position, IList additionalParameters, [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(92, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(position); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(additionalParameters?.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return ?(position, 0, additionalParameters, sendingSource); + } + + private static AdvancedTradingOperationResult ?(Position P_0, int P_1, IList P_2, string P_3) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.Symbol.NettingType == NettingType.OnePosition || P_0.Account.NettingType == NettingType.OnePosition) + { + return ?(P_0.Symbol, P_0.Account, P_1, P_2, P_3); + } + double num = ?(P_0, P_1); + double currentPrice = P_0.CurrentPrice; + Order order = Core.Instance.Orders.Where((Order order2) => order2.PositionId == P_0.Id).FirstOrDefault(delegate(Order order2) + { + OrderTypeBehavior behavior = order2.OrderType.Behavior; + return (uint)(behavior - 3) <= 1u; + }); + if (order == null) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ModifyOrderRequestParameters modifyOrderRequestParameters = new ModifyOrderRequestParameters(order); + if (order.OrderType.Behavior == OrderTypeBehavior.TrailingStop) + { + num = P_0.Symbol.CalculateTicks(currentPrice, num); + modifyOrderRequestParameters.TrailOffset = num; + } + else + { + modifyOrderRequestParameters.TriggerPrice = num; + } + modifyOrderRequestParameters.SendingSource = P_3; + TradingOperationResult tradingOperationResult = Core.Instance.ModifyOrder(modifyOrderRequestParameters); + return new AdvancedTradingOperationResult(modifyOrderRequestParameters, tradingOperationResult); + } + + private static AdvancedTradingOperationResult ?(Symbol P_0, Account P_1, int P_2, IList P_3, string P_4) + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (P_1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + if (P_0.NettingType != NettingType.OnePosition && P_1.NettingType != NettingType.OnePosition) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + OrderType orderType = P_0.Connection.BusinessObjects.OrderTypes.FirstOrDefault((OrderType orderType2) => orderType2.Behavior == OrderTypeBehavior.Stop); + if (orderType == null) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Position ?? = Core.Instance.Positions.FirstOrDefault((Position position) => position.ConnectionId == P_0.ConnectionId && P_0.IsSameAs(position.Symbol) && position.Account.Id == P_1.Id); + if (?? == null) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + try + { + Order[] array = Core.Instance.Orders.Where((Order order3) => order3.ConnectionId == P_0.ConnectionId && P_0.IsSameAs(order3.Symbol) && order3.Account.Id == P_1.Id).ToArray(); + Order order = array.FirstOrDefault((Order order3) => order3.OrderType.Behavior == OrderTypeBehavior.Stop && order3.Side != ??.Side); + if (order != null && !array.Any((Order order3) => string.IsNullOrEmpty(order3.GroupId)) && (from order3 in array + group order3 by order3.GroupId).Count() == 1) + { + ModifyOrderRequestParameters modifyOrderRequestParameters = new ModifyOrderRequestParameters(order) + { + TriggerPrice = ?(??, P_2), + SendingSource = P_4 + }; + TradingOperationResult tradingOperationResult = Core.Instance.ModifyOrder(modifyOrderRequestParameters); + advancedTradingOperationResult.?(modifyOrderRequestParameters, tradingOperationResult); + } + else if (order != null && array.Count() % 2 == 0 && !array.Any((Order order3) => string.IsNullOrEmpty(order3.GroupId)) && (from order3 in array + group order3 by order3.GroupId).Count() * 2 == array.Count()) + { + Order[] array2 = array.Where((Order order3) => order3.OrderType.Behavior == OrderTypeBehavior.Stop && order3.Side != ??.Side).ToArray(); + for (int num = 0; num < array2.Length; num++) + { + ModifyOrderRequestParameters modifyOrderRequestParameters2 = new ModifyOrderRequestParameters(array2[num]) + { + TriggerPrice = ?(??, P_2), + SendingSource = P_4 + }; + TradingOperationResult tradingOperationResult2 = Core.Instance.ModifyOrder(modifyOrderRequestParameters2); + advancedTradingOperationResult.?(modifyOrderRequestParameters2, tradingOperationResult2); + } + } + else + { + TaskCompletionSource ?? = new TaskCompletionSource(); + CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + Action value = delegate(OrderHistory orderHistory) + { + OrderStatus status = orderHistory.Status; + if ((status == OrderStatus.Opened || status == OrderStatus.Refused) ? true : false) + { + ??.SetResult(orderHistory); + } + }; + Core.Instance.OrdersHistoryAdded += value; + cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(5.0)); + try + { + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters + { + Account = ??.Account, + Symbol = ??.Symbol, + OrderTypeId = orderType.Id, + TriggerPrice = ?(??, P_2), + Side = ((??.Side == Side.Buy) ? Side.Sell : Side.Buy), + Quantity = ??.Quantity, + SendingSource = P_4 + }; + if (P_3 != null) + { + placeOrderRequestParameters.AdditionalParameters = P_3; + } + TradingOperationResult tradingOperationResult3 = Core.Instance.PlaceOrder(placeOrderRequestParameters); + advancedTradingOperationResult.?(placeOrderRequestParameters, tradingOperationResult3); + if (tradingOperationResult3.Status == TradingOperationResultStatus.Failure) + { + return advancedTradingOperationResult; + } + CancellationToken token = cancellationTokenSource.Token; + token.Register(delegate + { + ??.TrySetCanceled(); + }); + OrderHistory result = ??.Task.Result; + if (token.IsCancellationRequested) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (result.Status == OrderStatus.Refused) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Order[] array2 = array; + foreach (Order order2 in array2) + { + CancelOrderRequestParameters cancelOrderRequestParameters = new CancelOrderRequestParameters + { + Order = order2, + SendingSource = P_4 + }; + TradingOperationResult tradingOperationResult4 = Core.Instance.CancelOrder(cancelOrderRequestParameters); + advancedTradingOperationResult.?(cancelOrderRequestParameters, tradingOperationResult4); + } + } + finally + { + Core.Instance.OrdersHistoryAdded -= value; + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return advancedTradingOperationResult; + } + + private static double ?(Position P_0, int P_1) + { + if (P_0 == null) + { + return double.NaN; + } + double num = P_0.OpenPrice; + decimal num2 = (decimal)P_0.Symbol.RoundPriceToTickSize(P_0.OpenPrice); + if ((decimal)P_0.OpenPrice != num2) + { + decimal num3 = ((!(num2 < (decimal)P_0.OpenPrice)) ? ((P_0.Side == Side.Buy) ? num2 : ((decimal)P_0.Symbol.CalculatePrice((double)num2, -1.0))) : ((P_0.Side == Side.Buy) ? ((decimal)P_0.Symbol.CalculatePrice((double)num2, 1.0)) : num2)); + num = (double)num3; + } + if (P_1 != 0) + { + num = P_0.Symbol.CalculatePrice(num, (P_0.Side == Side.Buy) ? P_1 : (-P_1)); + } + return num; + } + + /// + /// Adjust SL/TP for given + /// + /// + /// + /// the name of the initiator of the call (optional) + public AdvancedTradingOperationResult AdjustSlTp(Position position, CancellationToken cancellationToken = default(CancellationToken), [CallerMemberName] string sendingSource = null) + { + if (position == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Symbol ?? = position.Symbol; + List list = Core.Instance.Orders.Where((Order P_0) => ??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(position.Account) && P_0.Side != position.Side && ((P_0.Side != Side.Buy) ? (P_0.GetExecutionPrice() < position.OpenPrice) : (P_0.GetExecutionPrice() > position.OpenPrice))).ToList(); + List list2 = Core.Instance.Orders.Where((Order P_0) => ??.IsSameAs(P_0.Symbol) && P_0.Account.Equals(position.Account) && P_0.Side != position.Side && ((P_0.Side != Side.Buy) ? (P_0.GetExecutionPrice() > position.OpenPrice) : (P_0.GetExecutionPrice() < position.OpenPrice))).ToList(); + if (!list.Any() && !list2.Any()) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(63, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(position); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + AdvancedTradingOperationResult advancedTradingOperationResult = null; + AdvancedTradingOperationResult advancedTradingOperationResult2 = null; + AdvancedTradingOperationResult advancedTradingOperationResult3 = new AdvancedTradingOperationResult(); + try + { + if (list.Any()) + { + advancedTradingOperationResult = ?(new ? + { + Position = position, + Brackets = list + }, cancellationToken, sendingSource); + } + else if (list2.Count > 1) + { + List list3 = list2.OrderBy((Order P_0) => P_0.GetExecutionPrice()).ToList(); + Order ?? = ((position.Side == Side.Buy) ? list3.First() : list3.Last()); + list3.Remove(??); + if (list3.All((Order P_0) => P_0.OrderTypeId != ??.OrderTypeId)) + { + list2.Remove(??); + advancedTradingOperationResult = ?(new ? + { + Position = position, + Brackets = new List { ?? } + }, cancellationToken, sendingSource); + } + } + if (list2.Any()) + { + advancedTradingOperationResult2 = ?(new ? + { + Position = position, + Brackets = list2 + }, cancellationToken, sendingSource); + } + if (advancedTradingOperationResult == null) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (advancedTradingOperationResult2 == null) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + advancedTradingOperationResult3.?(advancedTradingOperationResult).?(advancedTradingOperationResult2); + if (!(advancedTradingOperationResult.Value is string orderId) || !(advancedTradingOperationResult2.Value is string orderId2) || Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), position.Account, position.Symbol).Status != TradingOperationStatus.Allowed) + { + return advancedTradingOperationResult3; + } + Order order = null; + Order order2 = null; + CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5.0)); + while ((order == null || order2 == null) && !cancellationTokenSource.IsCancellationRequested) + { + order = Core.Instance.GetOrderById(orderId, position.ConnectionId); + order2 = Core.Instance.GetOrderById(orderId2, position.ConnectionId); + Task.Delay(100, cancellationTokenSource.Token).Wait(cancellationTokenSource.Token); + } + if (order == null || order2 == null) + { + return advancedTradingOperationResult3; + } + Core instance = Core.Instance; + string connectionId = position.ConnectionId; + LinkOCORequestParameters linkOCORequestParameters = new LinkOCORequestParameters(); + int num = 2; + List list4 = new List(num); + CollectionsMarshal.SetCount(list4, num); + Span span = CollectionsMarshal.AsSpan(list4); + int num2 = 0; + span[num2] = order; + num2++; + span[num2] = order2; + linkOCORequestParameters.OrdersToLink = list4; + linkOCORequestParameters.CancellationToken = cancellationToken; + instance.SendCustomRequest(connectionId, linkOCORequestParameters); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return advancedTradingOperationResult3; + } + + /// + /// Adjust stop loss for given + /// + /// + /// list of s + /// initial stop loss parameters (optional) + /// + /// the name of the initiator of the call (optional) + /// + public AdvancedTradingOperationResult AdjustStopLoss(Position position, IList stops, SlTpHolder initialStopLoss = null, CancellationToken cancellationToken = default(CancellationToken), [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(97, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(position); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(stops.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(initialStopLoss); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return ?(new ? + { + Position = position, + Brackets = stops, + InitialBracketParameters = initialStopLoss + }, cancellationToken, sendingSource); + } + + /// + /// Adjust take profit for given + /// + /// + /// list of s + /// initial take profit parameters (optional) + /// + /// the name of the initiator of the call (optional) + /// + public AdvancedTradingOperationResult AdjustTakeProfit(Position position, IList takes, SlTpHolder initialTakeProfit, CancellationToken cancellationToken = default(CancellationToken), [CallerMemberName] string sendingSource = null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(101, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(position); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(takes.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(initialTakeProfit); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(sendingSource); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return ?(new ? + { + Position = position, + Brackets = takes, + InitialBracketParameters = initialTakeProfit + }, cancellationToken, sendingSource); + } + + private static AdvancedTradingOperationResult ?(? P_0, CancellationToken P_1, string P_2) + { + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + Position position = P_0.Position; + IList brackets = P_0.Brackets; + SlTpHolder initialBracketParameters = P_0.InitialBracketParameters; + double quantity = position.Quantity; + double num = ?(position, brackets, initialBracketParameters); + List source = brackets.Where((Order order) => string.IsNullOrEmpty(order.GroupId)).ToList(); + if (source.Any()) + { + Order ?? = source.Aggregate((Order order, Order order2) => (!(order.RemainingQuantity > order2.RemainingQuantity)) ? order2 : order); + advancedTradingOperationResult.?(?(brackets.Where((Order order) => order.Id != ??.Id).ToList(), P_1, P_2)); + if (Math.Abs(??.RemainingQuantity - quantity) > double.Epsilon || Math.Abs(??.GetExecutionPrice() - num) > double.Epsilon) + { + ModifyOrderRequestParameters modifyOrderRequestParameters = new ModifyOrderRequestParameters(??) + { + Quantity = quantity, + CancellationToken = P_1, + SendingSource = P_2 + }; + modifyOrderRequestParameters.SetExecutionPrice(num); + TradingOperationResult tradingOperationResult = ?(modifyOrderRequestParameters); + advancedTradingOperationResult.?(modifyOrderRequestParameters, tradingOperationResult); + if (tradingOperationResult.Status != TradingOperationResultStatus.Success) + { + return advancedTradingOperationResult; + } + advancedTradingOperationResult.Value = tradingOperationResult.OrderId; + } + else + { + advancedTradingOperationResult.Value = ??.Id; + } + } + else + { + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters(brackets.FirstOrDefault()) + { + Quantity = quantity, + CancellationToken = P_1, + GroupId = string.Empty, + SendingSource = P_2 + }; + advancedTradingOperationResult.?(?(brackets, P_1, P_2)); + placeOrderRequestParameters.SetExecutionPrice(num); + TradingOperationResult tradingOperationResult2 = ?(placeOrderRequestParameters); + if (tradingOperationResult2.Status != TradingOperationResultStatus.Success) + { + return advancedTradingOperationResult; + } + advancedTradingOperationResult.?(placeOrderRequestParameters, tradingOperationResult2); + advancedTradingOperationResult.Value = tradingOperationResult2.OrderId; + } + return advancedTradingOperationResult; + } + + private static AdvancedTradingOperationResult ?(? P_0, CancellationToken P_1, string P_2) + { + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + Position position = P_0.Position; + IList brackets = P_0.Brackets; + SlTpHolder initialBracketParameters = P_0.InitialBracketParameters; + double quantity = position.Quantity; + double num = ?(position, brackets, initialBracketParameters); + if (double.IsNaN(num)) + { + return AdvancedTradingOperationResult.?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + List source = brackets.Where((Order order) => string.IsNullOrEmpty(order.GroupId)).ToList(); + if (source.Any()) + { + Order ?? = source.Aggregate((Order order, Order order2) => (!(order.RemainingQuantity > order2.RemainingQuantity)) ? order2 : order); + advancedTradingOperationResult.?(?(brackets.Where((Order order) => order.Id != ??.Id).ToList(), P_1, P_2)); + if (Math.Abs(??.RemainingQuantity - quantity) > double.Epsilon || Math.Abs(??.GetExecutionPrice() - num) > double.Epsilon) + { + ModifyOrderRequestParameters modifyOrderRequestParameters = new ModifyOrderRequestParameters(??) + { + Quantity = quantity, + CancellationToken = P_1, + SendingSource = P_2 + }; + modifyOrderRequestParameters.SetExecutionPrice(num); + TradingOperationResult tradingOperationResult = ?(modifyOrderRequestParameters); + advancedTradingOperationResult.?(modifyOrderRequestParameters, tradingOperationResult); + if (tradingOperationResult.Status != TradingOperationResultStatus.Success) + { + return advancedTradingOperationResult; + } + advancedTradingOperationResult.Value = tradingOperationResult.OrderId; + } + else + { + advancedTradingOperationResult.Value = ??.Id; + } + } + else + { + PlaceOrderRequestParameters placeOrderRequestParameters = new PlaceOrderRequestParameters(brackets.FirstOrDefault()) + { + Quantity = quantity, + CancellationToken = P_1, + GroupId = string.Empty, + SendingSource = P_2 + }; + advancedTradingOperationResult.?(?(brackets, P_1, P_2)); + placeOrderRequestParameters.SetExecutionPrice(num); + TradingOperationResult tradingOperationResult2 = ?(placeOrderRequestParameters); + advancedTradingOperationResult.?(placeOrderRequestParameters, tradingOperationResult2); + if (tradingOperationResult2.Status != TradingOperationResultStatus.Success) + { + return advancedTradingOperationResult; + } + advancedTradingOperationResult.Value = tradingOperationResult2.OrderId; + } + return advancedTradingOperationResult; + } + + private static double ?(Position P_0, IEnumerable P_1, SlTpHolder P_2 = null) + { + if (P_2 != null) + { + if (P_2.PriceMeasurement != PriceMeasurement.Absolute) + { + return P_0.Symbol.RoundPriceToTickSize(P_0.Symbol.CalculatePrice(P_0.OpenPrice, (double)((P_0.Side != Side.Buy) ? 1 : (-1)) * P_2.Price)); + } + return P_2.Price; + } + if (P_0.Side != Side.Buy) + { + return P_1.Min((Order order) => order.GetExecutionPrice()); + } + return P_1.Max((Order order) => order.GetExecutionPrice()); + } + + private static double ?(Position P_0, IEnumerable P_1, SlTpHolder P_2 = null) + { + if (P_2 != null) + { + if (P_2.PriceMeasurement != PriceMeasurement.Absolute) + { + return P_0.Symbol.RoundPriceToTickSize(P_0.Symbol.CalculatePrice(P_0.OpenPrice, (double)((P_0.Side == Side.Buy) ? 1 : (-1)) * P_2.Price)); + } + return P_2.Price; + } + return CoreMath.GetWeightedAverage(P_1.Select((Order order) => (order.GetExecutionPrice(), order.RemainingQuantity)), P_0.Symbol); + } + + private static TradingOperationResult ?(PlaceOrderRequestParameters P_0) + { + ManualResetEventSlim ?? = new ManualResetEventSlim(); + string ?? = null; + try + { + Core.Instance.OrderAdded += delegate(Order order) + { + if (!??.IsSet) + { + if (!string.IsNullOrEmpty(??) && order.Id == ??) + { + ??.Set(); + } + else if (P_0.IsCorrespondingOrder(order)) + { + ??.Set(); + } + } + }; + Core.Instance.Connections[P_0.ConnectionId]?.Limitation?.Wait(P_0.Type, P_0.CancellationToken); + TradingOperationResult tradingOperationResult = Core.Instance.PlaceOrder(P_0); + if (tradingOperationResult != null && tradingOperationResult.Status == TradingOperationResultStatus.Failure) + { + return tradingOperationResult; + } + ?? = tradingOperationResult.OrderId; + ??.Wait(TimeSpan.FromSeconds(5.0)); + return tradingOperationResult; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + Core.Instance.OrderAdded -= delegate(Order order) + { + if (!??.IsSet) + { + if (!string.IsNullOrEmpty(??) && order.Id == ??) + { + ??.Set(); + } + else if (P_0.IsCorrespondingOrder(order)) + { + ??.Set(); + } + } + }; + } + return null; + } + + private static TradingOperationResult ?(ModifyOrderRequestParameters P_0) + { + ManualResetEventSlim ?? = new ManualResetEventSlim(); + try + { + Core.Instance.OrderAdded += delegate(Order order) + { + if (!??.IsSet && P_0.IsCorrespondingOrder(order)) + { + ??.Set(); + } + }; + Core.Instance.Connections[P_0.ConnectionId]?.Limitation?.Wait(P_0.Type, P_0.CancellationToken); + TradingOperationResult tradingOperationResult = Core.Instance.ModifyOrder(P_0); + if (tradingOperationResult != null && tradingOperationResult.Status == TradingOperationResultStatus.Failure) + { + return tradingOperationResult; + } + ??.Wait(TimeSpan.FromSeconds(5.0)); + return tradingOperationResult; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + Core.Instance.OrderAdded -= delegate(Order order) + { + if (!??.IsSet && P_0.IsCorrespondingOrder(order)) + { + ??.Set(); + } + }; + } + return null; + } + + private static AdvancedTradingOperationResult ?(IList P_0, CancellationToken P_1, string P_2) + { + if (!P_0.Any()) + { + return AdvancedTradingOperationResult.?(); + } + AdvancedTradingOperationResult advancedTradingOperationResult = new AdvancedTradingOperationResult(); + ManualResetEvent ?? = new ManualResetEvent(initialState: false); + HashSet ?? = new HashSet(P_0.Select((Order order) => order.Id)); + try + { + Core.Instance.OrderRemoved += delegate(Order order) + { + ??.Remove(order.Id); + if (??.Count == 0) + { + ??.Set(); + } + }; + foreach (Order item in P_0) + { + CancelOrderRequestParameters cancelOrderRequestParameters = new CancelOrderRequestParameters + { + Order = item, + CancellationToken = P_1, + SendingSource = P_2 + }; + item.Connection.Limitation?.Wait(cancelOrderRequestParameters.Type, cancelOrderRequestParameters.CancellationToken); + TradingOperationResult tradingOperationResult = Core.Instance.CancelOrder(cancelOrderRequestParameters); + if (tradingOperationResult != null && tradingOperationResult.Status == TradingOperationResultStatus.Failure) + { + ??.Remove(item.Id); + } + advancedTradingOperationResult.?(cancelOrderRequestParameters, tradingOperationResult); + } + if (!??.Any()) + { + ??.Set(); + } + ??.WaitOne(TimeSpan.FromSeconds(5.0)); + return advancedTradingOperationResult; + } + finally + { + Core.Instance.OrderRemoved -= delegate(Order order) + { + ??.Remove(order.Id); + if (??.Count == 0) + { + ??.Set(); + } + }; + } + } + } + public record GroupTradingOperation + { + public GroupTradingOperationType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public GroupTradingOperationFilters Filters + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + [CompilerGenerated] + private readonly GroupTradingOperationType ??; + + [CompilerGenerated] + private readonly GroupTradingOperationFilters ??; + + public GroupTradingOperation(GroupTradingOperationType Type, GroupTradingOperationFilters Filters) + { + ?? = Type; + ?? = Filters; + base..ctor(); + } + + [CompilerGenerated] + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (PrintMembers(stringBuilder)) + { + stringBuilder.Append(' '); + } + stringBuilder.Append('}'); + return stringBuilder.ToString(); + } + + [CompilerGenerated] + protected virtual bool PrintMembers(StringBuilder builder) + { + RuntimeHelpers.EnsureSufficientExecutionStack(); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(Type.ToString()); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(Filters.ToString()); + return true; + } + + [CompilerGenerated] + public void Deconstruct(out GroupTradingOperationType Type, out GroupTradingOperationFilters Filters) + { + Type = this.Type; + Filters = this.Filters; + } + } + [Flags] + public enum GroupTradingOperationFilters + { + None = 0, + Connection = 1, + Symbol = 2, + Account = 4, + Side = 8, + TimeInForce = 0x10, + OrderType = 0x20, + CertainOrders = 0x40 + } + public enum GroupTradingOperationType + { + CancelOrders, + ClosePositions, + ReversePositions, + Flatten + } + public interface ISubTradingOperation + { + GroupTradingOperation ParentOperation { get; } + } + /// + /// The allowed result. + /// + public sealed class AllowedResult + { + [CompilerGenerated] + private TradingOperationStatus ??; + + [CompilerGenerated] + private string ??; + + /// + /// Gets the status. + /// + public TradingOperationStatus Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = tradingOperationStatus; + } + } + + /// + /// Gets the reason. + /// + public string Reason + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Get the allowed result. + /// + /// An AllowedResult. + public static AllowedResult GetAllowedResult() + { + return new AllowedResult + { + Status = TradingOperationStatus.Allowed + }; + } + + /// + /// Gets the not allowed result. + /// + /// The reason. + /// An AllowedResult. + public static AllowedResult GetNotAllowedResult(string reason = "") + { + return new AllowedResult + { + Status = TradingOperationStatus.NotAllowed, + Reason = reason + }; + } + } + public static class TradingOperations + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(OrderType P_0) + { + if (P_0.Behavior == OrderTypeBehavior.Limit) + { + return (P_0.Usage & OrderTypeUsage.CloseOrder) == OrderTypeUsage.CloseOrder; + } + return false; + } + + internal bool ?(OrderType P_0) + { + if (P_0.Behavior == OrderTypeBehavior.Stop) + { + return (P_0.Usage & OrderTypeUsage.CloseOrder) == OrderTypeUsage.CloseOrder; + } + return false; + } + + internal bool ?(OrderType P_0) + { + if (P_0.Behavior == OrderTypeBehavior.TrailingStop) + { + return (P_0.Usage & OrderTypeUsage.CloseOrder) == OrderTypeUsage.CloseOrder; + } + return false; + } + } + + public static AllowedResult IsAllowed(TradingOperation operation, TradingOperationParameters parameters) + { + if (parameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (Core.Instance.TradingStatus == TradingStatus.Locked) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + Symbol symbol = parameters.Symbol; + if (symbol != null && symbol.State == BusinessObjectState.Fake) + { + return AllowedResult.GetNotAllowedResult(string.Empty); + } + if (parameters.Account.IsLocked()) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return operation switch + { + TradingOperation.PlaceOrder => ?(parameters), + TradingOperation.ModifyOrder => ?(parameters), + TradingOperation.CancelOrder => ?(parameters), + TradingOperation.ClosePosition => ?(parameters), + _ => throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + }; + } + + public static AllowedResult IsAllowed(TradingOperation operation, IList parametersList) + { + if (parametersList == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + foreach (TradingOperationParameters parameters in parametersList) + { + AllowedResult allowedResult = IsAllowed(operation, parameters); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + return allowedResult; + } + } + return AllowedResult.GetAllowedResult(); + } + + public static AllowedResult IsOrderTpAllowed(TradingOperationParameters parameters) + { + TradingObject tradingObject = (parameters.Order as TradingObject) ?? parameters.Position; + if (tradingObject == null) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + AllowedResult allowedResult = AllowedResult.GetAllowedResult(); + OrderType orderType = parameters.Order?.OrderType; + if (orderType != null) + { + allowedResult = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol, orderType); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + return allowedResult; + } + allowedResult = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol, orderType); + } + else + { + allowedResult = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol); + } + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + return allowedResult; + } + if ((Core.Instance.Connections[tradingObject.ConnectionId]?.BusinessObjects?.OrderTypes)?.FirstOrDefault((OrderType P_0) => P_0.Behavior == OrderTypeBehavior.Limit && (P_0.Usage & OrderTypeUsage.CloseOrder) == OrderTypeUsage.CloseOrder) == null) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return AllowedResult.GetAllowedResult(); + } + + public static AllowedResult IsOrderSlAllowed(TradingOperationParameters parameters) + { + TradingObject tradingObject = (parameters.Order as TradingObject) ?? parameters.Position; + if (tradingObject == null) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + AllowedResult allowedResult = AllowedResult.GetAllowedResult(); + OrderType orderType = parameters.Order?.OrderType; + if (orderType != null) + { + allowedResult = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol, orderType); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + return allowedResult; + } + allowedResult = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol, orderType); + } + else + { + allowedResult = Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol); + } + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + return allowedResult; + } + if ((Core.Instance.Connections[tradingObject.ConnectionId]?.BusinessObjects?.OrderTypes)?.FirstOrDefault((OrderType P_0) => P_0.Behavior == OrderTypeBehavior.Stop && (P_0.Usage & OrderTypeUsage.CloseOrder) == OrderTypeUsage.CloseOrder) == null) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return AllowedResult.GetAllowedResult(); + } + + public static AllowedResult IsOrderSLTrailAllowed(TradingOperationParameters parameters) + { + TradingObject tradingObject = (parameters.Order as TradingObject) ?? parameters.Position; + if (tradingObject == null) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + AllowedResult allowedResult = AllowedResult.GetAllowedResult(); + OrderType orderType = parameters.Order?.OrderType; + allowedResult = ((orderType == null) ? Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol) : Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), tradingObject.Account, tradingObject.Symbol, orderType)); + if (allowedResult.Status == TradingOperationStatus.NotAllowed) + { + return allowedResult; + } + if ((Core.Instance.Connections[tradingObject.ConnectionId]?.BusinessObjects?.OrderTypes)?.FirstOrDefault((OrderType P_0) => P_0.Behavior == OrderTypeBehavior.TrailingStop && (P_0.Usage & OrderTypeUsage.CloseOrder) == OrderTypeUsage.CloseOrder) == null) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return AllowedResult.GetAllowedResult(); + } + + private static AllowedResult ?(TradingOperationParameters P_0) + { + if (P_0.Account != null && P_0.Symbol != null) + { + return Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), P_0.Account, P_0.Symbol); + } + if (P_0.Symbol != null) + { + return Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), P_0.Symbol); + } + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + private static AllowedResult ?(TradingOperationParameters P_0) + { + return AllowedResult.GetAllowedResult(); + } + + private static AllowedResult ?(TradingOperationParameters P_0) + { + if (P_0.Order == null || P_0.Order.State == BusinessObjectState.Fake) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return AllowedResult.GetAllowedResult(); + } + + private static AllowedResult ?(TradingOperationParameters P_0) + { + if (P_0.Position == null || P_0.Position.State == BusinessObjectState.Fake) + { + return AllowedResult.GetNotAllowedResult(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return AllowedResult.GetAllowedResult(); + } + } + /// + /// Defines advanced trading operation respond bundle + /// + public sealed class AdvancedTradingOperationResult + { + [CompilerGenerated] + private AdvancedTradingOperationResultStatus ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private IDictionary ??; + + /// + /// Respond operation state + /// + public AdvancedTradingOperationResultStatus Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = advancedTradingOperationResultStatus; + } + } + + /// + /// Respond message + /// + public string Message + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Respond value (optional) + /// + public object Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = obj; + } + } + + /// + /// Details of sub-operations + /// + public IDictionary Details + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dictionary; + } + } + + internal AdvancedTradingOperationResult() + { + Status = AdvancedTradingOperationResultStatus.Success; + Details = new Dictionary(); + } + + internal AdvancedTradingOperationResult(RequestParameters P_0, TradingOperationResult P_1) + : this() + { + ?(P_0, P_1); + } + + internal static AdvancedTradingOperationResult ?() + { + return new AdvancedTradingOperationResult(); + } + + internal static AdvancedTradingOperationResult ?(string P_0) + { + return new AdvancedTradingOperationResult + { + Status = AdvancedTradingOperationResultStatus.Failure, + Message = P_0 + }; + } + + internal void ?(RequestParameters P_0, TradingOperationResult P_1) + { + Details.Add(P_0, P_1); + ?(); + } + + internal AdvancedTradingOperationResult ?(AdvancedTradingOperationResult P_0) + { + foreach (var (key, value) in P_0.Details) + { + Details.Add(key, value); + } + ?(); + return this; + } + + private void ?() + { + int num = 0; + string text = null; + foreach (TradingOperationResult value in Details.Values) + { + switch (value.Status) + { + case TradingOperationResultStatus.Success: + num++; + break; + case TradingOperationResultStatus.Failure: + if (text == null) + { + text = value.Message; + } + break; + } + } + if (num == Details.Count) + { + Status = AdvancedTradingOperationResultStatus.Success; + return; + } + Message = text; + Status = ((num > 0) ? AdvancedTradingOperationResultStatus.PartiallySuccess : AdvancedTradingOperationResultStatus.Failure); + } + } + public sealed class BrandingInformationHelpLink + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + public string Text + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string URL + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool Separator + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public interface IBrandingInformation + { + string ApplicationName { get; } + + string ApplicationID { get; } + + string CopyrightDetails { get; } + + string PrivacePolicyUrl { get; } + + string TermsOfUseUrl { get; } + + string OfficialWebSite { get; } + + string LiveChatUrl { get; } + + string UpdateUrl { get; } + + string PricingPageUrl { get; } + + string AccountDashboardUrl { get; } + + string WelcomeScreenText { get; } + + string HelpCustomURL { get; } + + string GitCustomURL { get; } + + string ReleaseNotesURL { get; } + + BrandingInformationHelpLink[] HelpLinks { get; } + + bool IsGrayLabel { get; } + + /// + /// Get all available custom resources + /// + string[] GetResourceNames(); + + /// + /// Get custom resource stream by name + /// + Stream GetResource(string resourceName); + + /// + /// Check whether specified items was hidden by branding specification + /// + /// + bool IsItemHidden(string itemType, string itemName); + } +} +namespace ? +{ + internal sealed class ? : IBrandingInformation + { + public string ApplicationName => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string ApplicationID => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string CopyrightDetails => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string PrivacePolicyUrl => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string TermsOfUseUrl => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string OfficialWebSite => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string LiveChatUrl => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string UpdateUrl => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string PricingPageUrl => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string AccountDashboardUrl => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string WelcomeScreenText => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public string HelpCustomURL => null; + + public string GitCustomURL => null; + + public string ReleaseNotesURL => null; + + public BrandingInformationHelpLink[] HelpLinks => null; + + public bool IsGrayLabel => false; + + public string[] GetResourceNames() + { + return null; + } + + public Stream GetResource(string resourceName) + { + return null; + } + + public bool IsItemHidden(string itemType, string itemName) + { + return false; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// The assembly loader. + /// + public static class AssemblyLoader + { + private class ? + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Assembly ??; + + public string AssemblyFolder + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = text; + } + } + + public Assembly Assembly + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = assembly; + } + } + + public ?(string P_0, Assembly P_1) + { + AssemblyFolder = P_0; + Assembly = P_1; + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + internal Assembly? ?(object P_0, ResolveEventArgs P_1) + { + try + { + try + { + if (P_1.RequestingAssembly != null && ??.TryGetValue(P_1.Name, out var value) && File.Exists(value)) + { + Assembly assembly = Assembly.Load(File.ReadAllBytes(value)); + if ((object)assembly != null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.RequestingAssembly); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.RequestingAssembly); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return assembly; + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + if (P_1.RequestingAssembly != null && ??.TryGetValue(P_1.RequestingAssembly.FullName, out var value2)) + { + Assembly assembly2 = AssemblyLoader.?(P_1.Name, value2.AssemblyFolder); + if ((object)assembly2 != null) + { + return assembly2; + } + if (??.TryGetValue(P_1.Name, out var value3)) + { + return value3.Assembly; + } + LoggerManager loggers3 = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.RequestingAssembly); + loggers3.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + return null; + } + } + + private static readonly HashSet ??; + + private static readonly Dictionary ??; + + private static readonly Dictionary ??; + + private static Dictionary> ??; + + static AssemblyLoader() + { + ?? = new Dictionary>(); + ?? = new Dictionary(); + ?? = new HashSet + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + try + { + ?? = new Dictionary(); + string text = Path.Combine(Const.CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (File.Exists(text)) + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(text); + foreach (XmlNode childNode in xmlDocument.DocumentElement.ChildNodes) + { + if (childNode.Attributes[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()] != null && childNode.Attributes[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()] != null) + { + string value = Path.Combine(Const.CUSTOM_SCRIPTS_PATH, childNode.Attributes[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()].Value); + ??[childNode.Attributes[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()].Value] = value; + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + AppDomain.CurrentDomain.AssemblyResolve += delegate(object P_0, ResolveEventArgs P_1) + { + try + { + try + { + if (P_1.RequestingAssembly != null && ??.TryGetValue(P_1.Name, out var value2) && File.Exists(value2)) + { + Assembly assembly = Assembly.Load(File.ReadAllBytes(value2)); + if ((object)assembly != null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.RequestingAssembly); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.RequestingAssembly); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value2); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + return assembly; + } + } + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + if (P_1.RequestingAssembly != null && ??.TryGetValue(P_1.RequestingAssembly.FullName, out var value3)) + { + Assembly assembly2 = ?(P_1.Name, value3.AssemblyFolder); + if ((object)assembly2 != null) + { + return assembly2; + } + if (??.TryGetValue(P_1.Name, out var value4)) + { + return value4.Assembly; + } + LoggerManager loggers3 = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1.RequestingAssembly); + loggers3.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + } + } + catch (Exception ex3) + { + Core.Instance.Loggers.Log(ex3); + } + return (Assembly?)null; + }; + } + + /// + /// Load types. + /// + /// The folder name. + /// The target type. + /// The assembly name filter. + /// The search option. + /// If true, load in memory. + /// If true, allow loading references. + /// ]]> + public static List LoadTypes(string folderName, Type targetType, string assemblyNameFilter = null, SearchOption searchOption = SearchOption.TopDirectoryOnly, bool loadInMemory = false, bool allowLoadingReferences = false) + { + List list = new List(); + try + { + foreach (string item in Directory.EnumerateFiles(Path.Combine(Const.EXECUTING_FOLDER, folderName), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), searchOption)) + { + string fileName = Path.GetFileName(item); + if (string.IsNullOrEmpty(assemblyNameFilter) || fileName.Contains(assemblyNameFilter)) + { + List list2 = ?(item, targetType, loadInMemory, allowLoadingReferences); + if (list2 != null) + { + list.AddRange(list2); + } + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return list; + } + + internal static List ?(string P_0, Type P_1, bool P_2 = false, bool P_3 = false) + { + List list = new List(); + try + { + Assembly assembly = (P_2 ? Assembly.Load(File.ReadAllBytes(P_0)) : Assembly.LoadFrom(P_0)); + if (P_3) + { + ??[assembly.FullName] = new ?(Path.GetDirectoryName(P_0), assembly); + } + foreach (Type exportedType in assembly.ExportedTypes) + { + if (!exportedType.IsAbstract && (P_1.IsAssignableFrom(exportedType) || exportedType.GetInterfaces().Contains(P_1))) + { + list.Add(new TypeWrapper(exportedType, P_0)); + } + } + if (P_3 && list.Any()) + { + ?(assembly, P_0); + } + } + catch (BadImageFormatException ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + return list; + } + + private static void ?(Assembly P_0, string P_1) + { + AssemblyName[] referencedAssemblies = P_0.GetReferencedAssemblies(); + foreach (AssemblyName assemblyName in referencedAssemblies) + { + if (assemblyName.Name.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) || ??.Contains(assemblyName.Name)) + { + continue; + } + try + { + string path = Path.Combine(Path.GetDirectoryName(P_1), assemblyName.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (File.Exists(path)) + { + Assembly assembly = Assembly.Load(File.ReadAllBytes(path)); + if ((object)assembly != null) + { + ??[assemblyName.FullName] = new ?(Path.GetDirectoryName(P_1), assembly); + ?(assembly, P_1); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + private static void ?(string P_0) + { + ??[P_0] = new Dictionary(); + foreach (string item in Directory.EnumerateFiles(P_0, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchOption.AllDirectories)) + { + try + { + Assembly assembly = Assembly.Load(File.ReadAllBytes(item)); + if ((object)assembly != null) + { + ??[P_0][assembly.FullName] = assembly; + } + } + catch (BadImageFormatException ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + } + } + + private static Assembly ?(string P_0, string P_1) + { + if (!??.ContainsKey(P_1)) + { + ?(P_1); + } + if (??.TryGetValue(P_1, out var value) && value.TryGetValue(P_0, out var value2)) + { + return value2; + } + return null; + } + } + public class TypeWrapper + { + [CompilerGenerated] + private Type ??; + + [CompilerGenerated] + private string ??; + + public Type Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = type; + } + } + + public string AssemblyLocation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal TypeWrapper(Type P_0, string P_1) + { + Type = P_0; + AssemblyLocation = P_1; + } + + public static implicit operator Type(TypeWrapper typeWrapper) + { + return typeWrapper.Type; + } + + public override string ToString() + { + return Type?.ToString(); + } + } +} +namespace ? +{ + internal enum ? + { + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ?? + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// Quote type for subscribtion dictum + /// + public enum SubscribeQuoteType + { + /// + /// Level 1 quote + /// + Quote, + /// + /// Level 2 quote + /// + Level2, + /// + /// Last + /// + Last, + /// + /// Mark price + /// + Mark + } + [DataContract(Name = "HistoryType", Namespace = "TradingPlatform")] + public enum HistoryType + { + [Description("Bid")] + [EnumMember] + Bid, + [Description("Ask")] + [EnumMember] + Ask, + [Description("Midpoint")] + [EnumMember] + Midpoint, + [Description("Last")] + [EnumMember] + Last, + [Description("Bid/Ask")] + [EnumMember] + BidAsk, + [Description("Mark")] + [EnumMember] + Mark + } + public enum Side + { + Buy, + Sell + } + [Flags] + public enum LoggingLevel + { + System = 1, + [Description("Exception")] + Error = 2, + Trading = 4, + Verbose = 8, + Quotes = 0x10, + Painting = 0x20, + Performance = 0x40, + [Description("Loading history")] + LoadingHistory = 0x80 + } + /// + /// Trading operation state + /// + public enum TradingOperationResultStatus + { + Success, + Failure + } + /// + /// Complex trading operation state + /// + public enum AdvancedTradingOperationResultStatus + { + Success, + PartiallySuccess, + Failure + } + public enum NonFixedListDownload + { + Download, + IgnoreDownload + } + [DataContract(Name = "OptionType", Namespace = "TradingPlatform")] + public enum OptionType + { + [EnumMember] + Call, + [EnumMember] + Put + } + [Obfuscation(Exclude = true)] + public enum AggressorFlag + { + [Description("None")] + None, + [Description("Buy")] + Buy, + [Description("Sell")] + Sell, + [Description("Not set")] + NotSet + } + [Obfuscation(Exclude = true)] + public enum TickDirection + { + [Description("Not set")] + NotSet, + [Description("None")] + None, + [Description("Up")] + Up, + [Description("Down")] + Down + } + public enum CloseOrderType + { + [Description("Stop loss")] + StopLoss, + [Description("Take profit")] + TakeProfit + } + public enum TradingStatus + { + Allowed, + Locked, + AllowedFromStrategies + } + public enum TradingOperationStatus + { + Allowed, + NotAllowed + } + public enum TradingOperation + { + PlaceOrder, + ModifyOrder, + CancelOrder, + ClosePosition + } + public enum ValidateState + { + Valid, + NotValid + } + public enum RequestType + { + PlaceOrder, + ModifyOrder, + History, + Symbol, + SearchSymbol, + QuoteSubscribe, + FutureContracts, + OptionSeries, + Strikes, + ClosePosition, + CancelOrder, + Custom, + PnL, + Report, + Connect, + VolumeAnalysis, + VolumeAnalysisByPeriod, + PlaceMultiOrderOrder, + TradesHistory, + OrdersHistory, + ConvertPosition, + TradingSignals + } + public enum ColouringModes + { + [Description("None")] + None, + [Description("Compare to previous")] + Previous, + [Description("By sign")] + Signed + } + [Flags] + public enum NativeModifierKeys + { + None = 0, + Alt = 1, + Shift = 2, + Control = 4 + } + public enum NativeAlignment + { + NotSet, + Left, + Center, + Right + } + public enum NativeKey + { + None = 0, + Cancel = 1, + Back = 2, + Tab = 3, + LineFeed = 4, + Clear = 5, + Return = 6, + Enter = 6, + Pause = 7, + Capital = 8, + CapsLock = 8, + KanaMode = 9, + HangulMode = 9, + JunjaMode = 10, + FinalMode = 11, + HanjaMode = 12, + KanjiMode = 12, + Escape = 13, + ImeConvert = 14, + ImeNonConvert = 15, + ImeAccept = 16, + ImeModeChange = 17, + Space = 18, + Prior = 19, + PageUp = 19, + PageDown = 20, + End = 21, + Home = 22, + Left = 23, + Up = 24, + Right = 25, + Down = 26, + Select = 27, + Print = 28, + Execute = 29, + Snapshot = 30, + PrintScreen = 30, + Insert = 31, + Delete = 32, + Help = 33, + D0 = 34, + D1 = 35, + D2 = 36, + D3 = 37, + D4 = 38, + D5 = 39, + D6 = 40, + D7 = 41, + D8 = 42, + D9 = 43, + A = 44, + B = 45, + C = 46, + D = 47, + E = 48, + F = 49, + G = 50, + H = 51, + I = 52, + J = 53, + K = 54, + L = 55, + M = 56, + N = 57, + O = 58, + P = 59, + Q = 60, + R = 61, + S = 62, + T = 63, + U = 64, + V = 65, + W = 66, + X = 67, + Y = 68, + Z = 69, + LWin = 70, + RWin = 71, + Apps = 72, + Sleep = 73, + NumPad0 = 74, + NumPad1 = 75, + NumPad2 = 76, + NumPad3 = 77, + NumPad4 = 78, + NumPad5 = 79, + NumPad6 = 80, + NumPad7 = 81, + NumPad8 = 82, + NumPad9 = 83, + Multiply = 84, + Add = 85, + Separator = 86, + Subtract = 87, + Decimal = 88, + Divide = 89, + F1 = 90, + F2 = 91, + F3 = 92, + F4 = 93, + F5 = 94, + F6 = 95, + F7 = 96, + F8 = 97, + F9 = 98, + F10 = 99, + F11 = 100, + F12 = 101, + F13 = 102, + F14 = 103, + F15 = 104, + F16 = 105, + F17 = 106, + F18 = 107, + F19 = 108, + F20 = 109, + F21 = 110, + F22 = 111, + F23 = 112, + F24 = 113, + NumLock = 114, + Scroll = 115, + LeftShift = 116, + RightShift = 117, + LeftCtrl = 118, + RightCtrl = 119, + LeftAlt = 120, + RightAlt = 121, + BrowserBack = 122, + BrowserForward = 123, + BrowserRefresh = 124, + BrowserStop = 125, + BrowserSearch = 126, + BrowserFavorites = 127, + BrowserHome = 128, + VolumeMute = 129, + VolumeDown = 130, + VolumeUp = 131, + MediaNextTrack = 132, + MediaPreviousTrack = 133, + MediaStop = 134, + MediaPlayPause = 135, + LaunchMail = 136, + SelectMedia = 137, + LaunchApplication1 = 138, + LaunchApplication2 = 139, + Oem1 = 140, + OemSemicolon = 140, + OemPlus = 141, + OemComma = 142, + OemMinus = 143, + OemPeriod = 144, + Oem2 = 145, + OemQuestion = 145, + Oem3 = 146, + OemTilde = 146, + AbntC1 = 147, + AbntC2 = 148, + Oem4 = 149, + OemOpenBrackets = 149, + Oem5 = 150, + OemPipe = 150, + Oem6 = 151, + OemCloseBrackets = 151, + Oem7 = 152, + OemQuotes = 152, + Oem8 = 153, + Oem102 = 154, + OemBackslash = 154, + ImeProcessed = 155, + System = 156, + OemAttn = 157, + DbeAlphanumeric = 157, + OemFinish = 158, + DbeKatakana = 158, + OemCopy = 159, + DbeHiragana = 159, + OemAuto = 160, + DbeSbcsChar = 160, + OemEnlw = 161, + DbeDbcsChar = 161, + OemBackTab = 162, + DbeRoman = 162, + Attn = 163, + DbeNoRoman = 163, + CrSel = 164, + DbeEnterWordRegisterMode = 164, + ExSel = 165, + DbeEnterImeConfigureMode = 165, + EraseEof = 166, + DbeFlushString = 166, + Play = 167, + DbeCodeInput = 167, + Zoom = 168, + DbeNoCodeInput = 168, + NoName = 169, + DbeDetermineString = 169, + Pa1 = 170, + DbeEnterDialogConversionMode = 170, + OemClear = 171, + DeadCharProcessed = 172 + } + public class NativeKeyEventArgs + { + [CompilerGenerated] + private readonly NativeKey ??; + + [CompilerGenerated] + private readonly NativeModifierKeys ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + public NativeKey Key + { + [CompilerGenerated] + get + { + return ??; + } + } + + public NativeModifierKeys Modifiers + { + [CompilerGenerated] + get + { + return ??; + } + } + + public bool Handled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool IsRepeated + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public NativeKeyEventArgs(NativeKey key, NativeModifierKeys modifiers) + { + ?? = key; + ?? = modifiers; + } + } + public enum NativeDragDropEffects + { + Scroll = int.MinValue, + All = -2147483645, + None = 0, + Copy = 1, + Move = 2, + Link = 4 + } + public class NativeDragEventArgs + { + [CompilerGenerated] + private NativeDragDropEffects ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private readonly object[] ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private readonly Point ??; + + public NativeDragDropEffects Effects + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool Handled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object[] Data + { + [CompilerGenerated] + get + { + return ??; + } + } + + public object Source + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Point MousePosition + { + [CompilerGenerated] + get + { + return ??; + } + } + + public NativeDragEventArgs(NativeDragDropEffects effects, object source, object[] data, Point mousePosition) + { + Effects = effects; + Source = source; + ?? = data; + ?? = mousePosition; + } + + public NativeDragEventArgs(object source, object[] data, Point mousePosition) + { + Source = source; + ?? = data; + ?? = mousePosition; + } + } + public enum NativeWindowCaptionButtonType + { + Action, + Maximize, + Minimize, + Close, + FullScreen, + None + } + public enum PositionImpactType + { + Undefined, + Open, + Close + } + [Obfuscation(Exclude = true)] + public enum CorporateActionType + { + Undefined, + Split, + Dividend + } + public enum EntityLifecycle + { + Created, + Changed, + Removed + } + public enum VwapStdCalculationType + { + StandardDeviation, + VWAPVariance + } + public enum VWAPStandardDeviationMode + { + [Description("Single")] + Single, + [Description("Multiple")] + Multiple + } + public enum VwapDataType + { + [Description("Tick")] + Tick, + [Description("Current TF")] + CurrentTF + } + public enum VwapPriceType + { + [Description("Open")] + Open, + [Description("High")] + High, + [Description("Low")] + Low, + [Description("Close")] + Close, + [Description("HL/2")] + HL2, + [Description("HLC/3")] + HLC3, + [Description("OHLC/4")] + OHLC4 + } + public enum HistoryProcessorReversalCalculationType + { + [Description("Previous bar")] + PreviousBar, + [Description("Independent")] + Independent + } +} +namespace ? +{ + internal class ? : IBufferedProcessorValue + { + public ? ??; + + public IConnectionBindedObject ??; + + public ? Key => ??; + + public ?(? P_0, IConnectionBindedObject P_1) + { + ?? = P_0; + ?? = P_1; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// The account extensions. + /// + public static class AccountExtensions + { + /// + /// Returns a custom name if available otherwise, returns the name. + /// + /// The account. + public static string GetCurrentName(this Account account) + { + string text = Core.Instance.CustomAccountPropertiesProvider.GetProperty(account, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as string; + if (!string.IsNullOrEmpty(text)) + { + return text; + } + return account.Name; + } + + /// + /// Returns information about whether the account supports trading operations + /// + /// The account. + public static bool IsLocked(this Account account) + { + return Core.Instance.CustomAccountPropertiesProvider.GetProperty(account, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) as bool? == true; + } + } + /// + /// The aggressor flag calculator extensions. + /// + public static class AggressorFlagCalculatorExtensions + { + /// + /// Collect bid ask. + /// + /// The calculator. + /// The quote. + public static void CollectBidAsk(this IAggressorFlagCalculator calculator, Quote quote) + { + calculator.CollectBidAsk(quote.SymbolId, quote.Time.Ticks, quote.Bid, quote.Ask); + } + + /// + /// Calculate aggressor flag. + /// + /// The calculator. + /// The last. + /// An AggressorFlag. + public static AggressorFlag CalculateAggressorFlag(this IAggressorFlagCalculator calculator, Last last) + { + return calculator.CalculateAggressorFlag(last.SymbolId, last.Time.Ticks, last.Price); + } + } + public static class DateTimeExtensions + { + public static DateTime ToSelectedTimeZone(this DateTime dt) + { + return Core.Instance.TimeUtils.ConvertFromUTCToSelectedTimeZone(dt); + } + + public static DateTime FromSelectedTimeZoneToUtc(this DateTime dt) + { + return Core.Instance.TimeUtils.ConvertFromSelectedTimeZoneToUTC(dt); + } + + public static DateTime TrimSeconds(this DateTime value) + { + return new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, 0, value.Kind); + } + + public static DateTime CeilingTo(this DateTime value, TimeSpan timeSpan) + { + long num = value.Ticks % timeSpan.Ticks; + if (num == 0L) + { + return value; + } + return new DateTime(value.Ticks - num + timeSpan.Ticks, value.Kind); + } + + public static DateTime CeilingTo(this DateTime value, Period period) + { + return value.CeilingTo(TimeSpan.FromTicks(period.Ticks)); + } + + public static DateTime FloorTo(this DateTime value, TimeSpan timeSpan) + { + return new DateTime(value.Ticks - value.Ticks % timeSpan.Ticks, value.Kind); + } + + public static DateTime FloorTo(this DateTime value, Period period) + { + return value.FloorTo(TimeSpan.FromTicks(period.Ticks)); + } + + public static long ToUnixSeconds(this DateTime dateTime) + { + return new DateTimeOffset(dateTime).ToUnixTimeSeconds(); + } + + public static long ToUnixMilliseconds(this DateTime dateTime) + { + return new DateTimeOffset(dateTime).ToUnixTimeMilliseconds(); + } + + public static DateTime SetKind(this DateTime dateTime, DateTimeKind kind) + { + return new DateTime(dateTime.Ticks, kind); + } + + public static int GetWeekOfYear(this DateTime dateTime, DayOfWeek firstWeekDay = DayOfWeek.Monday) + { + return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstFullWeek, firstWeekDay); + } + + public static IEnumerable GetDaysOfWeekForCurrMonth(this DateTime date, DayOfWeek dayOfWeek) + { + DateTime dateTime = new DateTime(date.Year, date.Month, 1); + DateTime dateTime2 = dateTime.AddMonths(1); + while (dateTime < dateTime2 && dateTime.DayOfWeek != dayOfWeek) + { + dateTime = dateTime.AddDays(1.0); + } + while (dateTime < dateTime2) + { + yield return dateTime; + dateTime = dateTime.AddDays(7.0); + } + } + } + public static class DateTimeIntervalExtensions + { + public static TimeSpan GetLength(this Interval interval) + { + return TimeSpan.FromTicks(Math.Abs(interval.From.Ticks - interval.To.Ticks)); + } + + public static IEnumerable> Split(this Interval interval, TimeSpan step, bool roundToStep = false) + { + if (step == TimeSpan.Zero || step == Timeout.InfiniteTimeSpan) + { + yield return interval; + yield break; + } + DateTime dateTime; + DateTime to; + if (interval.IsReversal) + { + to = interval.From; + do + { + dateTime = to.Add(-step); + if (roundToStep) + { + dateTime = dateTime.CeilingTo(step); + } + if (dateTime < interval.To) + { + dateTime = interval.To; + } + yield return new Interval(dateTime, to); + to = dateTime; + } + while (dateTime > interval.To); + yield break; + } + dateTime = interval.From; + do + { + to = dateTime.Add(step); + if (roundToStep) + { + to = to.FloorTo(step); + } + if (to > interval.To) + { + to = interval.To; + } + yield return new Interval(dateTime, to); + dateTime = to; + } + while (to.Ticks < interval.To.Ticks); + } + + public static bool Contains(this Interval interval, Period period) + { + DateTime value = interval.From; + DateTime dateTime = interval.To; + if (interval.IsReversal) + { + value = interval.To; + dateTime = interval.From; + } + dateTime = dateTime.AddTicks(1L); + long ticks = value.CeilingTo(period).Ticks; + long ticks2 = dateTime.FloorTo(period).Ticks; + return period.Ticks <= ticks2 - ticks; + } + } + public static class DelegateExtensions + { + public static void InvokeSafely(this Delegate @delegate, params object[] args) + { + if ((object)@delegate == null) + { + return; + } + Delegate[] invocationList = @delegate.GetInvocationList(); + foreach (Delegate obj in invocationList) + { + try + { + obj.DynamicInvoke(args); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + } + public static class DoubleExtensions + { + private const string ?? = "#,0.##########"; + + public static string Format(this double value, int precision = 2, bool abbreviate = false) + { + if (double.IsNaN(value)) + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + if (abbreviate) + { + return value.?(precision); + } + double num = ((value == -0.0) ? Math.Abs(value) : value); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(precision); + return num.ToString(defaultInterpolatedStringHandler.ToStringAndClear()); + } + + private static string ?(this double P_0, int P_1) + { + string value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + if (Math.Abs(P_0) >= 1000000000000.0) + { + P_0 /= 1000000000000.0; + value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + else if (Math.Abs(P_0) >= 1000000000.0) + { + P_0 /= 1000000000.0; + value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + else if (Math.Abs(P_0) >= 1000000.0) + { + P_0 /= 1000000.0; + value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + else if (Math.Abs(P_0) >= 1000.0) + { + P_0 /= 1000.0; + value = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler; + if (!string.IsNullOrEmpty(value)) + { + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 2); + defaultInterpolatedStringHandler.AppendFormatted(P_0.?(1)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_1); + return P_0.ToString(defaultInterpolatedStringHandler.ToStringAndClear()); + } + + private static double ?(this double P_0, int P_1) + { + double num = Math.Pow(10.0, P_1); + return Math.Truncate(P_0 * num) / num; + } + + public static bool IsNanOrDefault(this double value) + { + if (value != 0.0) + { + return double.IsNaN(value); + } + return true; + } + + public static string FormatPriceWithMaxPrecision(this double price, IFormatProvider formatProvider = null) + { + if (double.IsInfinity(price) || double.IsNaN(price)) + { + price = 0.0; + } + if (formatProvider != null) + { + return price.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), formatProvider); + } + return price.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + public static string FormatPriceWithMaxPrecision(this double price, int precision) + { + if (double.IsInfinity(price) || double.IsNaN(price)) + { + price = 0.0; + } + string text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + for (int i = 0; i < precision; i++) + { + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + for (int j = precision; j < 10; j++) + { + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return price.ToString(text); + } + + public static double RoundTo(this double value, int degree) + { + decimal num = (decimal)value; + decimal num2 = (decimal)Math.Pow(10.0, degree); + return (double)(num - num % num2); + } + } + public static class EnumExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal string ?(EnumMemberAttribute P_0) + { + return P_0.Value; + } + + internal string ?(DescriptionAttribute P_0) + { + return P_0.Description; + } + } + + public static string GetEnumMember(this Enum value) + { + return value.GetAttributeValueOrDefault((EnumMemberAttribute P_0) => P_0.Value, value.ToString()); + } + + public static string GetDescription(this Enum value) + { + return value.GetAttributeValueOrDefault((DescriptionAttribute P_0) => P_0.Description, value.ToString()); + } + + public static TValue GetAttributeValueOrDefault(this Enum value, Func valueFunc, TValue defaultValue) where TAttribute : Attribute + { + TAttribute attribute = value.GetAttribute(); + if (valueFunc == null || attribute == null) + { + return defaultValue; + } + return valueFunc(attribute); + } + + public static TAttribute GetAttribute(this Enum value) where TAttribute : Attribute + { + return value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(TAttribute), inherit: false) + .Cast() + .FirstOrDefault(); + } + } + public static class ExceptionExtensions + { + public static string GetMessageRecursive(this Exception exception) + { + return exception?.InnerException?.GetMessageRecursive() ?? exception?.Message ?? string.Empty; + } + + public static string GetFullMessageRecursive(this Exception exception) + { + StringBuilder stringBuilder = new StringBuilder(exception.Message); + if (exception.InnerException != null) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(18, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(exception.InnerException.GetFullMessageRecursive()); + stringBuilder2.Append(ref handler); + } + return stringBuilder.ToString(); + } + + public static IEnumerable GetInnerExceptionsRecursive(this Exception exception) + { + for (Exception ex = exception; ex != null; ex = ex.InnerException) + { + yield return ex; + } + } + } + public static class HistoricalDataExtensions + { + /// + /// Gets the price from historical data + /// + /// + /// + /// + public static double GetPrice(this HistoricalData historicalData, PriceType priceType, int offset = 0) + { + return historicalData[offset, SeekOriginHistory.End][priceType]; + } + + /// + /// Get Bid price + /// + /// Offset value + /// + public static double Bid(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Bid, offset); + } + + /// + /// Get Ask price + /// + /// Offset value + /// + public static double Ask(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Ask, offset); + } + + /// + /// Get Last price + /// + /// Offset value + /// + public static double Last(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Last, offset); + } + + /// + /// Get Open price + /// + /// Offset value + /// + public static double Open(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Open, offset); + } + + /// + /// Get High price + /// + /// Offset value + /// + public static double High(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.High, offset); + } + + /// + /// Get Low price + /// + /// Offset value + /// + public static double Low(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Low, offset); + } + + /// + /// Get Close price + /// + /// Offset value + /// + public static double Close(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Close, offset); + } + + /// + /// Get Median price + /// + /// Offset value + /// + public static double Median(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Median, offset); + } + + /// + /// Get Typical price + /// + /// Offset value + /// + public static double Typical(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Typical, offset); + } + + /// + /// Get Weighted price + /// + /// Offset value + /// + public static double Weighted(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Weighted, offset); + } + + /// + /// Get Volume + /// + /// Offset value + /// + public static double Volume(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Volume, offset); + } + + /// + /// Get Volume in quoting asset + /// + /// Offset value + /// + public static double QuoteAssetVolume(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.QuoteAssetVolume, offset); + } + + /// + /// Get Ticks + /// + /// Offset value + /// + public static double Ticks(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.Ticks, offset); + } + + /// + /// Get Open interest + /// + /// Offset value + /// + public static double OpenInterest(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.OpenInterest, offset); + } + + /// + /// Get Funding rate + /// + /// Offset value + /// + public static double FundingRate(this HistoricalData historicalData, int offset = 0) + { + return historicalData.GetPrice(PriceType.FundingRate, offset); + } + + /// + /// Get Time + /// + /// Offset value + /// + public static DateTime Time(this HistoricalData historicalData, int offset = 0) + { + return new DateTime(historicalData[offset, SeekOriginHistory.End].TicksLeft, DateTimeKind.Utc); + } + } + public static class HistoryItemExtensions + { + public static void ProcessTickDirection(this IList historyItems, CancellationToken cancellationToken) + { + if (historyItems == null || historyItems.Count == 0 || historyItems[0] is HistoryItemBar) + { + return; + } + if (historyItems[0] is HistoryItemTick) + { + double previousPrice = double.NaN; + double previousPrice2 = double.NaN; + TickDirection prevItemTickDirection = TickDirection.NotSet; + TickDirection prevItemTickDirection2 = TickDirection.NotSet; + { + foreach (HistoryItemTick item in historyItems.OfType()) + { + if (cancellationToken.IsCancellationRequested) + { + break; + } + item.BidTickDirection = Symbol.DetermineTickDirection(previousPrice, item.Bid, prevItemTickDirection); + item.AskTickDirection = Symbol.DetermineTickDirection(previousPrice2, item.Ask, prevItemTickDirection2); + previousPrice = item.Bid; + previousPrice2 = item.Ask; + prevItemTickDirection = item.BidTickDirection; + prevItemTickDirection2 = item.AskTickDirection; + } + return; + } + } + double previousPrice3 = double.NaN; + TickDirection prevItemTickDirection3 = TickDirection.NotSet; + foreach (HistoryItemLast item2 in historyItems.OfType()) + { + if (cancellationToken.IsCancellationRequested) + { + break; + } + item2.TickDirection = Symbol.DetermineTickDirection(previousPrice3, item2.Price, prevItemTickDirection3); + previousPrice3 = item2.Price; + prevItemTickDirection3 = item2.TickDirection; + } + } + } + public static class Int32Extensions + { + public static DateTime AsUnixSecondsToDateTime(this int seconds) + { + return DateTimeOffset.FromUnixTimeSeconds(seconds).DateTime; + } + } + public static class Int64Extensions + { + public static DateTime AsUnixSecondsToDateTime(this long seconds) + { + return DateTimeOffset.FromUnixTimeSeconds(seconds).DateTime.SetKind(DateTimeKind.Utc); + } + + public static DateTime AsUnixMillisecondsToDateTime(this long milliseconds) + { + return DateTimeOffset.FromUnixTimeMilliseconds(milliseconds).DateTime.SetKind(DateTimeKind.Utc); + } + } + public static class IntervalExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? where ? : IComparable + { + public static readonly ? ?? = new ?(); + + public static Func, ?> ??; + + public static Func ??; + + public static Func, ?> ??; + + public static Func ??; + + internal ? ?(Interval P_0) + { + return P_0.Min; + } + + internal ? ?(? P_0) + { + return P_0; + } + + internal ? ?(Interval P_0) + { + return P_0.Max; + } + + internal ? ?(? P_0) + { + return P_0; + } + } + + /// + /// Combines intersecting intervals + /// + public static IEnumerable> Optimize(this IEnumerable> intervals) where T : IComparable + { + Interval[] source = intervals.ToArray(); + T[] array = (from P_0 in source + select P_0.Min into P_0 + orderby P_0 + select P_0).ToArray(); + T[] array2 = (from P_0 in source + select P_0.Max into P_0 + orderby P_0 + select P_0).ToArray(); + int num = 0; + int num2 = 0; + T val = array.First(); + int num3 = 0; + while (num < array.Length && num2 < array2.Length) + { + T val2 = array[num]; + T val3 = array2[num2]; + if (val2.CompareTo(val3) <= 0) + { + num3++; + num++; + } + else + { + num3--; + num2++; + } + if (num3 == 0) + { + yield return new Interval(val, val3); + val = val2; + } + } + yield return new Interval(val, array2.Last()); + } + } + public static class ListExtensions + { + public static void AddRange(this IList list, IEnumerable items) + { + if (items == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + foreach (T item in items) + { + list.Add(item); + } + } + } + public static class OidcClientOptionsExtensions + { + public static OidcClientOptions GetCopy(this OidcClientOptions oidc) + { + return new OidcClientOptions + { + Authority = oidc.Authority, + ClientId = oidc.ClientId, + ClientSecret = oidc.ClientSecret, + RedirectUri = oidc.RedirectUri, + PostLogoutRedirectUri = oidc.PostLogoutRedirectUri, + Scope = oidc.Scope, + ClockSkew = oidc.ClockSkew, + LoadProfile = oidc.LoadProfile, + ProviderInformation = oidc.ProviderInformation?.GetCopy() + }; + } + + public static ProviderInformation GetCopy(this ProviderInformation providerInformation) + { + return new ProviderInformation + { + IssuerName = providerInformation.IssuerName, + AuthorizeEndpoint = providerInformation.AuthorizeEndpoint, + TokenEndpoint = providerInformation.TokenEndpoint, + EndSessionEndpoint = providerInformation.EndSessionEndpoint, + KeySet = providerInformation.KeySet + }; + } + } + public static class OrderExtensions + { + public static double GetExecutionPrice(this IOrder order) + { + if (order != null) + { + OrderType orderType = order.OrderType; + if (orderType != null) + { + _ = orderType.Behavior; + if (0 == 0) + { + return order.OrderType.Behavior switch + { + OrderTypeBehavior.Unspecified => double.NaN, + OrderTypeBehavior.Market => double.NaN, + OrderTypeBehavior.Limit => order.Price, + OrderTypeBehavior.Stop => order.TriggerPrice, + OrderTypeBehavior.TrailingStop => order.TriggerPrice, + OrderTypeBehavior.StopLimit => order.Price, + _ => throw new ArgumentOutOfRangeException(), + }; + } + } + } + return double.NaN; + } + } + public static class OrderRequestParametersExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(SlTpHolder P_0) + { + if (double.IsNaN(P_0.QuantityPercentage)) + { + return double.IsNaN(P_0.Quantity); + } + return false; + } + + internal bool ?(SlTpHolder P_0) + { + return P_0.Quantity == 0.0; + } + } + + public static double GetExecutionPrice(this OrderRequestParameters parameters) + { + if (parameters != null) + { + OrderType orderType = parameters.OrderType; + if (orderType != null) + { + _ = orderType.Behavior; + if (0 == 0) + { + return parameters.OrderType.Behavior switch + { + OrderTypeBehavior.Unspecified => double.NaN, + OrderTypeBehavior.Market => double.NaN, + OrderTypeBehavior.Limit => parameters.Price, + OrderTypeBehavior.Stop => parameters.TriggerPrice, + OrderTypeBehavior.TrailingStop => parameters.TriggerPrice, + OrderTypeBehavior.StopLimit => parameters.Price, + _ => throw new ArgumentOutOfRangeException(), + }; + } + } + } + return double.NaN; + } + + public static void SetExecutionPrice(this OrderRequestParameters parameters, double price) + { + if (parameters == null) + { + return; + } + OrderType orderType = parameters.OrderType; + if (orderType == null) + { + return; + } + _ = orderType.Behavior; + if (0 == 0) + { + switch (parameters.OrderType.Behavior) + { + case OrderTypeBehavior.Limit: + parameters.Price = price; + break; + case OrderTypeBehavior.Stop: + case OrderTypeBehavior.StopLimit: + parameters.TriggerPrice = price; + break; + case OrderTypeBehavior.TrailingStop: + break; + } + } + } + + public static bool IsCorrespondingOrder(this OrderRequestParameters parameters, IOrder order) + { + if (parameters.Symbol.IsSameAs(order.Symbol) && parameters.Account.Equals(order.Account) && parameters.OrderTypeId == order.OrderTypeId && parameters.Side == order.Side && Math.Abs(parameters.Quantity - order.TotalQuantity) < double.Epsilon) + { + return Math.Abs(parameters.OrderType.GetFillPrice(parameters) - order.GetExecutionPrice()) < double.Epsilon; + } + return false; + } + + public static bool TryCorrectBracketsQuantity(this OrderRequestParameters requestParameters, out string error) + { + error = null; + if (!?(requestParameters.Quantity, requestParameters.Symbol.LotStep, requestParameters.StopLossItems, out error)) + { + return false; + } + if (!?(requestParameters.Quantity, requestParameters.Symbol.LotStep, requestParameters.TakeProfitItems, out error)) + { + return false; + } + return true; + } + + private static bool ?(double P_0, double P_1, List P_2, out string P_3) + { + P_3 = null; + if (P_2 == null || P_2.Count == 0 || P_2.All((SlTpHolder slTpHolder) => double.IsNaN(slTpHolder.QuantityPercentage) && double.IsNaN(slTpHolder.Quantity))) + { + return true; + } + double num = 0.0; + foreach (SlTpHolder item in P_2) + { + if (double.IsNaN(item.QuantityPercentage)) + { + num += item.Quantity; + continue; + } + double num2 = (item.Quantity = CoreMath.RoundToIncrement(item.QuantityPercentage / 100.0 * P_0, P_1)); + num += num2; + } + if (num != P_0) + { + if (num < P_0) + { + P_2.Last().Quantity += P_0 - num; + } + else + { + if (!(P_2.Last().Quantity > num - P_0)) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(93, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(num); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + P_3 = defaultInterpolatedStringHandler.ToStringAndClear(); + return false; + } + P_2.Last().Quantity -= num - P_0; + } + } + if (P_2.Any((SlTpHolder slTpHolder) => slTpHolder.Quantity == 0.0)) + { + P_3 = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return false; + } + return true; + } + } + public static class PeriodExtensions + { + public static Interval FindInterval(this Period period, DateTime dateTime) + { + return period.FindInterval(dateTime.Ticks); + } + + public static Interval FindInterval(this Period period, long dateTimeTicks) + { + long ticks = period.Ticks; + DateTime dateTime = new DateTime(dateTimeTicks - dateTimeTicks % ticks, DateTimeKind.Utc); + DateTime to = dateTime.AddTicks(ticks - 1); + return new Interval(dateTime, to); + } + } + public static class PositionExtensions + { + public static bool IsBreakevenPossible(this Position position) + { + PnLItem pnLItem = position?.NetPnL ?? position?.GrossPnL; + if (pnLItem == null) + { + return true; + } + return pnLItem.Value > 0.0; + } + } + public static class SelectItemExtensions + { + [CompilerGenerated] + private sealed class ? + { + public ? ??; + + internal bool ?(SelectItem P_0) + { + return P_0.Value.Equals(??); + } + } + + public static SelectItem GetItemByValue(this IEnumerable list, TValue value) + { + return list.FirstOrDefault((SelectItem P_0) => P_0.Value.Equals(value)); + } + } + public static class SessionsExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Comparison ??; + + internal bool ?(ISession P_0) + { + return P_0.IsPrimary; + } + + internal bool ?(ISession P_0) + { + return P_0.ContainsTime(TimeSpan.Zero); + } + + internal bool ?(ISession P_0) + { + return P_0.CloseTime > P_0.OpenTime; + } + + internal int ?(ISession P_0, ISession P_1) + { + return P_0.OpenTime.CompareTo(P_1.OpenTime); + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + internal bool ?(TimeZoneInfo.AdjustmentRule P_0) + { + return P_0.DateStart < ??.Date; + } + + internal bool ?(TimeZoneInfo.AdjustmentRule P_0) + { + return P_0.DateEnd > ??.Date; + } + + internal bool ?(TimeZoneInfo.AdjustmentRule P_0) + { + return P_0.DateStart < ??.Date; + } + + internal bool ?(TimeZoneInfo.AdjustmentRule P_0) + { + return P_0.DateEnd > ??.Date; + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + internal bool ?(ISession P_0) + { + return P_0.ContainsDate(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + public ISessionsContainer ??; + + internal bool ?(ISession P_0) + { + return P_0.ContainsDate(??, ??.TimeZone); + } + + internal bool ?(ISession P_0) + { + return P_0.ContainsDate(??); + } + } + + public static bool ContainsDate(this ISession session, DateTime dateTime) + { + return session.ContainsTime(dateTime.TimeOfDay); + } + + public static bool ContainsDate(this ISession session, long dateTimeTicks) + { + return session.ContainsTime(dateTimeTicks % 864000000000L); + } + + public static bool ContainsTime(this ISession session, TimeSpan time) + { + return session.ContainsTime(time.Ticks); + } + + public static bool ContainsTime(this ISession session, long timeTicks) + { + if (session.OpenTime < session.CloseTime) + { + if (timeTicks < session.OpenTime.Ticks || timeTicks >= session.CloseTime.Ticks) + { + return false; + } + } + else if (timeTicks >= session.CloseTime.Ticks && timeTicks < session.OpenTime.Ticks) + { + return false; + } + return true; + } + + public static bool ContainsDate(this ISession session, DateTime dateTime, TimeZoneInfo timeZone) + { + TimeSpan time = dateTime.TimeOfDay + ?(dateTime, timeZone); + return session.ContainsTime(time); + } + + internal static TimeSpan ?(DateTime P_0, TimeZoneInfo P_1) + { + TimeSpan result = TimeSpan.Zero; + if (P_1 == null) + { + return result; + } + DateTime date = DateTime.UtcNow.Date; + if (!P_1.IsDaylightSavingTime(P_0) && P_1.IsDaylightSavingTime(date)) + { + TimeZoneInfo.AdjustmentRule adjustmentRule = (from adjustmentRule3 in P_1.GetAdjustmentRules() + where adjustmentRule3.DateStart < P_0.Date + where adjustmentRule3.DateEnd > P_0.Date + select adjustmentRule3).FirstOrDefault(); + if (adjustmentRule != null) + { + result = -adjustmentRule.DaylightDelta; + } + } + if (P_1.IsDaylightSavingTime(P_0) && !P_1.IsDaylightSavingTime(date)) + { + TimeZoneInfo.AdjustmentRule adjustmentRule2 = (from adjustmentRule3 in P_1.GetAdjustmentRules() + where adjustmentRule3.DateStart < P_0.Date + where adjustmentRule3.DateEnd > P_0.Date + select adjustmentRule3).FirstOrDefault(); + if (adjustmentRule2 != null) + { + result = adjustmentRule2.DaylightDelta; + } + } + return result; + } + + public static ISession GetSessionForDate(this ISessionsContainer sessionsContainer, DateTime dateTime) + { + ISession[] sessionsForDate = sessionsContainer.GetSessionsForDate(dateTime); + if (!sessionsForDate.Any()) + { + return null; + } + return sessionsForDate.FirstOrDefault((ISession P_0) => P_0.ContainsDate(dateTime)); + } + + public static bool ContainsDate(this ISessionsContainer sessionsContainer, DateTime dateTime) + { + ISession[] sessionsForDate = sessionsContainer.GetSessionsForDate(dateTime); + if (!sessionsForDate.Any()) + { + return false; + } + if (sessionsContainer.TimeZone != null && sessionsContainer.TimeZone.SupportsDaylightSavingTime) + { + return sessionsForDate.Any((ISession P_0) => P_0.ContainsDate(dateTime, sessionsContainer.TimeZone)); + } + return sessionsForDate.Any((ISession P_0) => P_0.ContainsDate(dateTime)); + } + + public static bool ContainsDate(this ISessionsContainer sessionsContainer, long dateTimeTicks) + { + return sessionsContainer.ContainsDate(new DateTime(dateTimeTicks, DateTimeKind.Utc)); + } + + public static long GetSessionOffset(this ISessionsContainer sessionsContainer, TimeZone timezone, bool isWeek, bool applyNegativeSignForInDaySession = true) + { + ISession session = sessionsContainer.?(); + long num = ((session == null) ? (-timezone.TimeZoneInfo.BaseUtcOffset.Ticks) : ((!(session.CloseTime >= session.OpenTime)) ? (-(TimeSpan.FromHours(24.0).Ticks - session.OpenTime.Ticks)) : (((!applyNegativeSignForInDaySession) ? 1 : (-1)) * session.OpenTime.Ticks))); + if (isWeek) + { + num += (long)(new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc).DayOfWeek - 1) * 864000000000L; + } + return num; + } + + public static long GetSessionOpenTime(this ISessionsContainer sessionsContainer, TimeZone timezone) + { + return sessionsContainer.?()?.OpenTime.Ticks ?? timezone.TimeZoneInfo.BaseUtcOffset.Ticks; + } + + private static ISession ?(this ISessionsContainer P_0) + { + if (P_0 == null) + { + return null; + } + List list = P_0.ActiveSessions?.Where((ISession session) => session.IsPrimary).ToList(); + if (list == null || list.Count == 0) + { + list = P_0.ActiveSessions?.Where((ISession session) => session.ContainsTime(TimeSpan.Zero)).ToList(); + } + if (list == null || list.Count == 0) + { + list = P_0.ActiveSessions?.Where((ISession session) => session.CloseTime > session.OpenTime).ToList(); + } + if (list == null || list.Count == 0) + { + list = P_0.ActiveSessions?.ToList(); + } + list?.Sort((ISession session, ISession session2) => session.OpenTime.CompareTo(session2.OpenTime)); + return list?.FirstOrDefault(); + } + } + public static class SettingItemExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal string ?(SettingItem P_0) + { + return P_0.Name; + } + + internal string ?(SettingItem P_0) + { + return P_0.Name; + } + + internal SettingItem ?(SettingItem P_0) + { + return P_0; + } + + internal string ?(AdditionalInfoItem P_0) + { + return P_0.Id; + } + + internal object ?(AdditionalInfoItem P_0) + { + return P_0.Value; + } + + internal SettingItem ?(SettingItem P_0) + { + return P_0.GetCopy(); + } + } + + [CompilerGenerated] + private sealed class ? + { + public SettingItem ??; + + public object ??; + + internal void ?() + { + ??.Value = ??; + } + } + + public static SettingItem GetItemByName(this IEnumerable list, string name) + { + if (string.IsNullOrEmpty(name)) + { + return null; + } + foreach (SettingItem item in list) + { + if (item != null && item.Name == name) + { + return item; + } + } + return null; + } + + public static SettingItem GetItemByPath(this IEnumerable list, params string[] pathLevels) + { + if (pathLevels == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IEnumerable list2 = list; + for (int i = 0; i < pathLevels.Length; i++) + { + string name = pathLevels[i]; + SettingItem itemByName = list2.GetItemByName(name); + if (itemByName == null) + { + return null; + } + if (i == pathLevels.Length - 1) + { + return itemByName; + } + list2 = itemByName.Value as IList; + } + return null; + } + + /// + /// Get all settings or particular settings by provided hierarchy path + /// + public static IEnumerable GetItemsByPath(this IEnumerable list, params string[] pathLevels) + { + if (pathLevels == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IEnumerable enumerable = list; + for (int i = 0; i < pathLevels.Length; i++) + { + string text = pathLevels[i]; + if (string.IsNullOrEmpty(text)) + { + return enumerable; + } + SettingItem itemByName = enumerable.GetItemByName(text); + if (itemByName == null) + { + return null; + } + if (itemByName.Value is IList list2) + { + enumerable = list2; + } + else if (i == pathLevels.Length - 1) + { + return new List { itemByName }; + } + } + return enumerable; + } + + public static bool TryGetItemByName(this IEnumerable items, string name, out SettingItem item) + { + item = items?.GetItemByName(name); + return item != null; + } + + public static void ApplyVisualGroup(this IEnumerable list, SettingItemVisualGroup visualGroup, params string[] pathLevels) + { + if (pathLevels == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IEnumerable itemsByPath = list.GetItemsByPath(pathLevels); + if (itemsByPath == null) + { + return; + } + foreach (SettingItem item in itemsByPath) + { + if (item.Type == SettingItemType.Group && item.Value is IEnumerable list2) + { + list2.ApplyVisualGroup(visualGroup); + } + else + { + item.VisualGroup = visualGroup; + } + } + } + + public static SettingItem UpdateItemValue(this IEnumerable list, string name, object newValue, bool force = false) + { + SettingItem itemByName = list.GetItemByName(name); + if (itemByName == null) + { + return null; + } + if (itemByName is SettingItemGroup && itemByName.Value is IList list2 && newValue is IList list3) + { + foreach (SettingItem item in list3) + { + list2.UpdateItemValue(item.Name, item.Value); + } + } + else + { + itemByName.?(newValue, force); + } + return itemByName; + } + + public static void UpdateValues(this IEnumerable list, IEnumerable other, bool ignoreValidation = false, params string[] filterNames) + { + if (list == null || other == null) + { + return; + } + Dictionary dictionary = other.DistinctBy((SettingItem P_0) => P_0.Name).ToDictionary((SettingItem P_0) => P_0.Name, (SettingItem P_0) => P_0); + foreach (SettingItem item in list) + { + if ((filterNames.Any() && !filterNames.Contains(item.Name)) || !dictionary.TryGetValue(item.Name, out var value)) + { + continue; + } + if (item.Value is IList list2 && value.Value is IList other2) + { + list2.UpdateValues(other2, ignoreValidation); + continue; + } + try + { + item.?(value.Value, ignoreValidation); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + public static void UpdateValues(this IEnumerable list, AdditionalInfoCollection additionalInfoCollection) + { + if (additionalInfoCollection == null) + { + return; + } + Dictionary dictionary = additionalInfoCollection.ToDictionary((AdditionalInfoItem P_0) => P_0.Id, (AdditionalInfoItem P_0) => P_0.Value); + foreach (SettingItem item in list) + { + try + { + if (dictionary.TryGetValue(item.Name, out var value)) + { + item.?(value); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + public static bool IsAny(this IEnumerable list, Predicate predicate) + { + foreach (SettingItem item in list) + { + if (predicate(item)) + { + return true; + } + if (item.Value is IList list2 && list2.IsAny(predicate)) + { + return true; + } + } + return false; + } + + public static T GetValueOrDefault(this IEnumerable settings, T defaultValue, params string[] pathLevels) + { + SettingItem itemByPath = settings.GetItemByPath(pathLevels); + if (itemByPath == null) + { + return defaultValue; + } + return itemByPath.GetValue(); + } + + public static T GetVisibleValueOrDefault(this IEnumerable settings, T defaultValue, params string[] pathLevels) + { + SettingItem itemByPath = settings.GetItemByPath(pathLevels); + if (itemByPath == null || !itemByPath.Enabled || !itemByPath.Visible) + { + return defaultValue; + } + return itemByPath.GetValue(); + } + + public static T GetValue(this IEnumerable settings, params string[] pathLevels) + { + SettingItem itemByPath = settings.GetItemByPath(pathLevels); + if (itemByPath == null) + { + return default(T); + } + return itemByPath.GetValue(); + } + + public static T GetVisibleValue(this IEnumerable settings, params string[] pathLevels) + { + SettingItem itemByPath = settings.GetItemByPath(pathLevels); + if (itemByPath == null || !itemByPath.Enabled || !itemByPath.Visible) + { + return default(T); + } + return itemByPath.GetValue(); + } + + public static T GetValue(this SettingItem item) + { + try + { + object value = item.Value; + return (!(value is SelectItem selectItem)) ? ((!(value is PasswordHolder passwordHolder)) ? ((T)item.Value) : ((T)(object)passwordHolder.Password)) : ((!(typeof(T) == typeof(string))) ? ((T)selectItem.Value) : ((T)(object)selectItem.Value?.ToString())); + } + catch + { + return default(T); + } + } + + public static bool TryGetValue(this IEnumerable settings, string name, out T value) + { + value = default(T); + SettingItem itemByName = settings.GetItemByName(name); + if (itemByName == null) + { + return false; + } + value = itemByName.GetValue(); + return true; + } + + public static bool TryGetVisibleValue(this IEnumerable settings, string name, out T value) + { + value = default(T); + SettingItem itemByName = settings.GetItemByName(name); + if (itemByName == null || !itemByName.Enabled || !itemByName.Visible) + { + return false; + } + value = itemByName.GetValue(); + return true; + } + + public static IEnumerable ExpandGroups(this IEnumerable settings) + { + if (settings == null) + { + yield break; + } + foreach (SettingItem setting in settings) + { + if (setting.Value is IEnumerable settings2) + { + foreach (SettingItem item in settings2.ExpandGroups()) + { + yield return item; + } + } + else + { + yield return setting; + } + } + } + + public static SettingItem RestoreGroupsNesting(this SettingItem settingItem) + { + List list = new List(); + ?(settingItem, list); + if (list.Count > 0) + { + (list[0].Value as IList).Add(settingItem); + for (int i = 0; i < list.Count - 1; i++) + { + (list[i + 1].Value as IList).Add(list[i]); + } + return list.Last(); + } + return settingItem; + } + + public static void MergeWith(this IList origin, IList other) + { + if (other == null) + { + return; + } + foreach (SettingItem item in other) + { + SettingItem itemByName = origin.GetItemByName(item.Name); + if (itemByName == null) + { + origin.Add(item); + } + else if ((itemByName as SettingItemGroup)?.Value is IList origin2 && (item as SettingItemGroup)?.Value is IList other2) + { + origin2.MergeWith(other2); + } + else + { + itemByName.?(item); + } + } + } + + public static IEnumerable DeepCopy(this IEnumerable settings) + { + return settings.Select((SettingItem P_0) => P_0.GetCopy()); + } + + public static void SetValueWithReason(this SettingItem settingItem, object value, SettingItemValueChangingReason reason) + { + settingItem.InvokeActionWithReason(reason, delegate + { + settingItem.Value = value; + }); + } + + public static void InvokeActionWithReason(this SettingItem settingItem, SettingItemValueChangingReason reason, Action action) + { + SettingItemValueChangingReason valueChangingReason = settingItem.ValueChangingReason; + try + { + settingItem.ValueChangingReason = reason; + action?.Invoke(); + } + finally + { + settingItem.ValueChangingReason = valueChangingReason; + } + } + + [CompilerGenerated] + internal static void ?(SettingItem P_0, ICollection P_1) + { + if (P_0.Type == SettingItemType.Group) + { + SettingItemGroup item = new SettingItemGroup(P_0.Name, new List()); + P_1.Add(item); + } + if (P_0.Group != null) + { + ?(P_0.Group, P_1); + } + } + } + public static class StrategyExtensions + { + /// + /// Write info log message + /// + public static void LogInfo(this Strategy strategy, string message) + { + strategy.Log(message); + } + + /// + /// Write trading log message + /// + public static void LogTrading(this Strategy strategy, string message) + { + strategy.Log(message, StrategyLoggingLevel.Trading); + } + + /// + /// Write error log message + /// + public static void LogError(this Strategy strategy, string message) + { + strategy.Log(message, StrategyLoggingLevel.Error); + } + } + public static class StrategyMetricExtensions + { + public static void Add(this List metrics, string name, string formattedValue) + { + metrics.Add(new StrategyMetric + { + Name = name, + FormattedValue = formattedValue + }); + } + + public static void Add(this List metrics, string name, object value) + { + metrics.Add(name, value.ToString()); + } + } + public static class StringExtensions + { + public static bool Contains(this string str1, string str2, StringComparison stringComparison) + { + return str1.IndexOf(str2, stringComparison) >= 0; + } + + public static bool TryParseEnum(this string str, Func getAttributeValue, out TEnum enumValue) where TEnum : struct, IConvertible where TAttribute : Attribute + { + if (!typeof(TEnum).IsEnum) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + enumValue = default(TEnum); + FieldInfo[] fields = enumValue.GetType().GetFields(); + foreach (FieldInfo fieldInfo in fields) + { + object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(TAttribute), inherit: false); + if (customAttributes.Length == 0) + { + continue; + } + object[] array = customAttributes; + for (int j = 0; j < array.Length; j++) + { + if (array[j] is TAttribute arg && getAttributeValue(arg) == str) + { + enumValue = (TEnum)fieldInfo.GetValue(null); + return true; + } + } + } + return false; + } + + public static string EncodeFilePathPart(this string fileName) + { + string text = fileName; + char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); + foreach (char value in invalidFileNameChars) + { + text = text.Replace($"{value}", $"{value}"); + } + return text; + } + } + public static class SymbolExtensions + { + public static ISessionsContainer FindSessionsContainer(this Symbol symbol) + { + if (symbol == null) + { + return null; + } + if (Core.Instance.CustomSessions.Assignments.TryGetSessionsContainer(symbol, out var container)) + { + return container; + } + SessionsContainer currentSessionsInfo = symbol.CurrentSessionsInfo; + if (currentSessionsInfo == null) + { + Exchange exchange = symbol.Exchange; + if (exchange == null) + { + return null; + } + currentSessionsInfo = exchange.CurrentSessionsInfo; + } + return currentSessionsInfo; + } + + public static TimeSpan GetHistoryDownloadingStep(this Symbol symbol, HistoryAggregation aggregation) + { + return symbol?.HistoryMetadata?.?(aggregation) ?? new TimeSpan(10, 0, 0, 0); + } + + public static double CalculateValue(this Symbol symbol, Side side, double price, double quantity) + { + if (symbol == null || double.IsNaN(price) || double.IsNaN(quantity)) + { + return double.NaN; + } + return (double)((side == Side.Buy) ? 1 : (-1)) * ((symbol.QuotingType == SymbolQuotingType.LotSize) ? (price * symbol.LotSize * quantity) : (price * (symbol.GetTickCost(price) / symbol.GetTickSize(price)) * quantity)); + } + + public static string GetFormattedPoints(this Symbol symbol, Side side, double closePrice, double openPrice) + { + double num = symbol.CalculatePoints(side, closePrice, openPrice); + if (double.IsNaN(num)) + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + int precision = symbol.FindVariableTick(openPrice)?.Precision ?? CoreMath.GetValuePrecision((decimal)symbol.TickSize); + return num.Format(precision); + } + + public static string GetFormattedPoints(this Symbol symbol, double points, string suffix = "points") + { + if (double.IsNaN(points)) + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + int valuePrecision = CoreMath.GetValuePrecision((decimal)symbol.TickSize); + return points.Format(valuePrecision) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + suffix; + } + + public static double CalculatePoints(this Symbol symbol, Side side, double closePrice, double openPrice) + { + if (double.IsNaN(closePrice) || double.IsNaN(openPrice)) + { + return double.NaN; + } + decimal num = (decimal)closePrice; + decimal num2 = (decimal)openPrice; + if (side != Side.Buy) + { + return (double)(num2 - num); + } + return (double)(num - num2); + } + + public static HistoricalData GetHistory(this Symbol symbol, Period period, HistoryType historyType, int itemsCount) + { + TimeSpan timeSpan = TimeSpan.FromDays(36500.0); + HistoricalData historicalData = null; + int i = 1; + long num = period.Ticks * itemsCount; + num *= 3; + num = Math.Min(timeSpan.Ticks, num); + DateTime dateTime = Core.Instance.TimeUtils.DateTimeUtcNow.AddTicks(-num); + DateTime dateTime2 = Core.Instance.TimeUtils.DateTimeUtcNow.Add(-timeSpan); + if (period >= Period.MIN1 && period <= Period.DAY1) + { + ISessionsContainer sessionsContainer = symbol.FindSessionsContainer(); + if (sessionsContainer != null) + { + int num2 = 0; + while (!sessionsContainer.ContainsDate(dateTime) && num2 < 5760) + { + dateTime = dateTime.AddTicks(-period.Ticks); + num2++; + } + } + } + int num3 = -1; + for (; historicalData == null || (dateTime > dateTime2 && 10 >= i); i++) + { + if (period.BasePeriod != BasePeriod.Tick) + { + historicalData = symbol.GetHistory(period, historyType, dateTime); + } + else + { + long ticks = ?(symbol.Connection, i); + historicalData = symbol.GetHistory(period, historyType, new DateTime(ticks, DateTimeKind.Utc)); + } + if (historicalData.Count > itemsCount || (num3 != -1 && num3 == historicalData.Count && period.BasePeriod == BasePeriod.Day)) + { + break; + } + if (historicalData.Count > 0) + { + num *= itemsCount / historicalData.Count + 1; + } + if (num >= dateTime.Ticks) + { + break; + } + dateTime = dateTime.AddTicks(-num); + num3 = historicalData.Count; + } + if (historicalData.Count > itemsCount && itemsCount != 0) + { + historicalData.CutItems(historicalData.Count - itemsCount); + } + return historicalData; + } + + public static DeltaCalculationType GetDeltaCalculationTypeForQuotes(this Symbol symbol) + { + if (!Core.Instance.SymbolsMapping.TryGetQuotesSymbol(symbol, out var quotesSymbol)) + { + return symbol.DeltaCalculationType; + } + return quotesSymbol.DeltaCalculationType; + } + + public static DeltaCalculationType GetDeltaCalculationTypeForHistory(this Symbol symbol, Period period) + { + if (!Core.Instance.SymbolsMapping.TryGetHistorySymbol(symbol, period, out var historySymbol)) + { + return symbol.DeltaCalculationType; + } + return historySymbol.DeltaCalculationType; + } + + public static DeltaCalculationType GetDeltaCalculationTypeForVolumeAnalysis(this Symbol symbol) + { + if (!Core.Instance.SymbolsMapping.TryGetVolumeAnalysisSymbol(symbol, out var volumeAnalysisSymbol)) + { + return symbol.DeltaCalculationType; + } + return volumeAnalysisSymbol.DeltaCalculationType; + } + + public static HistoryMetadata GetHistoryMetadata(this Symbol symbol) + { + if (!Core.Instance.SymbolsMapping.TryGetVolumeAnalysisSymbol(symbol, out var volumeAnalysisSymbol)) + { + return symbol.HistoryMetadata; + } + return volumeAnalysisSymbol.HistoryMetadata; + } + + public static bool TryGetTradingSymbolId(this Symbol symbol, out string tradingSymbolId) + { + tradingSymbolId = null; + if (symbol == null) + { + return false; + } + if (symbol.State == BusinessObjectState.Fake) + { + return false; + } + if (symbol.AdditionalInfo == null) + { + return false; + } + if (!symbol.AdditionalInfo.TryGetItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var item)) + { + return false; + } + tradingSymbolId = item.Value as string; + return !string.IsNullOrEmpty(tradingSymbolId); + } + + public static bool IsSameAs(this Symbol symbol, Symbol otherSymbol) + { + if (symbol.Equals(otherSymbol)) + { + return true; + } + if (symbol.TryGetTradingSymbolId(out var tradingSymbolId) && otherSymbol.Id == tradingSymbolId) + { + return true; + } + if (otherSymbol.TryGetTradingSymbolId(out tradingSymbolId) && symbol.Id == tradingSymbolId) + { + return true; + } + return false; + } + + public static Symbol GetTradingSymbol(this Symbol symbol) + { + if (!symbol.TryGetTradingSymbolId(out var tradingSymbolId)) + { + return null; + } + return Core.Instance.GetSymbol(new GetSymbolRequestParameters + { + SymbolId = tradingSymbolId + }, symbol.ConnectionId); + } + + [CompilerGenerated] + internal static long ?(Connection P_0, int P_1) + { + long ticks = P_0.HistoryMetaData.DownloadingStep_Tick.Ticks; + ticks = (long)((double)ticks * Math.Pow(2.0, --P_1)); + return Core.Instance.TimeUtils.DateTimeUtcNow.Ticks - ticks; + } + } + public static class TaskExtensions + { + public static void GetResultWithoutContextCapturing(this Task task) + { + task.ConfigureAwait(continueOnCapturedContext: false).GetAwaiter().GetResult(); + } + + public static T GetResultWithoutContextCapturing(this Task task) + { + return task.ConfigureAwait(continueOnCapturedContext: false).GetAwaiter().GetResult(); + } + } + public static class TimeInForceExtensions + { + public static string Format(this TimeInForce value, DateTime expiration = default(DateTime)) + { + if (expiration == default(DateTime)) + { + return value.ToString(); + } + switch (value) + { + case TimeInForce.GTD: + return value.ToString() + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?() + Core.Instance.TimeUtils.ConvertFromUTCToSelectedTimeZone(expiration).ToShortDateString() + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + case TimeInForce.GTT: + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 2); + defaultInterpolatedStringHandler.AppendFormatted(value.ToString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(Core.Instance.TimeUtils.ConvertFromUTCToSelectedTimeZone(expiration), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + default: + return value.ToString(); + } + } + } + public static class TradingSignalExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal DateTime ?(Symbol P_0) + { + return P_0.ExpirationDate; + } + } + + [CompilerGenerated] + private sealed class ? + { + public TradingSignal ??; + + public Func ??; + + public Func ??; + + internal bool ?(Connection P_0) + { + return P_0.VendorName == ??.VendorName; + } + + internal bool ?(Symbol P_0) + { + return P_0.Name == ??.Ticker; + } + + internal bool ?(Connection P_0) + { + if (string.IsNullOrEmpty(??.VendorName) || P_0.VendorName == ??.VendorName) + { + return P_0.??.SymbolTypes.Contains(SymbolType.Futures); + } + return false; + } + + internal bool ?(Symbol P_0) + { + return P_0.Root == ??.Root; + } + } + + public static bool TryFindSymbol(this TradingSignal tradingSignal, out Symbol symbol) + { + symbol = null; + if (!string.IsNullOrEmpty(tradingSignal.Ticker)) + { + SearchSymbolsRequestParameters searchSymbolsRequestParameters = new SearchSymbolsRequestParameters + { + FilterName = tradingSignal.Ticker + }; + IList list = ((!string.IsNullOrEmpty(tradingSignal.VendorName)) ? Core.Instance.Connections.Connected.FirstOrDefault((Connection P_0) => P_0.VendorName == tradingSignal.VendorName)?.?(searchSymbolsRequestParameters) : Core.Instance.SearchSymbols(searchSymbolsRequestParameters)); + if (list == null || !list.Any()) + { + return false; + } + symbol = list.FirstOrDefault((Symbol P_0) => P_0.Name == tradingSignal.Ticker); + } + else if (!string.IsNullOrEmpty(tradingSignal.Root)) + { + foreach (Connection item in Core.Instance.Connections.Connected.Where((Connection P_0) => (string.IsNullOrEmpty(tradingSignal.VendorName) || P_0.VendorName == tradingSignal.VendorName) && P_0.??.SymbolTypes.Contains(SymbolType.Futures))) + { + IList source = item.?(new SearchSymbolsRequestParameters + { + FilterName = tradingSignal.Root, + SymbolTypes = new SymbolType[1] { SymbolType.Futures } + }); + if (!source.Any()) + { + continue; + } + List source2 = source.Where((Symbol P_0) => P_0.Root == tradingSignal.Root).ToList(); + if (source2.Any()) + { + symbol = source2.MinBy((Symbol P_0) => P_0.ExpirationDate); + if (symbol != null) + { + break; + } + } + } + } + if (symbol != null) + { + symbol = Core.Instance.GetSymbol(symbol.CreateInfo()); + } + Symbol symbol2 = symbol; + if (symbol2 != null) + { + return symbol2.State == BusinessObjectState.Normal; + } + return false; + } + } + public static class VolumeAnalysisExtensions + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func, VolumeAnalysisData> ??; + + public static Func ??; + + internal DateTime ?(VolumeAnalysisData P_0) + { + return P_0.TimeLeft; + } + + internal VolumeAnalysisData ?(VolumeAnalysisData P_0) + { + return P_0; + } + + internal VolumeAnalysisData ?(KeyValuePair P_0) + { + return P_0.Value; + } + + internal DateTime ?(VolumeAnalysisData P_0) + { + return P_0.TimeLeft; + } + } + + public static IEnumerable AggregateVolumeAnalysis(this IEnumerable tickItems, Period period, CancellationToken cancellationToken, double minVolumeAnalysisTickSize = double.NaN) + { + if (tickItems == null) + { + yield break; + } + VolumeAnalysisData volumeAnalysisData = null; + Interval interval = default(Interval); + foreach (IVolumeTickData tickItem in tickItems) + { + if (cancellationToken.IsCancellationRequested) + { + yield break; + } + DateTime dateTime = new DateTime(tickItem.Time, DateTimeKind.Utc); + if (!interval.Contains(dateTime)) + { + if (volumeAnalysisData != null) + { + yield return volumeAnalysisData; + } + interval = period.FindInterval(dateTime); + volumeAnalysisData = null; + } + if (volumeAnalysisData == null) + { + volumeAnalysisData = new VolumeAnalysisData + { + TimeLeft = interval.From + }; + } + double num = tickItem.Price; + if (!double.IsNaN(minVolumeAnalysisTickSize)) + { + num = CoreMath.RoundToIncrement(num, minVolumeAnalysisTickSize); + } + volumeAnalysisData.Calculate(num, tickItem.Volume, Symbol.ConvertTickDirection(tickItem.TickDirection)); + } + if (volumeAnalysisData != null) + { + yield return volumeAnalysisData; + } + } + + public static IEnumerable AggregateVolumeAnalysisByAgressor(this IEnumerable tickItems, Period period, CancellationToken cancellationToken, double minVolumeAnalysisTickSize = double.NaN) + { + if (tickItems == null) + { + yield break; + } + VolumeAnalysisData volumeAnalysisData = null; + Interval interval = default(Interval); + foreach (IVolumeTickData tickItem in tickItems) + { + if (cancellationToken.IsCancellationRequested) + { + yield break; + } + DateTime dateTime = new DateTime(tickItem.Time, DateTimeKind.Utc); + if (!interval.Contains(dateTime)) + { + if (volumeAnalysisData != null) + { + yield return volumeAnalysisData; + } + interval = period.FindInterval(dateTime); + volumeAnalysisData = null; + } + if (volumeAnalysisData == null) + { + volumeAnalysisData = new VolumeAnalysisData + { + TimeLeft = interval.From + }; + } + double num = tickItem.Price; + if (!double.IsNaN(minVolumeAnalysisTickSize)) + { + num = CoreMath.RoundToIncrement(num, minVolumeAnalysisTickSize); + } + volumeAnalysisData.Calculate(num, tickItem.Volume, tickItem.AggressorFlag); + } + if (volumeAnalysisData != null) + { + yield return volumeAnalysisData; + } + } + + public static IEnumerable AggregateVolumeAnalysis(this IEnumerable dataItems, Period period, CancellationToken cancellationToken) + { + if (dataItems == null) + { + yield break; + } + VolumeAnalysisData volumeAnalysisData = null; + Interval interval = default(Interval); + foreach (VolumeAnalysisData dataItem in dataItems) + { + if (cancellationToken.IsCancellationRequested) + { + yield break; + } + DateTime timeLeft = dataItem.TimeLeft; + if (!interval.Contains(timeLeft)) + { + if (volumeAnalysisData != null) + { + yield return volumeAnalysisData; + } + interval = period.FindInterval(timeLeft); + volumeAnalysisData = null; + } + if (volumeAnalysisData == null) + { + volumeAnalysisData = new VolumeAnalysisData + { + TimeLeft = interval.From + }; + } + volumeAnalysisData.Combine(dataItem); + } + if (volumeAnalysisData != null) + { + yield return volumeAnalysisData; + } + } + + public static IList Combine(this IEnumerable dataItems, IEnumerable anotherItems) + { + Dictionary dictionary = dataItems.ToDictionary((VolumeAnalysisData P_0) => P_0.TimeLeft, (VolumeAnalysisData P_0) => P_0); + foreach (VolumeAnalysisData anotherItem in anotherItems) + { + if (dictionary.TryGetValue(anotherItem.TimeLeft, out var value)) + { + value.Combine(anotherItem); + } + else + { + dictionary.Add(anotherItem.TimeLeft, anotherItem); + } + } + return (from P_0 in dictionary + select P_0.Value into P_0 + orderby P_0.TimeLeft + select P_0).ToList(); + } + + public static VolumeAnalysisData Collapse(this IEnumerable dataItems) + { + VolumeAnalysisData volumeAnalysisData = new VolumeAnalysisData(); + foreach (VolumeAnalysisData dataItem in dataItems) + { + volumeAnalysisData.Combine(dataItem); + } + return volumeAnalysisData; + } + } + public static class XElementExtensions + { + public static bool ToBool(this XElement element) + { + if (!bool.TryParse(element.Value, out var result)) + { + return false; + } + return result; + } + + public static int ToInt(this XElement element) + { + if (!int.TryParse(element.Value, out var result)) + { + return 0; + } + return result; + } + + public static long ToLong(this XElement element) + { + if (!long.TryParse(element.Value, out var result)) + { + return 0L; + } + return result; + } + + public static double ToDouble(this XElement element) + { + if (!double.TryParse(element.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) + { + return 0.0; + } + return result; + } + + public static decimal ToDecimal(this XElement element) + { + if (!decimal.TryParse(element.Value, out var result)) + { + return 0m; + } + return result; + } + + public static DateTime ToDateTime(this XElement element, bool toUTC = false) + { + if (DateTime.TryParse(element.Value, out var result)) + { + if (!toUTC) + { + return result; + } + return result.ToUniversalTime(); + } + return default(DateTime); + } + + public static DateTime ToDateTime(this XElement element, string format) + { + if (DateTime.TryParseExact(element.Value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) + { + return DateTime.SpecifyKind(result, DateTimeKind.Utc); + } + return default(DateTime); + } + + public static TimeSpan ToTimeSpan(this XElement element) + { + if (!TimeSpan.TryParse(element.Value, out var result)) + { + return default(TimeSpan); + } + return result; + } + + public static Color ToColor(this XElement element) + { + if (string.IsNullOrEmpty(element.Value)) + { + return Color.Empty; + } + int num = element.Value.IndexOf(','); + int num2 = element.Value.IndexOf(',', num + 1); + int num3 = element.Value.IndexOf(',', num2 + 1); + return Color.FromArgb(int.Parse(element.Value.Substring(num3 + 1, element.Value.Length - num3 - 1)), int.Parse(element.Value.Substring(0, num)), int.Parse(element.Value.Substring(num + 1, num2 - num - 1)), int.Parse(element.Value.Substring(num2 + 1, num3 - num2 - 1))); + } + + public static XElement ToXElement(this Color color, string nodeName = "Color") + { + XName? name = nodeName; + string content; + if (!color.IsEmpty) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4); + defaultInterpolatedStringHandler.AppendFormatted(color.R); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(color.G); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(color.B); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(color.A); + content = defaultInterpolatedStringHandler.ToStringAndClear(); + } + else + { + content = string.Empty; + } + return new XElement(name, content); + } + + public static Font ToFont(this XElement element) + { + if (string.IsNullOrEmpty(element.Value)) + { + return null; + } + int num = element.Value.IndexOf(','); + int num2 = element.Value.IndexOf(',', num + 1); + int num3 = element.Value.IndexOf(',', num2 + 1); + float.TryParse(element.Value.Substring(num + 1, num2 - num - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result); + return new Font(element.Value.Substring(0, num), result, (FontStyle)int.Parse(element.Value.Substring(num2 + 1, num3 - num2 - 1)), (GraphicsUnit)int.Parse(element.Value.Substring(num3 + 1, element.Value.Length - num3 - 1))); + } + + public static XElement ToXElement(this Font font, string nodeName = "Font") + { + XName? name = nodeName; + string content; + if (font != null) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4); + defaultInterpolatedStringHandler.AppendFormatted(font.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(font.Size.ToString(CultureInfo.InvariantCulture)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((int)font.Style); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((int)font.Unit); + content = defaultInterpolatedStringHandler.ToStringAndClear(); + } + else + { + content = string.Empty; + } + return new XElement(name, content); + } + } + public interface IRenamable + { + string Name { get; set; } + + bool IsNameAllowed(string s, ref string error); + } + public class Renamable : IRenamable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Converter ??; + + internal string ?(string P_0) + { + return P_0.ToLower(); + } + } + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private List ??; + + public bool AllowFileSystemForbiddenSymbols = true; + + [CompilerGenerated] + private string ??; + + public bool AllowEmptyName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public List ExcludeNames + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool IsNameAllowed(string s, ref string error) + { + if (!AllowEmptyName && string.IsNullOrWhiteSpace(s)) + { + error = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return false; + } + if (ExcludeNames != null && ExcludeNames.ConvertAll((string P_0) => P_0.ToLower()).ToArray().Contains(s.ToLower())) + { + error = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return false; + } + char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); + if (s.IndexOfAny(invalidFileNameChars) != -1) + { + string text = string.Empty; + string text2 = string.Empty; + char[] array = invalidFileNameChars; + foreach (char c in array) + { + if (char.IsWhiteSpace(c) || char.IsControl(c)) + { + string text3 = text2; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((int)c); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + text2 = text3 + defaultInterpolatedStringHandler.ToStringAndClear(); + } + else + { + string text4 = text; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 1); + defaultInterpolatedStringHandler.AppendFormatted(c); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + text = text4 + defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + text2 = text2.Trim(); + text2 = text2.Trim(','); + text += text2; + error = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + text; + return false; + } + error = string.Empty; + return true; + } + } + /// + /// The application logger event. + /// + public class ApplicationLoggerEvent : LoggerEvent + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public string Message + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ConnectionName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } +} +namespace ? +{ + internal class ? + { + [CompilerGenerated] + private LoggingLevel ??; + + [Option('l', "log", Required = false, HelpText = "Set logging level")] + public LoggingLevel LoggingLevel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = loggingLevel; + } + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public interface ILoggable + { + string Event { get; } + + string Message { get; } + } + public interface ILogger : IDisposable + { + LoggerScope AllowedScopes { get; } + + void Configure(LoggerConfig loggerConfig); + + void Log(string message, DateTime date, LoggingLevel level = LoggingLevel.System, string connection = null); + + void Log(string message, Exception exception, DateTime date, LoggingLevel level = LoggingLevel.Error, string connection = null); + + void Log(Exception exception, DateTime date, LoggingLevel level = LoggingLevel.Error, string connection = null); + + void Log(ILoggable loggable, DateTime date, LoggingLevel level = LoggingLevel.Error, string connection = null); + + List GetHistory(DateTime from, DateTime to); + + void DeleteLogFilesExcept(DateTime from, DateTime to); + } + [Flags] + public enum LoggerScope + { + Hidden = 0, + Application = 1, + General = 2, + LocalCopyTrading = 4 + } + public class LocalCopyTradingLoggerEvent : LoggerEvent + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private PlaceOrderRequestParameters ??; + + public string ConnectionName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public PlaceOrderRequestParameters OrderRequestParameters + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public class Loggable : ILoggable + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly string ??; + + public string Event + { + [CompilerGenerated] + get + { + return ??; + } + } + + public string Message + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Loggable(string @event, string message) + { + ?? = @event; + ?? = message; + } + } + public record LoggerConfig + { + public string LoggerName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string OutputFolderPath + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public LoggerScope Scope + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private LoggerScope ??; + + [CompilerGenerated] + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (PrintMembers(stringBuilder)) + { + stringBuilder.Append(' '); + } + stringBuilder.Append('}'); + return stringBuilder.ToString(); + } + + [CompilerGenerated] + protected virtual bool PrintMembers(StringBuilder builder) + { + RuntimeHelpers.EnsureSufficientExecutionStack(); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append((object?)LoggerName); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append((object?)OutputFolderPath); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(Scope.ToString()); + return true; + } + } +} +namespace ? +{ + internal class ? : ILogger, IDisposable + { + [CompilerGenerated] + private readonly LoggerScope ??; + + private readonly ICollection ??; + + public LoggerScope AllowedScopes + { + [CompilerGenerated] + get + { + return ??; + } + } + + public ?(ICollection P_0) + { + ?? = new List(); + foreach (ILogger item in P_0) + { + ??.Add(item); + } + } + + public void Configure(LoggerConfig loggerConfig) + { + foreach (ILogger item in ??) + { + try + { + item.Configure(loggerConfig); + } + catch (Exception) + { + } + } + } + + public void Log(string message, DateTime date, LoggingLevel level = LoggingLevel.System, string connection = null) + { + foreach (ILogger item in ??) + { + try + { + item.Log(message, date, level, connection); + } + catch (Exception) + { + } + } + } + + public void Log(string message, Exception exception, DateTime date, LoggingLevel level = LoggingLevel.Error, string connection = null) + { + foreach (ILogger item in ??) + { + try + { + item.Log(message, exception, date, level, connection); + } + catch (Exception) + { + } + } + } + + public void Log(Exception exception, DateTime date, LoggingLevel level = LoggingLevel.Error, string connection = null) + { + foreach (ILogger item in ??) + { + try + { + item.Log(exception, date, level, connection); + } + catch (Exception) + { + } + } + } + + public void Log(ILoggable loggable, DateTime date, LoggingLevel level = LoggingLevel.Error, string connection = null) + { + foreach (ILogger item in ??) + { + try + { + item.Log(loggable, date, level, connection); + } + catch (Exception) + { + } + } + } + + public List GetHistory(DateTime from, DateTime to) + { + List list = new List(); + ILogger logger = ??.FirstOrDefault(); + if (logger != null) + { + list.AddRange(logger.GetHistory(from, to)); + } + return list; + } + + public void DeleteLogFilesExcept(DateTime from, DateTime to) + { + foreach (ILogger item in ??) + { + item.DeleteLogFilesExcept(from, to); + } + } + + public void Dispose() + { + foreach (ILogger item in ??) + { + item.Dispose(); + } + ??.Clear(); + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public class LoggerEvent + { + [CompilerGenerated] + private LoggingLevel ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + public LoggingLevel Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime Date + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Event + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public sealed class LoggerManager : BufferedProcessor, IDisposable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Action ??; + + public static Func ??; + + public static Func ??; + + public static Predicate ??; + + internal void ?(ParserSettings P_0) + { + P_0.IgnoreUnknownArguments = true; + } + + internal bool ?(TypeWrapper P_0) + { + return !P_0.Type.IsAbstract; + } + + internal Type ?(TypeWrapper P_0) + { + return P_0.Type; + } + + internal bool ?(ILogger P_0) + { + return P_0 == null; + } + } + + [CompilerGenerated] + private sealed class ? + { + public LoggerManager ??; + + public string ??; + + public LoggingLevel ??; + + public string ??; + + internal void ?() + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ??.???.Log(??, dateTimeUtcNow, ??, ??); + ApplicationLoggerEvent applicationLoggerEvent = new ApplicationLoggerEvent + { + Date = dateTimeUtcNow, + Type = ??, + Event = ??, + Message = string.Empty, + ConnectionName = ?? + }; + ??.?(applicationLoggerEvent); + ??.?(dateTimeUtcNow, ??, string.Empty); + } + } + + [CompilerGenerated] + private sealed class ? + { + public LoggerManager ??; + + public string ??; + + public Exception ??; + + public LoggingLevel ??; + + public string ??; + + internal void ?() + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ??.???.Log(??, ??, dateTimeUtcNow, ??, ??); + ApplicationLoggerEvent applicationLoggerEvent = new ApplicationLoggerEvent + { + Date = dateTimeUtcNow, + Type = ??, + Event = ??, + Message = GetFormattedErrorMessage(??), + ConnectionName = ?? + }; + ??.?(applicationLoggerEvent); + ??.?(dateTimeUtcNow, ??, ??.Message); + } + } + + [CompilerGenerated] + private sealed class ? + { + public LoggerManager ??; + + public ILoggable ??; + + public LoggingLevel ??; + + public string ??; + + internal void ?() + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ??.??.Log(??, dateTimeUtcNow, ??, ??); + ApplicationLoggerEvent applicationLoggerEvent = new ApplicationLoggerEvent + { + Date = dateTimeUtcNow, + Type = ??, + Event = ??.Event, + Message = ??.Message, + ConnectionName = ?? + }; + ??.?(applicationLoggerEvent); + ??.?(dateTimeUtcNow, ??.Event, ??.Message); + } + } + + [CompilerGenerated] + private sealed class ? + { + public LoggerManager ??; + + public string ??; + + public DateTime ??; + + internal void ?() + { + ??.?(??, ??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public ILogger ??; + + public DateTime ??; + + public DateTime ??; + + internal void ?() + { + ??.DeleteLogFilesExcept(??, ??); + } + } + + private const int ?? = 864000; + + private const int ?? = 600; + + private const string ?? = "Loggers"; + + private int ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private LoggingLevel ??; + + private ILogger ??; + + private readonly List ??; + + private readonly List ??; + + private readonly List ??; + + public bool EnableAutoDeleting + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int AutoDeletePeriod + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Current logging level + /// + public LoggingLevel CurrentLogLevel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = loggingLevel; + } + } + + public event Action NewLog + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public LoggerManager() + { + AutoDeletePeriod = 30; + EnableAutoDeleting = true; + ?? = 863400; + ?? = new List(); + ?? = new List(); + ?? = new List(); + CurrentLogLevel = LoggingLevel.System | LoggingLevel.Error | LoggingLevel.Trading; + new Parser(delegate(ParserSettings P_0) + { + P_0.IgnoreUnknownArguments = true; + }).ParseArguments(Environment.GetCommandLineArgs()).WithParsed(delegate(? P_0) + { + AddLogLevel(P_0.LoggingLevel); + }).WithNotParsed(delegate(IEnumerable P_0) + { + foreach (Error item in P_0) + { + Log(item.ToString(), LoggingLevel.Error); + } + }); + } + + internal void ?() + { + List list = AssemblyLoader.LoadTypes(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), typeof(ILogger), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchOption.AllDirectories); + if (list != null) + { + ??.AddRange(from P_0 in list + where !P_0.Type.IsAbstract + select P_0.Type); + ?? = GetLogger(new LoggerConfig + { + LoggerName = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + OutputFolderPath = Path.Combine(Directory.GetParent(Const.EXECUTING_FOLDER).FullName, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Scope = LoggerScope.Application + }); + Start(); + Core.Instance.?(?); + } + } + + public void Dispose() + { + Core.Instance.?(?); + Stop(); + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + } + + public ILogger GetLogger(LoggerConfig loggerConfig) + { + List list = new List(); + foreach (Type item in ??) + { + ILogger logger = (ILogger)Activator.CreateInstance(item); + if (logger.AllowedScopes.HasFlag(loggerConfig.Scope)) + { + list.Add(logger); + } + } + ? ? = new ?(list); + ?.Configure(loggerConfig); + ?(?); + return ?; + } + + /// + /// Sets logs with custom messag, logging level, connection name + /// + public void Log(string message, LoggingLevel loggingLevel = LoggingLevel.System, string connectionName = null) + { + if (?(loggingLevel)) + { + Push(delegate + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ???.Log(message, dateTimeUtcNow, loggingLevel, connectionName); + ApplicationLoggerEvent applicationLoggerEvent = new ApplicationLoggerEvent + { + Date = dateTimeUtcNow, + Type = loggingLevel, + Event = message, + Message = string.Empty, + ConnectionName = connectionName + }; + ?(applicationLoggerEvent); + ?(dateTimeUtcNow, message, string.Empty); + }); + } + } + + /// + /// Sets logs with exception and custom message (optional), logging level, connection name + /// + public void Log(Exception ex, string message = null, LoggingLevel loggingLevel = LoggingLevel.Error, string connectionName = null) + { + if (!(ex is ThreadAbortException) && ?(loggingLevel)) + { + Push(delegate + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ???.Log(message, ex, dateTimeUtcNow, loggingLevel, connectionName); + ApplicationLoggerEvent applicationLoggerEvent = new ApplicationLoggerEvent + { + Date = dateTimeUtcNow, + Type = loggingLevel, + Event = message, + Message = GetFormattedErrorMessage(ex), + ConnectionName = connectionName + }; + ?(applicationLoggerEvent); + ?(dateTimeUtcNow, message, ex.Message); + }); + } + } + + /// + /// Sets logs with objects inherited from ILoggable interface,logging level, connection name + /// + public void Log(ILoggable loggable, LoggingLevel loggingLevel = LoggingLevel.System, string connectionName = null) + { + if (loggable == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (?(loggingLevel)) + { + Push(delegate + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ??.Log(loggable, dateTimeUtcNow, loggingLevel, connectionName); + ApplicationLoggerEvent applicationLoggerEvent = new ApplicationLoggerEvent + { + Date = dateTimeUtcNow, + Type = loggingLevel, + Event = loggable.Event, + Message = loggable.Message, + ConnectionName = connectionName + }; + ?(applicationLoggerEvent); + ?(dateTimeUtcNow, loggable.Event, loggable.Message); + }); + } + } + + public void Log(string @event, string message, LoggingLevel loggingLevel = LoggingLevel.System, string connectionName = null) + { + Log(new Loggable(@event, message), loggingLevel, connectionName); + } + + private void ?(ApplicationLoggerEvent P_0) + { + ???.Invoke(P_0); + } + + /// + /// Sets a log level in case of deep debug + /// + public void AddLogLevel(LoggingLevel loggingLevel) + { + CurrentLogLevel |= loggingLevel; + } + + /// + /// Remove a log level if one has not needed already + /// + public void RemoveLogLevel(LoggingLevel loggingLevel) + { + CurrentLogLevel &= ~loggingLevel; + } + + public List GetHistory(DateTime from, DateTime to) + { + List list = new List(); + if (?? != null) + { + list.AddRange(??.GetHistory(from, to).OfType()); + } + return list; + } + + /// + /// Manage files existence in folder. + /// + public void RegisterExternalLogFolder(string path) + { + if (!Directory.Exists(path)) + { + return; + } + if (!??.Contains(path)) + { + ??.Add(path); + } + if (EnableAutoDeleting && ?? < 863400) + { + DateTime ?? = Core.Instance.TimeUtils.DateTimeUtcNow.AddDays(-AutoDeletePeriod); + Push(delegate + { + ?(path, ??); + }); + } + } + + private void ?() + { + if (?? == null || !EnableAutoDeleting) + { + return; + } + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + DateTime dateTime = dateTimeUtcNow.AddDays(-AutoDeletePeriod); + foreach (ILogger item in ??) + { + item?.DeleteLogFilesExcept(dateTime, dateTimeUtcNow); + } + foreach (string item2 in ??) + { + ?(item2, dateTime); + } + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + private void ?(string P_0, DateTime P_1) + { + if (string.IsNullOrEmpty(P_0)) + { + return; + } + try + { + if (!Directory.Exists(P_0)) + { + return; + } + string[] files = Directory.GetFiles(P_0); + foreach (string text in files) + { + FileInfo fileInfo = new FileInfo(text); + if (fileInfo.CreationTimeUtc < P_1 || fileInfo.LastWriteTime < P_1) + { + File.Delete(text); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + private void ?(ILogger P_0) + { + ??.RemoveAll((ILogger logger) => logger == null); + ??.Add(P_0); + if (EnableAutoDeleting && ?? < 863400) + { + DateTime ?? = Core.Instance.TimeUtils.DateTimeUtcNow; + DateTime ?? = ??.AddDays(-AutoDeletePeriod); + Push(delegate + { + P_0.DeleteLogFilesExcept(??, ??); + }); + } + } + + private void ?() + { + if (?? < 864000) + { + ??++; + return; + } + Push(?); + ?? = 0; + } + + private bool ?(LoggingLevel P_0) + { + if (!CurrentLogLevel.HasFlag(P_0)) + { + return (LoggingLevel.System | LoggingLevel.Error | LoggingLevel.Trading | LoggingLevel.LoadingHistory).HasFlag(P_0); + } + return true; + } + + private void ?(DateTime P_0, string P_1, string P_2) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 1); + defaultInterpolatedStringHandler.AppendFormatted(P_0, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + StringBuilder stringBuilder = new StringBuilder(defaultInterpolatedStringHandler.ToStringAndClear()); + if (!string.IsNullOrEmpty(P_1)) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(P_1); + stringBuilder3.Append(ref handler); + } + if (!string.IsNullOrEmpty(P_2)) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(P_2); + stringBuilder4.Append(ref handler); + } + } + + protected override void Process(Action subject) + { + subject?.Invoke(); + } + + protected static string GetFormattedErrorMessage(Exception ex) + { + return new StringBuilder().Append(ex.Message).Append(' ').Append(ex.StackTrace) + .Replace(Environment.NewLine, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + .ToString(); + } + + [CompilerGenerated] + private void ?(? P_0) + { + AddLogLevel(P_0.LoggingLevel); + } + + [CompilerGenerated] + private void ?(IEnumerable P_0) + { + foreach (Error item in P_0) + { + Log(item.ToString(), LoggingLevel.Error); + } + } + } + /// + /// ??? ?????????, ??????? ????? ?????????????? ??? ???????? email + /// + public class EmailParameters + { + public string[] address; + + public string subject; + + public string text; + + public string[] fileNames; + + public bool asFile; + + public SendMailCallbackDelegate callBack; + } + public delegate void SendMailCallbackDelegate(EmailSendCompletedResult result); + public class EmailSendCompletedResult + { + public EmailSendCompletedStatus Status; + + public string Message; + + public void SetError(Exception ex) + { + Message = ex.Message; + Status = EmailSendCompletedStatus.Failure; + } + } + public enum EmailSendCompletedStatus + { + Success, + Failure + } + public class MailUtils : ICustomizable + { + [CompilerGenerated] + private sealed class ? + { + public MailUtils ??; + + public EmailParameters ??; + + internal void ?() + { + try + { + ??.?(??); + } + catch (Exception error) + { + if (??.callBack != null) + { + EmailSendCompletedResult emailSendCompletedResult = new EmailSendCompletedResult(); + emailSendCompletedResult.SetError(error); + ??.callBack(emailSendCompletedResult); + } + } + } + } + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + public bool MailUseSSLConnection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public string MailLogin + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string MailPassword + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public int MailSMTPServerTimeout + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public string MailSMTPServer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public int MailSMTPPort + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public IList Settings + { + get + { + List list = new List(); + list.Add(new SettingItemBoolean(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MailUseSSLConnection) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = 10 + }); + if (MailLogin != null) + { + list.Add(new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MailLogin) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = 30 + }); + } + if (MailPassword != null) + { + list.Add(new SettingItemPassword(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new PasswordHolder(MailPassword, SavePassword: true, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = 40 + }); + } + list.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MailSMTPServerTimeout) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = 50, + Minimum = 0, + Maximum = int.MaxValue, + Increment = 1 + }); + if (MailSMTPServer != null) + { + list.Add(new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MailSMTPServer) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = 70 + }); + } + list.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MailSMTPPort) + { + Text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = 80, + Minimum = 0, + Maximum = int.MaxValue, + Increment = 1 + }); + return list; + } + set + { + if (value == null) + { + return; + } + foreach (SettingItem value2 in new SettingsHolder(value).Values) + { + string name = value2.Name; + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (!(name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + MailSMTPPort = (int)value2.Value; + } + } + else + { + MailSMTPServer = (string)value2.Value; + } + } + else + { + MailSMTPServerTimeout = (int)value2.Value; + } + } + else + { + MailPassword = (value2.Value as PasswordHolder).Password; + } + } + else + { + MailLogin = (string)value2.Value; + } + } + else + { + MailUseSSLConnection = (bool)value2.Value; + } + } + } + } + + private void ?(EmailParameters P_0) + { + EmailSendCompletedResult emailSendCompletedResult = new EmailSendCompletedResult(); + MailMessage mailMessage = new MailMessage(); + SmtpClient smtpClient = null; + try + { + if (string.IsNullOrEmpty(MailLogin)) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + mailMessage.From = new MailAddress(MailLogin); + mailMessage.Subject = P_0.subject; + if (P_0.address != null) + { + string[] address = P_0.address; + foreach (string addresses in address) + { + mailMessage.To.Add(addresses); + } + } + AlternateView item = AlternateView.CreateAlternateViewFromString(P_0.text, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + string text = P_0.text; + if (text != null) + { + text = text.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + text = text.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (P_0.fileNames != null) + { + if (!P_0.asFile) + { + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + for (int j = 0; j < P_0.fileNames.Length; j++) + { + text = text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + j + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + AlternateView alternateView = AlternateView.CreateAlternateViewFromString(text, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + for (int k = 0; k < P_0.fileNames.Length; k++) + { + if (P_0.fileNames[k] != null) + { + LinkedResource linkedResource = new LinkedResource(P_0.fileNames[k]); + linkedResource.ContentId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + k; + alternateView.LinkedResources.Add(linkedResource); + } + } + mailMessage.AlternateViews.Add(item); + mailMessage.AlternateViews.Add(alternateView); + } + else + { + mailMessage.AlternateViews.Add(item); + string[] address = P_0.fileNames; + foreach (string fileName in address) + { + mailMessage.Attachments.Add(new Attachment(fileName)); + } + } + } + else + { + AlternateView item2 = AlternateView.CreateAlternateViewFromString(text, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + mailMessage.AlternateViews.Add(item); + mailMessage.AlternateViews.Add(item2); + } + smtpClient = new SmtpClient(MailSMTPServer) + { + Credentials = new NetworkCredential(mailMessage.From.Address, MailPassword), + EnableSsl = MailUseSSLConnection, + Port = MailSMTPPort, + Timeout = MailSMTPServerTimeout + }; + smtpClient.Send(mailMessage); + emailSendCompletedResult.Status = EmailSendCompletedStatus.Success; + } + catch (Exception error) + { + emailSendCompletedResult.SetError(error); + } + finally + { + mailMessage?.Dispose(); + smtpClient?.Dispose(); + P_0.callBack?.Invoke(emailSendCompletedResult); + } + } + + /// + /// ???????? ????????? ?? E-mail + /// + public void SendAsync(EmailParameters parameters) + { + Task.Factory.StartNew(delegate + { + try + { + ?(parameters); + } + catch (Exception error) + { + if (parameters.callBack != null) + { + EmailSendCompletedResult emailSendCompletedResult = new EmailSendCompletedResult(); + emailSendCompletedResult.SetError(error); + parameters.callBack(emailSendCompletedResult); + } + } + }); + } + + internal void ?() + { + } + } + [Serializable] + public class PairColor : IXElementSerialization, IEquatable + { + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public Color Color1 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color Color2 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Text1 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Text2 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public PairColor() + { + } + + public PairColor(Color color1, Color color2, string text1 = null, string text2 = null) + { + Color1 = color1; + Color2 = color2; + Text1 = text1; + Text2 = text2; + } + + public XElement ToXElement() + { + return new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Color1.ToXElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), Color2.ToXElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Color1 = xElement.ToColor(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Color2 = xElement2.ToColor(); + } + } + + public bool Equals(PairColor other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Color1.Equals(other.Color1) && Color2.Equals(other.Color2) && Text1 == other.Text1) + { + return Text2 == other.Text2; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((PairColor)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Color1, Color2, Text1, Text2); + } + } + public class PublishedAttribute : Attribute + { + } + public class NotPublishedAttribute : Attribute + { + } + public static class loc + { + private const string ?? = "CoreLocarizer"; + + public const string HIDDEN = "#hidden#"; + + private static ? ??; + + private static Dictionary ?? = new Dictionary(); + + private static CultureInfo DefaultCultureInfo => CultureInfo.CurrentUICulture; + + private static CultureInfo TerminalCultureInfo => CultureInfo.DefaultThreadCurrentUICulture; + + /// + /// + /// + public static void OnLocaleChanged() + { + foreach (? value in ??.Values) + { + value.?(TerminalCultureInfo); + } + ???.?(TerminalCultureInfo); + } + + private static ? ?(string P_0, string P_1) + { + return new ? + { + DirectoryPath = Path.GetDirectoryName(P_0), + Name = P_1 + }; + } + + /// + /// ?????, ?? ?????? ??? ??????? xgettext.exe + /// + /// + /// + public static string key(string text) + { + return text; + } + + public static string _(string text, string pluginFolderName = null, [CallerFilePath] string callerFilePath = null) + { + if (string.IsNullOrWhiteSpace(text)) + { + return string.Empty; + } + string empty = string.Empty; + string text2 = text; + empty = ((!string.IsNullOrWhiteSpace(pluginFolderName)) ? pluginFolderName : ?(callerFilePath)); + if (!string.IsNullOrWhiteSpace(empty)) + { + if (??.ContainsKey(empty) && ??[empty].Catalog.Translations.ContainsKey(text)) + { + text2 = ??[empty].Catalog.GetString(text); + } + if (!text2.Equals(text)) + { + return text2; + } + } + if (?? != null && ??.Catalog.Translations.ContainsKey(text)) + { + text2 = ??.Catalog.GetString(text); + } + return text2; + } + + /// + /// Check, whether current translation equal to hidden + /// + public static bool IsHidden(string text, string pluginFolderName = null, [CallerFilePath] string callerFilePath = null) + { + try + { + if (string.IsNullOrWhiteSpace(text)) + { + return false; + } + if (text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return true; + } + string empty = string.Empty; + bool flag = false; + empty = ((!string.IsNullOrWhiteSpace(pluginFolderName)) ? pluginFolderName : ?(callerFilePath)); + if (!string.IsNullOrWhiteSpace(empty)) + { + if (??.ContainsKey(empty) && ??[empty].CatalogEN.Translations.ContainsKey(text)) + { + flag = ??[empty].CatalogEN.GetString(text) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + if (flag) + { + return flag; + } + } + if (?? != null && ??.CatalogEN.Translations.ContainsKey(text)) + { + flag = ??.CatalogEN.GetString(text) == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return flag; + } + catch + { + return false; + } + } + + private static string ?(string P_0) + { + if (P_0 == null) + { + return string.Empty; + } + foreach (string item in Path.GetDirectoryName(P_0).Split(Path.DirectorySeparatorChar).Reverse()) + { + if (??.ContainsKey(item)) + { + return item; + } + } + return string.Empty; + } + + /// + /// + /// + /// + public static void UnRegisterPlugin(string pluginName) + { + if (??.ContainsKey(pluginName)) + { + ? ? = ??[pluginName]; + ?.?(); + if (?.AttachedPluginCounter <= 0) + { + ??.Remove(pluginName); + } + } + } + + /// + /// + /// + /// + /// + public static void RegisterPlugin(string pluginName, string location) + { + if (!??.ContainsKey(pluginName)) + { + ? ? = ?(location, pluginName); + ??[pluginName] = new ?(TerminalCultureInfo ?? DefaultCultureInfo, ?); + } + } + + /// + /// + /// + public static void InitializeCoreLocalizer() + { + ? ? = ?(Assembly.GetCallingAssembly().Location, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?? = new ?(TerminalCultureInfo ?? DefaultCultureInfo, ?); + } + } +} +namespace ? +{ + internal class ? + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public string DirectoryPath + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + } + internal class ? + { + private const string ?? = "locale"; + + private ? ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private Catalog ??; + + [CompilerGenerated] + private Catalog ??; + + internal int AttachedPluginCounter + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + internal Catalog Catalog + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = catalog; + } + } + + internal Catalog CatalogEN + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = catalog; + } + } + + internal ?(CultureInfo P_0, ? P_1) + { + Catalog = new Catalog(); + AttachedPluginCounter = 0; + ?? = P_1; + ?(); + ?(P_0); + ?(); + } + + internal void ?(CultureInfo P_0) + { + Catalog = new Catalog(); + if (P_0 != null) + { + string text = ?(??, P_0); + if (File.Exists(text)) + { + MoLoader loader = new MoLoader(text); + Catalog = new Catalog(loader); + } + } + } + + internal void ?() + { + AttachedPluginCounter++; + } + + internal void ?() + { + AttachedPluginCounter--; + } + + private string ?(? P_0, CultureInfo P_1) + { + return Path.Combine(P_0.DirectoryPath, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_1.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + private void ?() + { + CatalogEN = new Catalog(); + try + { + CultureInfo cultureInfo = CultureInfo.GetCultureInfo(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + string text = ?(??, cultureInfo); + if (File.Exists(text)) + { + MoLoader loader = new MoLoader(text); + CatalogEN = new Catalog(loader); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CatalogEN = new Catalog(); + } + } + } +} +namespace TradingPlatform.BusinessLayer +{ + /// + /// Allows to save Symbols into named lists + /// + public class SymbolList : IComparable, ICustomizable, IRenamable + { + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(SymbolList P_0) + { + return P_0.Name == ??; + } + } + + [CompilerGenerated] + private bool ??; + + private string ??; + + [CompilerGenerated] + private string ??; + + private List ??; + + public bool AllowToModify + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public string Name + { + get + { + return ??; + } + set + { + if (AllowToModify) + { + if (Core.Instance.SymbolList.FirstOrDefault((SymbolList P_0) => P_0.Name == ??) != null) + { + Core.Instance.RenameSymbolList(??, value); + } + else + { + Core.Instance.AddSymbolList(value, Symbols); + } + } + } + } + + public string Group + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IEnumerable Symbols + { + get + { + foreach (BusinessObjectInfo item in ??) + { + yield return new Symbol(item); + } + } + set + { + ??.Clear(); + foreach (Symbol item in value) + { + ??.Add(item.CreateInfo()); + } + } + } + + public IList Settings + { + get + { + List list = new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name) + }; + foreach (Symbol symbol in Symbols) + { + list.Add(new SettingItemSymbol(symbol.Name, symbol)); + } + return list; + } + set + { + List list = new List(); + foreach (SettingItem item in value) + { + if (item.Type == SettingItemType.Symbol) + { + list.Add(item.Value as Symbol); + } + else if (item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + ?(item.Value as string); + } + } + if (list.Count > 0) + { + Symbols = list; + } + } + } + + public bool IsNameAllowed(string s, ref string error) + { + if (string.IsNullOrWhiteSpace(s)) + { + error = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return false; + } + if (Name != s && Core.Instance.SymbolList.Any((SymbolList P_0) => P_0.Name == s)) + { + error = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return false; + } + return true; + } + + public IEnumerable GetRealSymbols() + { + foreach (BusinessObjectInfo item in ??) + { + yield return Core.Instance.GetSymbol(item); + } + } + + internal SymbolList() + { + ?? = new List(); + AllowToModify = true; + } + + public SymbolList(string name, IEnumerable symbols) + : this() + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?(name); + Symbols = symbols ?? throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + internal SymbolList(IList P_0, bool P_1) + : this() + { + Settings = P_0; + AllowToModify = P_1; + } + + public int CompareTo(object obj) + { + return Name.CompareTo((obj as SymbolList).Name); + } + + internal void ?(string P_0) + { + if (AllowToModify) + { + ?? = P_0; + } + } + + [CompilerGenerated] + private bool ?(SymbolList P_0) + { + return P_0.Name == ??; + } + } + public sealed class TimeUtils + { + public enum TimeFormat + { + Hours12, + Hours24 + } + + public static readonly string[] AvailableDateFormats = new string[12] + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + + public const long UNIX_START_TIME_TICKS = 621355968000000000L; + + [CompilerGenerated] + private TimeZone ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private ? ??; + + private CultureInfo ??; + + [CompilerGenerated] + private bool ??; + + public DateTime DateTimeUtcNow => DateTime.UtcNow.AddMilliseconds(TimeSynchronizer.ServerTimeOffset); + + public int ServerTimeOffset => TimeSynchronizer?.ServerTimeOffset ?? 0; + + public TimeZone SelectedTimeZone + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime StartTerminalDateTimeUtc + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + internal ? TimeSynchronizer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = ?; + } + } + + public bool IsSyncFailed => TimeSynchronizer.State == ?.??; + + public string SyncErrorMessage => TimeSynchronizer.LastSyncErrorMessage; + + public CultureInfo CultureInfo + { + get + { + if (!UseUICultureInfo) + { + return ??; + } + return CultureInfo.CurrentCulture; + } + } + + public bool UseUICultureInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string DateFormatPattern + { + get + { + return ??.DateTimeFormat.ShortDatePattern; + } + set + { + if (!string.IsNullOrEmpty(value)) + { + ??.DateTimeFormat.ShortDatePattern = value; + ??.DateTimeFormat.DateSeparator = (value.Contains('.') ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + } + + public TimeFormat TimeHoursFormat + { + get + { + if (!??.DateTimeFormat.ShortTimePattern.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + return TimeFormat.Hours24; + } + return TimeFormat.Hours12; + } + set + { + ??.DateTimeFormat.ShortTimePattern = ((value == TimeFormat.Hours12) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ??.DateTimeFormat.LongTimePattern = ((value == TimeFormat.Hours12) ? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() : 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public TimeUtils() + { + TimeSynchronizer = new ?(); + SelectedTimeZone = new TimeZone(TimeZoneType.Local); + UseUICultureInfo = true; + ?? = (CultureInfo)CultureInfo.InvariantCulture.Clone(); + DateFormatPattern = AvailableDateFormats[0]; + TimeHoursFormat = TimeFormat.Hours24; + } + + internal void ?() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + TimeSynchronizer.?(); + StartTerminalDateTimeUtc = DateTimeUtcNow; + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + internal void ?() + { + TimeSynchronizer.Dispose(); + } + + public DateTime ConvertFromUTCToSelectedTimeZone(DateTime dateTime) + { + return ConvertFromUTCToTimeZone(dateTime, SelectedTimeZone); + } + + public TimeSpan ConvertFromUTCToSelectedTimeZone(TimeSpan time) + { + return ConvertFromUTCToTimeZone(time, SelectedTimeZone); + } + + public DateTime ConvertFromSelectedTimeZoneToUTC(DateTime dateTime) + { + return ConvertFromTimeZoneToUTC(dateTime, SelectedTimeZone); + } + + public DateTime ConvertFromUTCToTimeZone(DateTime dateTime, TimeZone timeZone) + { + if (timeZone.TimeZoneInfo != null && dateTime.Kind != DateTimeKind.Local) + { + return TimeZoneInfo.ConvertTimeFromUtc(dateTime, timeZone.TimeZoneInfo); + } + return dateTime; + } + + public TimeSpan ConvertFromUTCToTimeZone(TimeSpan time, TimeZone timeZone) + { + DateTime dateTime = DateTimeUtcNow.Date + time; + if (timeZone.TimeZoneInfo != null && dateTime.Kind != DateTimeKind.Local) + { + return TimeZoneInfo.ConvertTimeFromUtc(dateTime, timeZone.TimeZoneInfo).TimeOfDay; + } + return time; + } + + public DateTime ConvertFromTimeZoneToUTC(DateTime dateTime, TimeZone timeZone) + { + if (dateTime.Kind == DateTimeKind.Utc) + { + return dateTime; + } + if (dateTime.Kind == DateTimeKind.Local) + { + dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified); + } + if (timeZone.TimeZoneInfo != null) + { + return TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone.TimeZoneInfo); + } + return dateTime; + } + + public string GetFormatedDateTime(DateTime dateTime) + { + return dateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo); + } + + public string GetFormatedDateShortTime(DateTime dateTime) + { + return dateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo); + } + + public string GetFormatedDate(DateTime dateTime) + { + return dateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo); + } + + public string GetFormatedDateTimeWithMilliseconds(DateTime dateTime) + { + string text = CultureInfo.DateTimeFormat.ShortDatePattern + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + CultureInfo.DateTimeFormat.LongTimePattern.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return dateTime.ToString(text, CultureInfo); + } + + public string GetFormatedShortTime(DateTime dateTime) + { + return dateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo); + } + + public string GetFormatedLongTime(DateTime dateTime) + { + return dateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo); + } + + public string GetFormatedLongTimeWithMilliseconds(DateTime dateTime) + { + string text = CultureInfo.DateTimeFormat.LongTimePattern.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return dateTime.ToString(text, CultureInfo); + } + + public string GetFormatedLongTime(TimeSpan timeSpan) + { + return GetFormatedLongTime(DateTimeUtcNow.Date + timeSpan); + } + } + public readonly struct TimeZone : IEquatable, IComparable, IComparable + { + [CompilerGenerated] + private readonly TimeZoneInfo ??; + + [CompilerGenerated] + private readonly TimeZoneType ??; + + public TimeZoneInfo TimeZoneInfo + { + [CompilerGenerated] + get + { + return ??; + } + } + + public TimeZoneType Type + { + [CompilerGenerated] + get + { + return ??; + } + } + + public bool IsEmpty + { + get + { + if (Type == TimeZoneType.Specific) + { + return TimeZoneInfo == null; + } + return false; + } + } + + public TimeZone(TimeZoneType type, TimeZoneInfo timeZoneInfo = null) + { + if (type == TimeZoneType.Local && timeZoneInfo != null) + { + throw new ArgumentException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (type == TimeZoneType.Specific && timeZoneInfo == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?? = type; + ?? = ((type == TimeZoneType.Local) ? TimeZoneInfo.Local : timeZoneInfo); + } + + public static string ShortName(TimeZone timeZone) + { + if (timeZone.Type != TimeZoneType.Local) + { + return ?(timeZone.TimeZoneInfo, false); + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + + public static string Cities(TimeZone timeZone) + { + return ?(timeZone.TimeZoneInfo, true); + } + + private static string ?(TimeZoneInfo P_0, bool P_1) + { + if (P_0 == null) + { + return string.Empty; + } + if (P_0.Id == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + if (P_1) + { + int num = P_0.DisplayName.IndexOf(')') + 1; + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.DisplayName.Substring(num, P_0.DisplayName.Length - num); + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.DisplayName.Substring(1, P_0.DisplayName.IndexOf(')') - 1); + } + + public static bool operator ==(TimeZone timeZone1, TimeZone timeZone2) + { + if (timeZone1.Type == timeZone2.Type) + { + return timeZone1.TimeZoneInfo?.Id == timeZone2.TimeZoneInfo?.Id; + } + return false; + } + + public static bool operator !=(TimeZone timeZone1, TimeZone timeZone2) + { + if (timeZone1.Type == timeZone2.Type) + { + return timeZone1.TimeZoneInfo?.Id != timeZone2.TimeZoneInfo?.Id; + } + return true; + } + + public bool Equals(TimeZone other) + { + if (object.Equals(TimeZoneInfo, other.TimeZoneInfo)) + { + return Type == other.Type; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj is TimeZone other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (((TimeZoneInfo != null) ? TimeZoneInfo.GetHashCode() : 0) * 397) ^ (int)Type; + } + + public int CompareTo(TimeZone other) + { + if (TimeZoneInfo == null) + { + return 1; + } + if (other.TimeZoneInfo == null) + { + return -1; + } + int num = TimeZoneInfo.BaseUtcOffset.CompareTo(other.TimeZoneInfo.BaseUtcOffset); + if (num != 0) + { + return num; + } + return string.Compare(TimeZoneInfo.Id, other.TimeZoneInfo.Id, StringComparison.Ordinal); + } + + public int CompareTo(object obj) + { + if (!(obj is TimeZone other)) + { + return 0; + } + return CompareTo(other); + } + + public override string ToString() + { + return TimeZoneInfo?.DisplayName; + } + } + public enum TimeZoneType + { + Specific, + Local + } + /// + /// Defines a trading operation respond bundle + /// + public sealed class TradingOperationResult : ILoggable + { + [CompilerGenerated] + private TradingOperationResultStatus ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private long ??; + + /// + /// Respond operation state + /// + public TradingOperationResultStatus Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = tradingOperationResultStatus; + } + } + + /// + /// Respond message + /// + public string Message + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Respond order id + /// + public string OrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public long RequestId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + string ILoggable.Event => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + string ILoggable.Message => ToString(); + + private TradingOperationResult() + { + } + + public static TradingOperationResult CreateSuccess(long requestId, string orderId = null) + { + return new TradingOperationResult + { + RequestId = requestId, + Status = TradingOperationResultStatus.Success, + OrderId = orderId + }; + } + + public static TradingOperationResult CreateError(long requestId, string message) + { + return new TradingOperationResult + { + RequestId = requestId, + Status = TradingOperationResultStatus.Failure, + Message = message + }; + } + + [NotPublished] + public void SetOrderId(string orderId) + { + OrderId = orderId; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3); + defaultInterpolatedStringHandler.AppendFormatted(Status); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted((Status == TradingOperationResultStatus.Success) ? (3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + OrderId) : Message); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(RequestId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public delegate TradingOperationResult TradingRequestHandler(TradingRequestParameters requestParameters); + public struct ValidateResult + { + [CompilerGenerated] + private ValidateState ??; + + [CompilerGenerated] + private string ??; + + public ValidateState State + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Reason + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public static ValidateResult Valid => new ValidateResult + { + State = ValidateState.Valid + }; + + public static ValidateResult NotValid(string reason) + { + return new ValidateResult + { + State = ValidateState.NotValid, + Reason = reason + }; + } + } + /// + /// Provides VA calculation parameters + /// + [Published] + public class VolumeAnalysisCalculationParameters + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private DeltaCalculationType ??; + + [CompilerGenerated] + private CumulativeDeltaReset ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private ISessionsContainer ??; + + [CompilerGenerated] + private TimeZone ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + public double FilteredVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ForceReload + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DeltaCalculationType DeltaCalculationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public CumulativeDeltaReset CumulativeDeltaReset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double CustomTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int CustomStep + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ISessionsContainer SessionsContainer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeZone TimeZone + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool CalculatePriceLevels + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ForceUsingTickData + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VolumeAnalysisCalculationParameters() + { + FilteredVolume = 0.0; + ForceReload = false; + DeltaCalculationType = DeltaCalculationType.AggressorFlag; + CustomTickSize = double.NaN; + CustomStep = 1; + CalculatePriceLevels = true; + ForceUsingTickData = false; + } + + internal VolumeAnalysisCalculationParameters(VolumeAnalysisCalculationParameters P_0) + { + FilteredVolume = P_0.FilteredVolume; + ForceReload = P_0.ForceReload; + DeltaCalculationType = P_0.DeltaCalculationType; + CumulativeDeltaReset = P_0.CumulativeDeltaReset; + CustomTickSize = P_0.CustomTickSize; + CustomStep = P_0.CustomStep; + SessionsContainer = P_0.SessionsContainer; + TimeZone = P_0.TimeZone; + CalculatePriceLevels = P_0.CalculatePriceLevels; + ForceUsingTickData = P_0.ForceUsingTickData; + } + } + /// + /// Provides VA calculation request per + /// + [Published] + public class VolumeAnalysisCalculationRequest : VolumeAnalysisCalculationParameters + { + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime From + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime To + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + internal string Marker => Symbol?.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Symbol?.ConnectionId; + + public VolumeAnalysisCalculationRequest() + { + } + + internal VolumeAnalysisCalculationRequest(VolumeAnalysisCalculationRequest P_0) + : base(P_0) + { + Symbol = P_0.Symbol; + From = P_0.From; + To = P_0.To; + } + + internal VolumeAnalysisCalculationRequest(VolumeAnalysisCalculationParameters P_0) + : base(P_0) + { + } + } +} +namespace ? +{ + internal abstract class ? : IVolumeAnalysisCalculationProgress, IDisposable + { + protected enum ? + { + ??, + ??, + ??, + ??, + ??, + ??, + ??, + ?? + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func> ??; + + public static Func ??; + + internal DateTime ?(VolumeAnalysisInterval P_0) + { + return P_0.Interval.From; + } + + internal IEnumerable ?(VolumeAnalysisInterval P_0) + { + return P_0.VolumeAnalysis; + } + + internal long ?(Period P_0) + { + return P_0.Ticks; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Period ??; + + internal bool ?(Period P_0) + { + return P_0.Ticks < ??.Ticks; + } + } + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private EventHandler ??; + + private VolumeAnalysisCalculationState ??; + + [CompilerGenerated] + private int ??; + + private readonly CancellationTokenSource ??; + + protected readonly VolumeAnalysisCalculationRequest ??; + + private Interval ??; + + private Interval ??; + + [CompilerGenerated] + private bool ?? = true; + + private readonly ManualResetEventSlim ??; + + private readonly ConcurrentQueue ??; + + private bool ??; + + private DateTime? ??; + + public VolumeAnalysisCalculationState State + { + get + { + return ??; + } + protected internal set + { + if (volumeAnalysisCalculationState != ??) + { + ?? = volumeAnalysisCalculationState; + ?(); + if (State == VolumeAnalysisCalculationState.Finished) + { + ??.Set(); + } + } + } + } + + public int ProgressPercent => (int)(??.GetLength().Ticks * 100 / CorrectedInterval.GetLength().Ticks); + + public int ProgressBarIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public bool IsAborted => ??.IsCancellationRequested; + + protected CancellationToken CancellationToken => ??.Token; + + protected Interval CorrectedInterval + { + get + { + return ??; + } + private set + { + ?? = interval; + ?? = new Interval(??.To, ??.To); + } + } + + public VolumeAnalysisCalculationParameters CalculationParameters => new VolumeAnalysisCalculationParameters(??); + + protected Symbol Symbol => ??.Symbol; + + protected Connection Connection => Symbol?.Connection; + + protected VolumeAnalysisMetadata VolumeAnalysisMetadata => Symbol?.VolumeAnalysisMetadata; + + protected double PriceStep + { + get + { + double num = Symbol.TickSize; + if (!??.CustomTickSize.IsNanOrDefault()) + { + num = ??.CustomTickSize; + } + if (??.CustomStep > 1) + { + num *= (double)??.CustomStep; + } + return num; + } + } + + public bool AllowByLicense + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + + public event EventHandler StateChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event EventHandler ProgressChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + protected ?(VolumeAnalysisCalculationRequest P_0) + { + ?? = P_0 ?? throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CorrectedInterval = new Interval(??.From, ??.To); + ?? = new CancellationTokenSource(); + ?? = VolumeAnalysisCalculationState.None; + ProgressBarIndex = int.MaxValue; + ?? = new ConcurrentQueue(); + ?? = new ManualResetEventSlim(); + } + + internal virtual void ?() + { + if (Symbol == null || Symbol.State == BusinessObjectState.Fake || (Connection == null && Symbol.SymbolType != SymbolType.Synthetic)) + { + State = VolumeAnalysisCalculationState.Finished; + return; + } + try + { + State = VolumeAnalysisCalculationState.Processing; + ?(); + CorrectedInterval = ?(); + if (CorrectedInterval.IsEmpty) + { + State = VolumeAnalysisCalculationState.Finished; + return; + } + if (?(out var ?2)) + { + ?(); + return; + } + bool flag = (((uint)(?2 - 3) <= 1u || ?2 == ?.?.??) ? true : false); + if (flag && Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), ??.Symbol).Status == TradingOperationStatus.NotAllowed) + { + Core.Instance.PushDealTicket(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Symbol?.Connection?.VendorName, DealTicketType.Refuse); + return; + } + foreach (Interval item in CorrectedInterval.Reverse().Split(Symbol?.HistoryMetadata?.DownloadingStep_Tick ?? TimeSpan.FromHours(1.0), roundToStep: true)) + { + int num = 0; + try + { + if (IsAborted) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1); + defaultInterpolatedStringHandler.AppendFormatted(this); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + break; + } + HistoricalData history = Symbol.GetHistory(new HistoryRequestParameters + { + Symbol = Symbol, + FromTime = item.From, + ToTime = item.To, + Aggregation = new HistoryAggregationTick((Symbol.VolumeType == SymbolVolumeType.Volume) ? HistoryType.Last : HistoryType.BidAsk), + CancellationToken = CancellationToken, + ForceReload = ??.ForceReload + }); + if (history.Count > 0) + { + IHistoryItem historyItem = history.LastOrDefault(); + if (historyItem != null && (!??.HasValue || ?? < historyItem.TimeLeft)) + { + ?? = historyItem.TimeLeft; + } + num = ?(history, item); + } + else if (!??.HasValue) + { + ?? = CorrectedInterval.From; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + if (item.To == CorrectedInterval.To) + { + ?? = true; + ?(); + } + ?(item.From, (num != 0) ? num : ProgressBarIndex); + } + } + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + finally + { + try + { + if (!??) + { + ?? = true; + ?(); + } + ?(); + } + catch (Exception ex3) + { + Core.Instance.Loggers.Log(ex3); + } + State = VolumeAnalysisCalculationState.Finished; + } + } + + private protected virtual void ?() + { + } + + public void AbortLoading() + { + ???.Cancel(); + } + + public void Wait(CancellationToken token = default(CancellationToken)) + { + WaitHandle.WaitAny(new WaitHandle[3] + { + ??.WaitHandle, + ???.Token.WaitHandle, + token.WaitHandle + }); + } + + public virtual void Dispose() + { + ?(); + ??.Clear(); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 3); + defaultInterpolatedStringHandler.AppendFormatted(GetType().Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(CorrectedInterval); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + protected virtual bool ?(out ? P_0) + { + P_0 = ?.?.??; + VolumeAnalysisMetadata volumeAnalysisMetadata = VolumeAnalysisMetadata; + if (volumeAnalysisMetadata == null || !volumeAnalysisMetadata.IsVolumeAnalysisAvailable) + { + P_0 = ?.?.??; + return false; + } + if (Symbol.VolumeType != SymbolVolumeType.Volume) + { + P_0 = ?.?.??; + return false; + } + if (??.DeltaCalculationType != Symbol.GetDeltaCalculationTypeForVolumeAnalysis()) + { + P_0 = ?.?.??; + return false; + } + if (!??.FilteredVolume.IsNanOrDefault()) + { + P_0 = ?.?.??; + return false; + } + if (??.ForceUsingTickData) + { + P_0 = ?.?.??; + return false; + } + if (!VolumeAnalysisMetadata.TryFindLargestLoadingPeriod(CorrectedInterval, ??.CalculatePriceLevels, out var _)) + { + P_0 = ?.?.??; + return false; + } + return true; + } + + protected abstract void ?(); + + protected void ?(Interval P_0, Period P_1, ? P_2) + { + IDictionary downloadingStepByPeriod = VolumeAnalysisMetadata.GetDownloadingStepByPeriod(??.CalculatePriceLevels); + foreach (Interval item in P_0.Reverse().Split(downloadingStepByPeriod[P_1], roundToStep: true)) + { + int progressBarIndex = ProgressBarIndex; + try + { + if (IsAborted) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1); + defaultInterpolatedStringHandler.AppendFormatted(this); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + break; + } + VolumeAnalysisByPeriodRequestParameters volumeAnalysisByPeriodRequestParameters = new VolumeAnalysisByPeriodRequestParameters + { + SymbolId = Symbol.Id, + FromTime = item.From, + ToTime = item.To.AddTicks(-1L), + Period = P_1, + CalculatePriceLevels = ??.CalculatePriceLevels, + CancellationToken = CancellationToken, + MinVolumeAnalysisTickSize = Symbol.MinVolumeAnalysisTickSize, + SessionsContainer = ??.SessionsContainer + }; + List list = new List(); + List parametersForServerRequest = new List(); + VolumeAnalysisStorage volumeAnalysisStorage = Symbol.Connection.VolumeAnalysisStorage; + if (!??.ForceReload && volumeAnalysisStorage != null) + { + IList collection = volumeAnalysisStorage.Load(volumeAnalysisByPeriodRequestParameters, out parametersForServerRequest); + if (IsAborted) + { + LoggerManager loggers2 = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1); + defaultInterpolatedStringHandler.AppendFormatted(this); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + break; + } + list.AddRange(collection); + } + else + { + parametersForServerRequest.Add(volumeAnalysisByPeriodRequestParameters); + } + foreach (VolumeAnalysisByPeriodRequestParameters item2 in parametersForServerRequest) + { + if (IsAborted) + { + LoggerManager loggers3 = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1); + defaultInterpolatedStringHandler.AppendFormatted(this); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers3.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + return; + } + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + item2.ForceReload = ??.ForceReload; + if (item2.ToTime.Ticks % 10 == 0L) + { + item2.ToTime = item2.ToTime.AddTicks(-1L); + } + VolumeAnalysisInterval volumeAnalysisInterval = Connection.LoadVolumeAnalysis(item2); + if (volumeAnalysisInterval?.VolumeAnalysis == null) + { + continue; + } + list.Add(volumeAnalysisInterval); + Period period = item2.Period; + TimeSpan timeSpan = period.BasePeriod switch + { + BasePeriod.Month => TimeSpan.FromDays(2.0), + BasePeriod.Year => TimeSpan.FromDays(2.0), + _ => TimeSpan.FromHours(2.0), + }; + VolumeAnalysisData volumeAnalysisData = volumeAnalysisInterval.VolumeAnalysis.LastOrDefault(); + if (volumeAnalysisData != null) + { + DateTime dateTime = period.BasePeriod switch + { + BasePeriod.Month => volumeAnalysisData.TimeLeft.AddMonths(period.PeriodMultiplier), + BasePeriod.Year => volumeAnalysisData.TimeLeft.AddYears(period.PeriodMultiplier), + _ => volumeAnalysisData.TimeLeft.AddTicks(period.Ticks), + }; + if (dateTime > item2.Interval.To && dateTime > dateTimeUtcNow) + { + volumeAnalysisInterval = new VolumeAnalysisInterval + { + Description = volumeAnalysisInterval.Description, + VolumeAnalysis = volumeAnalysisInterval.VolumeAnalysis.Take(volumeAnalysisInterval.VolumeAnalysis.Count - 1).ToList(), + Interval = new Interval(volumeAnalysisInterval.Interval.From, volumeAnalysisData.TimeLeft) + }; + } + else if (volumeAnalysisInterval.Interval.To > dateTimeUtcNow - timeSpan) + { + volumeAnalysisInterval = new VolumeAnalysisInterval + { + Description = volumeAnalysisInterval.Description, + VolumeAnalysis = volumeAnalysisInterval.VolumeAnalysis.ToList(), + Interval = new Interval(volumeAnalysisInterval.Interval.From, dateTime) + }; + } + } + else if (!volumeAnalysisInterval.Interval.IsEmpty) + { + DateTime dateTime2 = item2.Interval.To.FloorTo(new TimeSpan(period.Ticks)); + if (dateTime2 > dateTimeUtcNow - timeSpan) + { + dateTime2 = (dateTimeUtcNow - timeSpan).FloorTo(new TimeSpan(period.Ticks)); + } + if (dateTime2 < item2.Interval.From) + { + dateTime2 = item2.Interval.From; + } + volumeAnalysisInterval = new VolumeAnalysisInterval + { + Description = volumeAnalysisInterval.Description, + VolumeAnalysis = volumeAnalysisInterval.VolumeAnalysis.ToList(), + Interval = new Interval(volumeAnalysisInterval.Interval.From, dateTime2) + }; + } + if (!volumeAnalysisInterval.Interval.IsEmpty) + { + if (volumeAnalysisInterval.Interval.To.Microsecond == 999) + { + volumeAnalysisInterval = new VolumeAnalysisInterval + { + Description = volumeAnalysisInterval.Description, + VolumeAnalysis = volumeAnalysisInterval.VolumeAnalysis, + Interval = new Interval(volumeAnalysisInterval.Interval.From, volumeAnalysisInterval.Interval.To.AddTicks(1L)) + }; + } + _ = volumeAnalysisInterval.Interval.To.Second; + volumeAnalysisStorage?.Save(volumeAnalysisInterval); + } + } + List list2 = list.OrderBy((VolumeAnalysisInterval volumeAnalysisInterval2) => volumeAnalysisInterval2.Interval.From).SelectMany((VolumeAnalysisInterval volumeAnalysisInterval2) => volumeAnalysisInterval2.VolumeAnalysis).ToList(); + if (list2 == null || list2.Count <= 0) + { + continue; + } + VolumeAnalysisData volumeAnalysisData2 = list2.LastOrDefault(); + if (volumeAnalysisData2 != null) + { + DateTime value = (VolumeAnalysisMetadata.BuildUncompletedBars ? volumeAnalysisData2.TimeLeft.AddTicks(P_1.Ticks) : volumeAnalysisData2.TimeLeft); + if (!??.HasValue || ?? < value) + { + ?? = value; + } + } + P_2?.Invoke(list2, item, ref progressBarIndex); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + if (!?? && item.To == CorrectedInterval.To) + { + ?(P_1, item, P_2); + ?? = true; + ?(); + } + ?(item.From, progressBarIndex); + } + } + } + + private void ?(Period P_0, Interval P_1, ? P_2) + { + if (!VolumeAnalysisMetadata.BuildUncompletedBars) + { + return; + } + Period[] array = (from period2 in VolumeAnalysisMetadata.GetAllowedPeriods(??.CalculatePriceLevels) + where period2.Ticks < P_0.Ticks + orderby period2.Ticks descending + select period2).ToArray(); + if (!array.Any()) + { + Interval interval; + if (??.HasValue) + { + interval = new Interval(??.Value, P_1.To); + } + else + { + TimeSpan maxTicksLoadingPeriod = VolumeAnalysisMetadata.MaxTicksLoadingPeriod; + interval = ((!(P_1.GetLength() > maxTicksLoadingPeriod)) ? P_1 : new Interval(P_1.To - maxTicksLoadingPeriod, P_1.To)); + } + HistoricalData history = Symbol.GetHistory(new HistoryRequestParameters + { + Symbol = Symbol, + Interval = interval, + Aggregation = new HistoryAggregationTick((Symbol.VolumeType == SymbolVolumeType.Volume) ? HistoryType.Last : HistoryType.BidAsk), + CancellationToken = CancellationToken, + ForceReload = ??.ForceReload, + HistoryRequestType = HistoryRequestType.BuildUncompleteBarLogic + }); + IHistoryItem historyItem = history.LastOrDefault(); + if (historyItem != null && (!??.HasValue || ?? < historyItem.TimeLeft)) + { + ?? = historyItem.TimeLeft; + } + ?(history, P_1); + return; + } + Period[] array2 = array; + foreach (Period period in array2) + { + DateTime dateTime = (??.HasValue ? ??.Value : ((P_0.BasePeriod == BasePeriod.Tick) ? P_1.From : (((P_1.To - P_1.From).Ticks >= P_0.Ticks) ? P_1.To.AddTicks(-P_0.Ticks) : P_1.From))); + if (dateTime == P_1.To) + { + break; + } + ?(new Interval(dateTime, P_1.To), period, P_2); + } + } + + protected abstract int ?(HistoricalData P_0, Interval P_1); + + protected virtual void ?() + { + if (Symbol != null) + { + if (Symbol.VolumeType == SymbolVolumeType.Volume) + { + Symbol.NewLast += ?; + } + else + { + Symbol.NewQuote += ?; + } + } + } + + protected virtual void ?() + { + if (Symbol != null) + { + if (Symbol.VolumeType == SymbolVolumeType.Volume) + { + Symbol.NewLast -= ?; + } + else + { + Symbol.NewQuote -= ?; + } + } + } + + private void ?(Symbol P_0, MessageQuote P_1) + { + ?(P_1); + } + + protected virtual void ?(MessageQuote P_0) + { + if (!?(P_0)) + { + ?(P_0); + } + } + + protected abstract VolumeAnalysisData ?(long P_0); + + private bool ?(MessageQuote P_0) + { + if (?? && ??.IsEmpty) + { + return false; + } + ??.Enqueue(P_0); + return true; + } + + private void ?() + { + MessageQuote result; + while (??.TryDequeue(out result)) + { + if (result != null) + { + ?(result); + } + } + } + + private void ?(MessageQuote P_0) + { + if (P_0.Time <= (?? ?? CorrectedInterval.To) || !AllowByLicense) + { + return; + } + VolumeAnalysisData volumeAnalysisData = ?(P_0.Time.Ticks); + if (volumeAnalysisData == null) + { + return; + } + lock (volumeAnalysisData) + { + volumeAnalysisData.?(??, P_0); + } + } + + protected virtual Interval ?() + { + DateTime dateTime = ??.From; + DateTime dateTime2 = ??.To; + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + if (dateTime > dateTimeUtcNow) + { + dateTime = dateTimeUtcNow; + } + if (dateTime2 > dateTimeUtcNow) + { + dateTime2 = dateTimeUtcNow; + } + if (Symbol.QuoteDelay != default(TimeSpan) && dateTime2 > dateTimeUtcNow - Symbol.QuoteDelay) + { + dateTime2 = dateTimeUtcNow - Symbol.QuoteDelay; + } + return new Interval(dateTime, dateTime2); + } + + protected void ?(DateTime P_0, int P_1 = int.MaxValue) + { + ?? = new Interval(P_0, ??.To); + ProgressBarIndex = P_1; + ?(); + } + + private void ?() + { + ???.InvokeSafely(this, new VolumeAnalysisTaskEventArgs(this)); + } + + private void ?() + { + ???.InvokeSafely(this, new VolumeAnalysisTaskEventArgs(this)); + } + } + internal delegate void ?(IList P_0, Interval P_1, ref int P_2); + internal class ? : ?, IVolumeAnalysisCalculationTask, IDisposable + { + [Serializable] + [CompilerGenerated] + private new sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal Period ?(Period P_0) + { + return P_0; + } + + internal DateTime ?(VolumeAnalysisData P_0) + { + return P_0.TimeLeft; + } + } + + [CompilerGenerated] + private new sealed class ? + { + public long ??; + + public Period ??; + + public ? ??; + + public DateTime ??; + + public DateTime ??; + + public DateTime ??; + + public VolumeAnalysisData ??; + + public Func ??; + + internal bool ?(Period P_0) + { + return P_0.Ticks <= ??; + } + + internal bool ?(Period P_0) + { + return P_0 < ??; + } + + internal void ?(IList P_0, Interval P_1, ref int P_2) + { + if (??.?? == default(DateTime) || ??.?? > ??) + { + ??.?? = ??; + } + if (??.?? == default(DateTime) || ??.?? < ??) + { + ??.?? = ??; + } + if (P_0.Count > 0) + { + ?? = new DateTime(Math.Max(??.Ticks, ((IEnumerable)P_0).Max((Func)?.?.??.?).Ticks + ??.Ticks), DateTimeKind.Utc); + } + if (??.??.SessionsContainer != null && ?? < Period.DAY1) + { + P_0 = P_0.Where((VolumeAnalysisData volumeAnalysisData) => ??.??.SessionsContainer.ContainsDate(volumeAnalysisData.TimeLeft)).ToList(); + } + ??.Combine(P_0.Collapse()); + } + + internal bool ?(VolumeAnalysisData P_0) + { + return ??.??.SessionsContainer.ContainsDate(P_0.TimeLeft); + } + } + + [CompilerGenerated] + private VolumeAnalysisData ??; + + private DateTime ??; + + private DateTime ??; + + public VolumeAnalysisData Result + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = volumeAnalysisData; + } + } + + public IVolumeAnalysisCalculationProgress Progress => this; + + internal ?(VolumeAnalysisCalculationRequest P_0) + : base(P_0) + { + Result = new VolumeAnalysisData(); + } + + public override void Dispose() + { + Result = null; + base.Dispose(); + } + + protected override void ?() + { + try + { + ?(base.CorrectedInterval, Result); + if (base.PriceStep != base.Symbol.TickSize) + { + Result = Result?.CreateAggregatedSnapshot(base.PriceStep); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?(base.CorrectedInterval.From); + } + } + + private void ?(Interval P_0, VolumeAnalysisData P_1, Period P_2 = default(Period)) + { + if (P_0.IsEmpty) + { + return; + } + Period[] allowedPeriods = base.VolumeAnalysisMetadata.GetAllowedPeriods(??.CalculatePriceLevels); + long ?? = (P_0.To - P_0.From).Ticks; + allowedPeriods = allowedPeriods.Where((Period period) => period.Ticks <= ??).ToArray(); + if (P_2 == default(Period)) + { + P_2 = allowedPeriods.Max((Period result) => result); + } + else + { + P_2 = allowedPeriods.FirstOrDefault((Period period) => period < P_2); + } + if (P_2 == default(Period)) + { + HistoricalData history = base.Symbol.GetHistory(new HistoryRequestParameters + { + Symbol = base.Symbol, + Interval = P_0, + Aggregation = new HistoryAggregationTick((base.Symbol.VolumeType == SymbolVolumeType.Volume) ? HistoryType.Last : HistoryType.BidAsk), + CancellationToken = base.CancellationToken, + ForceReload = ??.ForceReload + }); + ?(history, P_0); + return; + } + DateTime ?? = P_0.From; + DateTime ?? = P_0.To; + if (P_2.Ticks - (?? - ??).Ticks != 1) + { + ?? = P_0.From.CeilingTo(P_2); + ?? = P_0.To.FloorTo(P_2); + } + if (??.Ticks + P_2.Ticks == P_0.To.Ticks + 1) + { + ?? = P_0.To; + } + DateTime ?? = ??; + if (!(?? == ??)) + { + ?(new Interval(??, ??), P_2, delegate(IList list, Interval interval, ref int reference) + { + if (?? == default(DateTime) || ?? > ??) + { + ?? = ??; + } + if (?? == default(DateTime) || ?? < ??) + { + ?? = ??; + } + if (list.Count > 0) + { + ?? = new DateTime(Math.Max(??.Ticks, ((IEnumerable)list).Max((Func)?.?.??.?).Ticks + P_2.Ticks), DateTimeKind.Utc); + } + if (??.SessionsContainer != null && P_2 < Period.DAY1) + { + list = list.Where((VolumeAnalysisData volumeAnalysisData) => ??.SessionsContainer.ContainsDate(volumeAnalysisData.TimeLeft)).ToList(); + } + P_1.Combine(list.Collapse()); + }); + } + ?? = ??; + if (P_0.From < ??) + { + ?(new Interval(P_0.From, ??), P_1, P_2); + } + if (?? < P_0.To) + { + ?(new Interval(??, P_0.To), P_1, P_2); + } + } + + protected override int ?(HistoricalData P_0, Interval P_1) + { + Result?.?(??, P_0); + return 0; + } + + protected override void ?() + { + DateTime dateTime = Core.Instance.TimeUtils.DateTimeUtcNow; + if (???.Symbol?.Connection != null) + { + dateTime = ??.Symbol.Connection.ServerTime; + } + if (!(??.To < dateTime)) + { + base.?(); + } + } + + protected override void ?(MessageQuote P_0) + { + if (P_0.Time > ??.To) + { + ?(); + } + else if (!(P_0.Time < ??.From)) + { + base.?(P_0); + } + } + + protected override VolumeAnalysisData ?(long P_0) + { + return Result; + } + } + internal class ? : ? + { + private const int ?? = 1000000; + + private readonly ConcurrentQueue ??; + + private readonly ConcurrentQueue ??; + + internal ?(HistoricalData P_0, VolumeAnalysisCalculationRequest P_1) + : base(P_0, P_1) + { + if (??.Aggregation is HistoryAggregationRenko) + { + ?? = default(Period); + } + ?? = new ConcurrentQueue(); + ?? = new ConcurrentQueue(); + ??.NewHistoryItem += ?; + } + + public override void Dispose() + { + if (?? != null) + { + ??.NewHistoryItem -= ?; + } + base.Dispose(); + } + + private protected override void ?(HistoricalData P_0, int P_1) + { + if (P_0.Count <= P_1 + 1) + { + return; + } + IHistoryItem historyItem = null; + if (??.Any()) + { + IHistoryItem historyItem2 = ??[0, SeekOriginHistory.End]; + if (historyItem2.TryGetData(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var data) && data) + { + historyItem = historyItem2; + historyItem.VolumeAnalysisData = ?(historyItem2, ??.Count - 1); + } + } + foreach (IVolumeTickData item in P_0.Skip(P_1 + 1).OfType()) + { + if (historyItem != null && historyItem.TicksLeft <= item.Time) + { + lock (historyItem.VolumeAnalysisData) + { + historyItem.VolumeAnalysisData.?(??, item); + } + } + ??.Enqueue(item); + } + } + + protected override void ?(MessageQuote P_0) + { + if (!base.AllowByLicense || !(P_0 is IVolumeTickData item)) + { + return; + } + VolumeAnalysisData volumeAnalysisData = ?(P_0.Time.Ticks); + bool data = false; + IHistoryItem historyItem = null; + if (??.Any()) + { + historyItem = ??[0, SeekOriginHistory.End]; + if (historyItem.TimeLeft <= P_0.Time) + { + historyItem.TryGetData(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out data); + } + } + if (volumeAnalysisData == null && historyItem != null && data) + { + volumeAnalysisData = ?(historyItem, ??.Count - 1); + } + if (volumeAnalysisData == null || data) + { + ??.Enqueue(item); + while (??.Count > 1000000) + { + ??.TryDequeue(out var _); + } + if (!data) + { + return; + } + } + if (volumeAnalysisData != null) + { + lock (volumeAnalysisData) + { + volumeAnalysisData.?(??, P_0); + } + ???.?(); + } + } + + private void ?(object P_0, HistoryEventArgs P_1) + { + ?(??); + ?(??); + ???.?(); + } + + private void ?(ConcurrentQueue P_0) + { + IVolumeTickData result; + while (P_0.TryPeek(out result)) + { + VolumeAnalysisData volumeAnalysisData = ?(result.Time); + if (volumeAnalysisData == null) + { + break; + } + P_0.TryDequeue(out result); + lock (volumeAnalysisData) + { + volumeAnalysisData.?(??, result); + } + } + } + } + internal class ? : ? + { + [CompilerGenerated] + private new sealed class ? + { + public ? ??; + + public double ??; + + public Func ??; + + internal void ?(IList P_0, Interval P_1, ref int P_2) + { + if (??.??.SessionsContainer != null && ??.?? < Period.DAY1) + { + P_0 = P_0.Where((VolumeAnalysisData volumeAnalysisData3) => ??.??.SessionsContainer.ContainsDate(volumeAnalysisData3.TimeLeft)).ToList(); + } + int num = ??.?(??.??, P_1); + if (num < 0) + { + return; + } + P_2 = num; + int num2 = 0; + while (num < ??.??.Count && num2 < P_0.Count) + { + IHistoryItem historyItem = ??.??[num, SeekOriginHistory.Begin]; + VolumeAnalysisData volumeAnalysisData = P_0[num2]; + if (volumeAnalysisData.TimeLeft.Ticks > historyItem.TicksRight) + { + num++; + continue; + } + if (volumeAnalysisData.TimeLeft.Ticks + ??.??.Ticks - 1 < historyItem.TicksLeft) + { + num2++; + continue; + } + IHistoryItem historyItem2 = historyItem; + if (historyItem2.VolumeAnalysisData == null) + { + VolumeAnalysisData obj = new VolumeAnalysisData + { + TimeLeft = historyItem.TimeLeft + }; + VolumeAnalysisData volumeAnalysisData2 = obj; + historyItem2.VolumeAnalysisData = obj; + } + if (?? != ??.Symbol.TickSize) + { + historyItem.VolumeAnalysisData.Combine(volumeAnalysisData.CreateAggregatedSnapshot(??)); + } + else + { + historyItem.VolumeAnalysisData.Combine(volumeAnalysisData); + } + num2++; + } + } + + internal bool ?(VolumeAnalysisData P_0) + { + return ??.??.SessionsContainer.ContainsDate(P_0.TimeLeft); + } + } + + protected HistoricalData ??; + + protected Period ??; + + internal ?(HistoricalData P_0, VolumeAnalysisCalculationRequest P_1) + : base(P_1) + { + ?? = P_0; + if (Vendor.TryCorrectPeriodForDirectDownload(base.VolumeAnalysisMetadata?.GetAllowedPeriods(P_1.CalculatePriceLevels), ??.Aggregation.GetPeriod, out var allowedPeriod)) + { + ?? = allowedPeriod; + } + } + + internal override void ?() + { + if (?? == null) + { + base.State = VolumeAnalysisCalculationState.Finished; + } + else + { + base.?(); + } + } + + private protected override void ?() + { + base.?(); + double num = 0.0; + DateTime dateTime = default(DateTime); + if (base.IsAborted) + { + return; + } + for (int i = 0; i < ??.Count; i++) + { + IHistoryItem historyItem = ??[i, SeekOriginHistory.Begin]; + num = ?(dateTime, historyItem.TimeLeft, num); + if (historyItem.VolumeAnalysisData?.Total != null) + { + historyItem.VolumeAnalysisData.Total.?? = num; + num += (double)(decimal)historyItem.VolumeAnalysisData.Total.Delta; + } + dateTime = historyItem.TimeLeft; + } + } + + public override void Dispose() + { + base.Dispose(); + if (?? != null) + { + ??.VolumeAnalysisCalculationProgress = null; + for (int i = 0; i < ??.Count; i++) + { + ??[i, SeekOriginHistory.End].VolumeAnalysisData = null; + } + ?? = null; + } + } + + protected override bool ?(out ?.? P_0) + { + if (?? == default(Period)) + { + P_0 = ?.?.??; + return false; + } + return base.?(out P_0); + } + + protected override void ?() + { + double ?? = base.PriceStep; + ?(base.CorrectedInterval, ??, delegate(IList P_0, Interval P_1, ref int P_2) + { + if (??.SessionsContainer != null && ?? < Period.DAY1) + { + P_0 = P_0.Where((VolumeAnalysisData volumeAnalysisData3) => ??.SessionsContainer.ContainsDate(volumeAnalysisData3.TimeLeft)).ToList(); + } + int num = ?(??, P_1); + if (num >= 0) + { + P_2 = num; + int num2 = 0; + while (num < ??.Count && num2 < P_0.Count) + { + IHistoryItem historyItem = ??[num, SeekOriginHistory.Begin]; + VolumeAnalysisData volumeAnalysisData = P_0[num2]; + if (volumeAnalysisData.TimeLeft.Ticks > historyItem.TicksRight) + { + num++; + } + else if (volumeAnalysisData.TimeLeft.Ticks + ??.Ticks - 1 < historyItem.TicksLeft) + { + num2++; + } + else + { + IHistoryItem historyItem2 = historyItem; + if (historyItem2.VolumeAnalysisData == null) + { + VolumeAnalysisData obj = new VolumeAnalysisData + { + TimeLeft = historyItem.TimeLeft + }; + VolumeAnalysisData volumeAnalysisData2 = obj; + historyItem2.VolumeAnalysisData = obj; + } + if (?? != base.Symbol.TickSize) + { + historyItem.VolumeAnalysisData.Combine(volumeAnalysisData.CreateAggregatedSnapshot(??)); + } + else + { + historyItem.VolumeAnalysisData.Combine(volumeAnalysisData); + } + num2++; + } + } + } + }); + } + + protected override int ?(HistoricalData P_0, Interval P_1) + { + int num = ?(??, P_1); + int i = 0; + if (num < 0) + { + return 0; + } + int result = num; + while (i < P_0.Count && num < ??.Count) + { + IHistoryItem historyItem = ??[num, SeekOriginHistory.Begin]; + if (historyItem.TryGetData(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var data) && data) + { + num++; + continue; + } + DateTime timeLeft = historyItem.TimeLeft; + DateTime dateTime = new DateTime(historyItem.TicksRight, DateTimeKind.Utc); + while (P_0[i, SeekOriginHistory.Begin].TimeLeft < timeLeft) + { + i++; + if (i >= P_0.Count) + { + break; + } + } + for (; i < P_0.Count; i++) + { + IHistoryItem historyItem2 = P_0[i, SeekOriginHistory.Begin]; + if (historyItem2.TimeLeft > dateTime) + { + break; + } + IHistoryItem historyItem3 = historyItem; + if (historyItem3.VolumeAnalysisData == null) + { + VolumeAnalysisData obj = new VolumeAnalysisData + { + TimeLeft = timeLeft + }; + VolumeAnalysisData volumeAnalysisData = obj; + historyItem3.VolumeAnalysisData = obj; + } + historyItem.VolumeAnalysisData.?(??, historyItem2); + } + num++; + } + ?(P_0, i); + return result; + } + + private protected virtual void ?(HistoricalData P_0, int P_1) + { + } + + protected override void ?() + { + if (?? != null) + { + ??.?(?); + } + } + + protected override void ?() + { + if (?? != null) + { + ??.?(?); + } + } + + protected override VolumeAnalysisData ?(long P_0) + { + int num = (int)??.GetIndexByTime(P_0, SeekOriginHistory.Begin); + if (num < 0 || num >= ??.Count) + { + return null; + } + IHistoryItem historyItem = ??[num, SeekOriginHistory.Begin]; + if (historyItem == null) + { + return null; + } + return ?(historyItem, num); + } + + private protected VolumeAnalysisData ?(IHistoryItem P_0, int P_1) + { + if (P_0.VolumeAnalysisData != null) + { + return P_0.VolumeAnalysisData; + } + P_0.VolumeAnalysisData = new VolumeAnalysisData + { + TimeLeft = P_0.TimeLeft + }; + if (P_1 <= 0) + { + return P_0.VolumeAnalysisData; + } + IHistoryItem historyItem = ??[P_1 - 1, SeekOriginHistory.Begin]; + if (historyItem?.VolumeAnalysisData != null) + { + P_0.VolumeAnalysisData.Total.?? = ?(historyItem.TimeLeft, P_0.TimeLeft, historyItem.VolumeAnalysisData.Total.CumulativeDelta); + } + return P_0.VolumeAnalysisData; + } + + private void ?(object P_0, HistoryEventArgs P_1) + { + if (P_1 is ? { MessageQuote: not null } ?2) + { + ?(?2.MessageQuote); + } + } + + protected override void ?(MessageQuote P_0) + { + base.?(P_0); + ???.?(); + } + + protected override Interval ?() + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + DateTime dateTime = ??.From; + DateTime dateTime2 = ((??.ToTime == default(DateTime)) ? dateTimeUtcNow : ??.ToTime); + if (dateTime > dateTimeUtcNow) + { + dateTime = dateTimeUtcNow; + } + if (dateTime2 > dateTimeUtcNow) + { + dateTime2 = dateTimeUtcNow; + } + if (base.Symbol.QuoteDelay != default(TimeSpan) && dateTime2 > dateTimeUtcNow - base.Symbol.QuoteDelay) + { + dateTime2 -= base.Symbol.QuoteDelay; + } + return new Interval(dateTime, dateTime2); + } + + private int ?(HistoricalData P_0, Interval P_1) + { + if (P_0 == null || P_0.Count == 0) + { + return -1; + } + if (new Interval(P_0[0, SeekOriginHistory.Begin].TimeLeft, new DateTime(P_0[0, SeekOriginHistory.End].TicksRight, DateTimeKind.Utc)).Intersect(P_1) == Interval.Default) + { + return -1; + } + long num = P_1.From.Ticks; + long num2 = Math.Abs(P_0.Aggregation.GetPeriod.Ticks); + do + { + int num3 = (int)P_0.GetIndexByTime(num, SeekOriginHistory.Begin); + if (num3 >= 0) + { + return num3; + } + num += num2; + } + while (num <= P_1.To.Ticks); + return -1; + } + + private double ?(DateTime P_0, DateTime P_1, double P_2) + { + TimeZoneInfo timeZoneInfo = ??.TimeZone.TimeZoneInfo; + DateTime dateTime = P_0; + DateTime dateTime2 = P_1; + if (timeZoneInfo != null) + { + dateTime = TimeZoneInfo.ConvertTime(P_0, timeZoneInfo); + dateTime2 = TimeZoneInfo.ConvertTime(P_1, timeZoneInfo); + } + return ??.CumulativeDeltaReset switch + { + CumulativeDeltaReset.Never => P_2, + CumulativeDeltaReset.Daily => (dateTime.DayOfWeek != dateTime2.DayOfWeek) ? 0.0 : P_2, + CumulativeDeltaReset.Weekly => (dateTime.GetWeekOfYear() != dateTime2.GetWeekOfYear()) ? 0.0 : P_2, + CumulativeDeltaReset.ByChartSession => ?(??.SessionsContainer, P_0, P_1) ? 0.0 : P_2, + _ => P_2, + }; + } + + private bool ?(ISessionsContainer P_0, DateTime P_1, DateTime P_2) + { + if (P_0 == null) + { + return false; + } + ISession sessionForDate = P_0.GetSessionForDate(P_2); + if (sessionForDate == null) + { + return false; + } + ISession sessionForDate2 = P_0.GetSessionForDate(P_1); + if (sessionForDate2 == null) + { + return true; + } + if (P_1.TimeOfDay <= sessionForDate2.CloseTime && P_1.TimeOfDay < sessionForDate.OpenTime && sessionForDate.OpenTime <= P_2.TimeOfDay && sessionForDate2.CloseTime < P_2.TimeOfDay) + { + return true; + } + return false; + } + } +} +namespace TradingPlatform.BusinessLayer +{ + public class VolumeAnalysisTaskEventArgs : EventArgs + { + [CompilerGenerated] + private readonly VolumeAnalysisCalculationState ??; + + [CompilerGenerated] + private readonly int ??; + + public VolumeAnalysisCalculationState CalculationState + { + [CompilerGenerated] + get + { + return ??; + } + } + + public int ProgressPercent + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal VolumeAnalysisTaskEventArgs(IVolumeAnalysisCalculationProgress P_0) + { + ?? = P_0.State; + ?? = P_0.ProgressPercent; + } + } + [Published] + public class VolumeAnalysisData + { + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private VolumeAnalysisItem ??; + + [CompilerGenerated] + private Dictionary ??; + + [CompilerGenerated] + private EventHandler ??; + + public DateTime TimeLeft + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Summary calculated Volume info + /// + public VolumeAnalysisItem Total + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Volume info for each price + /// + public Dictionary PriceLevels + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Fire in case of price level was added or existing was updated + /// + public event EventHandler ItemUpdated + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public VolumeAnalysisData() + { + Total = new VolumeAnalysisItem(); + PriceLevels = new Dictionary(); + } + + internal VolumeAnalysisData(VolumeAnalysisData P_0) + { + TimeLeft = P_0.TimeLeft; + Total = new VolumeAnalysisItem(P_0.Total); + PriceLevels = new Dictionary(); + foreach (KeyValuePair priceLevel in P_0.PriceLevels) + { + PriceLevels.Add(priceLevel.Key, new VolumeAnalysisItem(priceLevel.Value)); + } + } + + internal void ?(VolumeAnalysisCalculationRequest P_0, HistoricalData P_1) + { + foreach (object item in P_1) + { + ?(P_0, item); + } + } + + internal void ?(VolumeAnalysisCalculationRequest P_0, MessageQuote P_1) + { + ?(P_0, (object)P_1); + } + + internal void ?(VolumeAnalysisCalculationRequest P_0, IVolumeTickData P_1) + { + ?(P_0, (object)P_1); + } + + internal void ?(VolumeAnalysisCalculationRequest P_0, object P_1) + { + if (!(P_1 is IVolumeTickData { Price: var price, Volume: var volume } volumeTickData)) + { + return; + } + AggressorFlag aggressorFlag = ((P_0.DeltaCalculationType == DeltaCalculationType.TickDirection) ? Symbol.ConvertTickDirection(volumeTickData.TickDirection) : volumeTickData.AggressorFlag); + bool flag = volumeTickData.VolumeTickDataType == VolumeTickDataType.Ticks; + long time = volumeTickData.Time; + if (P_0.SessionsContainer == null || P_0.SessionsContainer.ContainsDate(time)) + { + double num = P_0.Symbol.GetTickSize(price); + if (!P_0.CustomTickSize.IsNanOrDefault()) + { + num = P_0.CustomTickSize; + } + if (P_0.CustomStep > 1) + { + num *= (double)P_0.CustomStep; + } + if (!double.IsNaN(P_0.Symbol.MinVolumeAnalysisTickSize) && num < P_0.Symbol.MinVolumeAnalysisTickSize) + { + num = P_0.Symbol.MinVolumeAnalysisTickSize; + } + double num2 = CoreMath.RoundToIncrement(price, num); + ?(num2, volume, aggressorFlag, flag, P_0.FilteredVolume); + } + } + + private void ?(double P_0, double P_1, AggressorFlag P_2, bool P_3, double P_4) + { + Total.?(P_1, P_2, P_3, P_4); + if (!PriceLevels.TryGetValue(P_0, out var value)) + { + PriceLevels.Add(P_0, value = new VolumeAnalysisItem()); + } + value.?(P_1, P_2, P_3, P_4); + ?(P_0, value); + } + + public void Calculate(double price, double size, AggressorFlag aggressorFlag) + { + ?(price, size, aggressorFlag, false, 0.0); + } + + public VolumeAnalysisData CreateAggregatedSnapshot(double aggregationStep) + { + VolumeAnalysisData volumeAnalysisData = new VolumeAnalysisData(); + try + { + volumeAnalysisData.Total = Total; + foreach (KeyValuePair priceLevel in PriceLevels) + { + double key = CoreMath.RoundToIncrement(priceLevel.Key, aggregationStep); + if (!volumeAnalysisData.PriceLevels.TryGetValue(key, out var value)) + { + volumeAnalysisData.PriceLevels.Add(key, value = new VolumeAnalysisItem()); + } + value.Combine(priceLevel.Value); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return volumeAnalysisData; + } + + private void ?(double P_0, VolumeAnalysisItem P_1) + { + ???.Invoke(this, new VolumeAnalysisDataEventArgs(P_0, P_1)); + } + + public void Combine(VolumeAnalysisData data) + { + Total.Combine(data.Total); + foreach (KeyValuePair priceLevel in data.PriceLevels) + { + if (!PriceLevels.TryGetValue(priceLevel.Key, out var value)) + { + value = (PriceLevels[priceLevel.Key] = new VolumeAnalysisItem()); + } + value.Combine(priceLevel.Value); + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 2); + defaultInterpolatedStringHandler.AppendFormatted(TimeLeft); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PriceLevels.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [Published] + public class VolumeAnalysisDataEventArgs : EventArgs + { + [CompilerGenerated] + private readonly double ??; + + [CompilerGenerated] + private readonly VolumeAnalysisItem ??; + + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + } + + public VolumeAnalysisItem Item + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal VolumeAnalysisDataEventArgs(double P_0, VolumeAnalysisItem P_1) + { + ?? = P_0; + ?? = P_1; + } + } + [Published] + public enum VolumeAnalysisCalculationState + { + None = 0, + Processing = 4, + Finished = 0x10 + } + [Published] + [Obfuscation(ApplyToMembers = true, Exclude = true)] + public enum VolumeAnalysisField + { + Trades, + BuyTrades, + SellTrades, + Volume, + BuyVolume, + SellVolume, + BuySellVolume, + FilteredVolume, + FilteredBuyVolume, + FilteredSellVolume, + MaxOneTradeVolume, + BuyVolumePercent, + SellVolumePercent, + Delta, + DeltaPercent, + CumulativeDelta, + FilteredTotalVolumePercent, + FilteredBuyVolumePercent, + FilteredSellVolumePercent, + MaxOneTradeVolumePercent, + AverageSize, + AverageBuySize, + AverageSellSize, + OpenInterest, + MinDelta, + MaxDelta, + DeltaFinish + } + public enum CumulativeDeltaReset + { + [Description("Full chart range")] + Never, + [Description("Daily")] + Daily, + [Description("Weekly")] + Weekly, + [Description("By chart session")] + ByChartSession + } + /// + /// Represent item with Volume Analysis calculation results + /// + [Published] + public class VolumeAnalysisItem : IVolumeAnalysisItem + { + private const double ?? = double.MaxValue; + + private const double ?? = double.MinValue; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + internal double ??; + + public int Trades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int BuyTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int SellTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Volume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double BuyVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double SellVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double FilteredTotalVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double FilteredBuyVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double FilteredSellVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public double MaxOneTradeVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double MinDelta + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double MaxDelta + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double BuyVolumePercent + { + get + { + if (!(Volume > 0.0)) + { + return 0.0; + } + return BuyVolume / Volume * 100.0; + } + } + + public double SellVolumePercent + { + get + { + if (!(Volume > 0.0)) + { + return 0.0; + } + return SellVolume / Volume * 100.0; + } + } + + public double Delta => BuyVolume - SellVolume; + + public double DeltaPercent + { + get + { + if (Volume == 0.0) + { + return 0.0; + } + return Delta / Volume * 100.0; + } + } + + public double CumulativeDelta => ?? + Delta; + + public double FilteredTotalVolumePercent + { + get + { + if (!(Volume > 0.0)) + { + return 0.0; + } + return FilteredTotalVolume / Volume * 100.0; + } + } + + public double FilteredBuyVolumePercent + { + get + { + if (!(Volume > 0.0)) + { + return 0.0; + } + return FilteredBuyVolume / Volume * 100.0; + } + } + + public double FilteredSellVolumePercent + { + get + { + if (!(Volume > 0.0)) + { + return 0.0; + } + return FilteredSellVolume / Volume * 100.0; + } + } + + public double MaxOneTradeVolumePercent + { + get + { + if (!(Volume > 0.0)) + { + return 0.0; + } + return MaxOneTradeVolume / Volume * 100.0; + } + } + + public double AverageSize + { + get + { + if (Trades <= 0) + { + return 0.0; + } + return Volume / (double)Trades; + } + } + + public double AverageBuySize + { + get + { + if (BuyTrades <= 0) + { + return 0.0; + } + return BuyVolume / (double)BuyTrades; + } + } + + public double AverageSellSize + { + get + { + if (SellTrades <= 0) + { + return 0.0; + } + return SellVolume / (double)SellTrades; + } + } + + public double DeltaFinish => Delta - ((Math.Abs(MinDelta) > Math.Abs(MaxDelta)) ? MinDelta : MaxDelta); + + public VolumeAnalysisItem() + { + MinDelta = double.MaxValue; + MaxDelta = double.MinValue; + } + + internal VolumeAnalysisItem(VolumeAnalysisItem P_0) + { + Trades = P_0.Trades; + BuyTrades = P_0.BuyTrades; + SellTrades = P_0.SellTrades; + Volume = P_0.Volume; + BuyVolume = P_0.BuyVolume; + SellVolume = P_0.SellVolume; + FilteredTotalVolume = P_0.FilteredTotalVolume; + FilteredBuyVolume = P_0.FilteredBuyVolume; + FilteredSellVolume = P_0.FilteredSellVolume; + MaxOneTradeVolume = P_0.MaxOneTradeVolume; + MinDelta = P_0.MinDelta; + MaxDelta = P_0.MaxDelta; + ?? = P_0.??; + } + + public double GetValue(VolumeAnalysisField field) + { + return field switch + { + VolumeAnalysisField.Trades => Trades, + VolumeAnalysisField.BuyTrades => BuyTrades, + VolumeAnalysisField.SellTrades => SellTrades, + VolumeAnalysisField.Volume => Volume, + VolumeAnalysisField.BuySellVolume => Volume, + VolumeAnalysisField.BuyVolume => BuyVolume, + VolumeAnalysisField.BuyVolumePercent => BuyVolumePercent, + VolumeAnalysisField.SellVolume => SellVolume, + VolumeAnalysisField.SellVolumePercent => SellVolumePercent, + VolumeAnalysisField.Delta => Delta, + VolumeAnalysisField.DeltaPercent => DeltaPercent, + VolumeAnalysisField.CumulativeDelta => CumulativeDelta, + VolumeAnalysisField.AverageSize => AverageSize, + VolumeAnalysisField.AverageBuySize => AverageBuySize, + VolumeAnalysisField.AverageSellSize => AverageSellSize, + VolumeAnalysisField.MaxOneTradeVolume => MaxOneTradeVolume, + VolumeAnalysisField.MaxOneTradeVolumePercent => MaxOneTradeVolumePercent, + VolumeAnalysisField.FilteredVolume => FilteredTotalVolume, + VolumeAnalysisField.FilteredTotalVolumePercent => FilteredTotalVolumePercent, + VolumeAnalysisField.FilteredBuyVolume => FilteredBuyVolume, + VolumeAnalysisField.FilteredBuyVolumePercent => FilteredBuyVolumePercent, + VolumeAnalysisField.FilteredSellVolume => FilteredSellVolume, + VolumeAnalysisField.FilteredSellVolumePercent => FilteredSellVolumePercent, + VolumeAnalysisField.MinDelta => (MinDelta != double.MaxValue) ? MinDelta : 0.0, + VolumeAnalysisField.MaxDelta => (MaxDelta != double.MinValue) ? MaxDelta : 0.0, + VolumeAnalysisField.DeltaFinish => DeltaFinish, + _ => 0.0, + }; + } + + public void Combine(VolumeAnalysisItem item) + { + Trades += item.Trades; + BuyTrades += item.BuyTrades; + SellTrades += item.SellTrades; + Volume += item.Volume; + BuyVolume += item.BuyVolume; + SellVolume += item.SellVolume; + FilteredTotalVolume += item.FilteredTotalVolume; + FilteredBuyVolume += item.FilteredBuyVolume; + FilteredSellVolume += item.FilteredSellVolume; + MaxOneTradeVolume = Math.Max(item.MaxOneTradeVolume, MaxOneTradeVolume); + MinDelta = ((MinDelta == double.MaxValue) ? Math.Min(MinDelta, item.MinDelta) : double.NaN); + MaxDelta = ((MaxDelta == double.MinValue) ? Math.Max(MaxDelta, item.MaxDelta) : double.NaN); + } + + internal void ?(double P_0, AggressorFlag P_1 = AggressorFlag.None, bool P_2 = false, double P_3 = 0.0) + { + Volume += P_0; + BuyVolume += ((P_1 == AggressorFlag.Buy) ? P_0 : 0.0); + SellVolume += ((P_1 == AggressorFlag.Sell) ? P_0 : 0.0); + double delta = Delta; + MinDelta = Math.Min(MinDelta, delta); + MaxDelta = Math.Max(MaxDelta, delta); + if (P_2) + { + return; + } + Trades++; + if (P_0 > MaxOneTradeVolume) + { + MaxOneTradeVolume = P_0; + } + if (P_0 >= P_3) + { + FilteredTotalVolume += P_0; + } + switch (P_1) + { + case AggressorFlag.Buy: + BuyTrades++; + if (P_0 >= P_3) + { + FilteredBuyVolume += P_0; + } + break; + case AggressorFlag.Sell: + SellTrades++; + if (P_0 >= P_3) + { + FilteredSellVolume += P_0; + } + break; + } + } + } + /// + /// Volume Analysis calculations + /// + [Published] + public class VolumeAnalysisManager + { + private const int ?? = 10; + + private const int ?? = 7; + + private int ??; + + private readonly ActionBufferedProcessorWithPriority ??; + + internal VolumeAnalysisManager() + { + ?? = new ActionBufferedProcessorWithPriority(3); + } + + internal void ?() + { + ??.Start(); + } + + internal void ?() + { + ???.Stop(); + } + + /// + /// Calculate volume profile for requested time range + /// + public IVolumeAnalysisCalculationTask CalculateProfile(VolumeAnalysisCalculationRequest request) + { + VolumeAnalysisCalculationRequest volumeAnalysisCalculationRequest = new VolumeAnalysisCalculationRequest(request); + if (Core.Instance.SymbolsMapping.TryGetVolumeAnalysisSymbol(request.Symbol, out var volumeAnalysisSymbol)) + { + volumeAnalysisCalculationRequest.Symbol = volumeAnalysisSymbol; + } + bool num = ?(volumeAnalysisCalculationRequest); + ? ? = new ?(volumeAnalysisCalculationRequest); + if (!num) + { + ?.State = VolumeAnalysisCalculationState.Finished; + return ?; + } + ??.Push(?.?, 1, volumeAnalysisCalculationRequest.Marker); + return ?; + } + + /// + /// Calculate volume profile for each bar in History Data + /// + public IVolumeAnalysisCalculationProgress CalculateProfile(HistoricalData historicalData, VolumeAnalysisCalculationParameters calculationParameters) + { + VolumeAnalysisCalculationRequest volumeAnalysisCalculationRequest = new VolumeAnalysisCalculationRequest(calculationParameters) + { + Symbol = historicalData.Symbol, + From = ((historicalData.Count == 0) ? Core.Instance.TimeUtils.DateTimeUtcNow : historicalData[0, SeekOriginHistory.Begin].TimeLeft), + To = ((historicalData.ToTime == DateTime.MinValue) ? Core.Instance.TimeUtils.DateTimeUtcNow : historicalData.ToTime) + }; + if (Core.Instance.SymbolsMapping.TryGetVolumeAnalysisSymbol(volumeAnalysisCalculationRequest.Symbol, out var volumeAnalysisSymbol)) + { + volumeAnalysisCalculationRequest.Symbol = volumeAnalysisSymbol; + } + bool num = ?(volumeAnalysisCalculationRequest); + ? ? = ((historicalData.Aggregation.BarCreationBehavior == BarCreationBehavior.Deferred) ? new ?(historicalData, volumeAnalysisCalculationRequest) : new ?(historicalData, volumeAnalysisCalculationRequest)); + if (!num) + { + ?.State = VolumeAnalysisCalculationState.Finished; + return ?; + } + historicalData.VolumeAnalysisCalculationProgress = ?; + ??.Push(?.?, 1, volumeAnalysisCalculationRequest.Marker); + return ?; + } + + /// + /// Calculate volume profile for requested time range + /// + public IVolumeAnalysisCalculationTask CalculateProfile(Symbol symbol, DateTime from, DateTime to) + { + return CalculateProfile(new VolumeAnalysisCalculationRequest + { + Symbol = symbol, + From = from, + To = to + }); + } + + /// + /// Calculate volume profile for each bar in History Data + /// + public IVolumeAnalysisCalculationProgress CalculateProfile(HistoricalData historicalData) + { + return CalculateProfile(historicalData, new VolumeAnalysisCalculationParameters()); + } + + private bool ?(VolumeAnalysisCalculationRequest P_0) + { + if (P_0 == null) + { + return false; + } + if ((Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) == null && Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), P_0.Symbol).Status != TradingOperationStatus.Allowed && Core.Instance.RulesManager.IsAllowed(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0.Symbol).Status != TradingOperationStatus.Allowed && (P_0.Symbol == null || P_0.Symbol.State != BusinessObjectState.Fake)) + { + ??++; + if (?? > 10) + { + Core.Instance.Licences.OnLicenceCheckError(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null); + return false; + } + DateTime dateTime = Core.Instance.TimeUtils.DateTimeUtcNow.AddDays(-7.0); + if (P_0.From < dateTime) + { + P_0.From = dateTime; + Core.Instance.Licences.OnLicenceCheckError(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null); + } + } + return true; + } + } +} +namespace TradingPlatform.BusinessLayer.TimeSync +{ + public enum _Mode + { + SymmetricActive, + SymmetricPassive, + Client, + Server, + Broadcast, + Unknown + } + public enum _Stratum + { + Unspecified, + PrimaryReference, + SecondaryReference, + Reserved + } + /// + /// from: + /// http://www.codeguru.com/csharp/csharp/cs_date_time/timeroutines/article.php/c4207/C-SNTP-Client.htm + /// +++ ???????? ???????, ?????????? ToString(), ????? ?????? ?????. + /// +++ ReceiveTimeout?SendTimeout + /// + /// NTPClient is a C# class designed to connect to time servers on the Internet. + /// The implementation of the protocol is based on the RFC 2030. + /// + /// Public class members: + /// + /// LeapIndicator - Warns of an impending leap second to be inserted/deleted in the last + /// minute of the current day. (See the _LeapIndicator enum) + /// + /// VersionNumber - Version number of the protocol (3 or 4). + /// + /// Mode - Returns mode. (See the _Mode enum) + /// + /// Stratum - Stratum of the clock. (See the _Stratum enum) + /// + /// PollInterval - Maximum interval between successive messages. + /// + /// Precision - Precision of the clock. + /// + /// RootDelay - Round trip time to the primary reference source. + /// + /// RootDispersion - Nominal error relative to the primary reference source. + /// + /// ReferenceTimestamp - The time at which the clock was last set or corrected. + /// + /// OriginateTimestamp - The time at which the request departed the client for the server. + /// + /// ReceiveTimestamp - The time at which the request arrived at the server. + /// + /// Transmit Timestamp - The time at which the reply departed the server for client. + /// + /// RoundTripDelay - The time between the departure of request and arrival of reply. + /// + /// LocalClockOffset - The offset of the local clock relative to the primary reference + /// source. + /// + /// Initialize - Sets up data structure and prepares for connection. + /// + /// Connect - Connects to the time server and populates the data structure. + /// + /// IsResponseValid - Returns true if received data is valid and if comes from + /// a NTP-compliant time server. + /// + /// ToString - Returns a string representation of the object. + /// + /// ----------------------------------------------------------------------------- + /// Structure of the standard NTP header (as described in RFC 2030) + /// 1 2 3 + /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// |LI | VN |Mode | Stratum | Poll | Precision | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | Root Delay | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | Root Dispersion | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | Reference Identifier | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | | + /// | Reference Timestamp (64) | + /// | | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | | + /// | Originate Timestamp (64) | + /// | | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | | + /// | Receive Timestamp (64) | + /// | | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | | + /// | Transmit Timestamp (64) | + /// | | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | Key Identifier (optional) (32) | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | | + /// | | + /// | Message Digest (optional) (128) | + /// | | + /// | | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// + /// ----------------------------------------------------------------------------- + /// + /// NTP Timestamp Format (as described in RFC 2030) + /// 1 2 3 + /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | Seconds | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// | Seconds Fraction (0-padded) | + /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /// + /// + public class NTPClient : IDisposable + { + private const byte ?? = 48; + + private const byte ?? = 16; + + private const byte ?? = 24; + + private const byte ?? = 32; + + private const byte ?? = 40; + + private byte[] ??; + + public DateTime ReceptionTimestamp; + + private UdpClient ??; + + private readonly string ??; + + public byte VersionNumber => (byte)((??[0] & 0x38) >> 3); + + public _Mode Mode => (byte)(??[0] & 7) switch + { + 1 => _Mode.SymmetricActive, + 2 => _Mode.SymmetricPassive, + 3 => _Mode.Client, + 4 => _Mode.Server, + 5 => _Mode.Broadcast, + _ => _Mode.Unknown, + }; + + public _Stratum Stratum + { + get + { + byte b = ??[1]; + if (b == 0) + { + return _Stratum.Unspecified; + } + if (b == 1) + { + return _Stratum.PrimaryReference; + } + if (b <= 15) + { + return _Stratum.SecondaryReference; + } + return _Stratum.Reserved; + } + } + + public double Precision => 1000.0 * Math.Pow(2.0, (int)??[3]); + + public DateTime ReferenceTimestamp + { + get + { + DateTime dateTime = ?(?(16)); + TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now); + return dateTime + utcOffset; + } + } + + public DateTime OriginateTimestamp => ?(?(24)); + + public DateTime ReceiveTimestamp + { + get + { + DateTime dateTime = ?(?(32)); + TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now); + return dateTime + utcOffset; + } + } + + public DateTime TransmitTimestamp + { + get + { + DateTime dateTime = ?(?(40)); + TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now); + return dateTime + utcOffset; + } + set + { + ?(40, value); + } + } + + public int RoundTripDelay => (int)(ReceiveTimestamp - OriginateTimestamp + (ReceptionTimestamp - TransmitTimestamp)).TotalMilliseconds; + + public int LocalClockOffset => (int)((ReceiveTimestamp - OriginateTimestamp - (ReceptionTimestamp - TransmitTimestamp)).TotalMilliseconds / 2.0); + + private DateTime ?(ulong P_0) + { + TimeSpan timeSpan = TimeSpan.FromMilliseconds(P_0); + return new DateTime(1900, 1, 1) + timeSpan; + } + + private ulong ?(byte P_0) + { + ulong num = 0uL; + ulong num2 = 0uL; + for (int i = 0; i <= 3; i++) + { + num = 256 * num + ??[P_0 + i]; + } + for (int j = 4; j <= 7; j++) + { + num2 = 256 * num2 + ??[P_0 + j]; + } + return num * 1000 + num2 * 1000 / 4294967296L; + } + + private void ?(byte P_0, DateTime P_1) + { + DateTime dateTime = new DateTime(1900, 1, 1, 0, 0, 0); + ulong num = (ulong)(P_1 - dateTime).TotalMilliseconds; + ulong num2 = num / 1000; + ulong num3 = num % 1000 * 4294967296L / 1000; + ulong num4 = num2; + for (int num5 = 3; num5 >= 0; num5--) + { + ??[P_0 + num5] = (byte)(num4 % 256); + num4 /= 256; + } + num4 = num3; + for (int num6 = 7; num6 >= 4; num6--) + { + ??[P_0 + num6] = (byte)(num4 % 256); + num4 /= 256; + } + } + + private void ?() + { + ??[0] = 27; + for (int i = 1; i < 48; i++) + { + ??[i] = 0; + } + TransmitTimestamp = DateTime.Now; + } + + public NTPClient(string host) + { + ?? = new byte[48]; + ?? = host; + } + + /// + /// Connect to the time server + /// + public void Connect() + { + try + { + try + { + if (?? != null) + { + ??.Close(); + } + } + catch + { + } + IPEndPoint remoteEP = new IPEndPoint(Dns.GetHostAddresses(??)[0], 123); + ?? = new UdpClient(); + ??.Connect(remoteEP); + ?(); + Socket client = ??.Client; + int receiveTimeout = (??.Client.SendTimeout = (int)TimeSpan.FromSeconds(5.0).TotalMilliseconds); + client.ReceiveTimeout = receiveTimeout; + ??.Send(??, ??.Length); + ?? = ??.Receive(ref remoteEP); + if (!IsResponseValid()) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ??); + } + ReceptionTimestamp = DateTime.Now; + } + catch (SocketException ex) + { + throw new Exception(ex.Message); + } + } + + public bool IsResponseValid() + { + if (??.Length < 48 || Mode != _Mode.Server) + { + return false; + } + return true; + } + + public override string ToString() + { + string text = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + switch (Mode) + { + case _Mode.Unknown: + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + break; + case _Mode.SymmetricActive: + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + break; + case _Mode.SymmetricPassive: + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + break; + case _Mode.Client: + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + break; + case _Mode.Server: + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + break; + case _Mode.Broadcast: + text += 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + break; + } + text = text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + TransmitTimestamp; + text = text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + LocalClockOffset + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + return text + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + + public void Dispose() + { + try + { + if (?? != null) + { + ??.Close(); + } + ?? = null; + } + catch + { + } + } + } +} +namespace ? +{ + internal sealed class ? : IDisposable + { + private const int ?? = 1800000; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private ? ??; + + [CompilerGenerated] + private string ??; + + private ReadOnlyCollection ??; + + private Timer ??; + + public int ServerTimeOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = num; + } + } + + public ? State + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = ?2; + } + } + + public string LastSyncErrorMessage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public ?() + { + State = ?.??; + } + + public void ?() + { + ServerTimeOffset = 0; + ?? = new string[4] + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }.AsReadOnly(); + ?? = new Timer(?, null, TimeSpan.FromMilliseconds(-1.0), new TimeSpan(1, 0, 0)); + ?(); + } + + public void Dispose() + { + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + } + + public void ?() + { + bool flag = false; + string text = string.Empty; + try + { + State = ?.??; + foreach (string item in ??) + { + try + { + using NTPClient nTPClient = new NTPClient(item); + nTPClient.Connect(); + if (nTPClient.IsResponseValid()) + { + if (nTPClient.LocalClockOffset <= 1800000) + { + flag = true; + ServerTimeOffset = nTPClient.LocalClockOffset; + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(45, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ServerTimeOffset); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + break; + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + item); + } + } + catch (Exception ex) + { + text = ex.Message; + Core.Instance.Loggers.Log(text, LoggingLevel.Verbose); + } + } + } + finally + { + if (flag) + { + State = ?.??; + LastSyncErrorMessage = string.Empty; + } + else + { + State = ?.??; + LastSyncErrorMessage = text; + } + } + } + + private void ?(object P_0) + { + ?(); + } + } + internal enum ? + { + ??, + ??, + ??, + ?? + } +} +namespace TradingPlatform.BusinessLayer.Options +{ + public sealed class BlackScholesPriceModel : PriceModel + { + public const double START_IV = 1E-05; + + public override PriceModels Type => PriceModels.BlackScholes; + + protected override double NormDist(double x) + { + double num = 0.049867347; + double num2 = 0.0211410061; + double num3 = 0.0032776263; + double num4 = 3.80036E-05; + double num5 = 4.88906E-05; + double num6 = 5.383E-06; + double num7 = Math.Abs(x); + double num8 = 1.0 + num7 * (num + num7 * (num2 + num7 * (num3 + num7 * (num4 + num7 * (num5 + num7 * num6))))); + num8 *= num8; + num8 *= num8; + num8 *= num8; + num8 *= num8; + num8 = 1.0 / (2.0 * num8); + if (x >= 0.0) + { + num8 = 1.0 - num8; + } + return num8; + } + + public override double Delta(Symbol option, double IV, double Int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Delta(option.ExpirationDate, option.StrikePrice, option.OptionType, option.Underlier.Last, IV, Int_Rate, shift); + } + + public override double Delta(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + double num = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num <= 0.0) + { + num = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double x = (Math.Log(price / StrikePrice) + (Int_Rate + IV * IV / 2.0) * num) / (IV * Math.Sqrt(num)); + Math.Sqrt(num); + if (OptionType == OptionType.Call) + { + return NormDist(x); + } + return NormDist(x) - 1.0; + } + + public override double Gamma(Symbol option, double IV, double int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Gamma(option.ExpirationDate, option.StrikePrice, option.OptionType, option.Underlier.Last, IV, int_Rate, shift); + } + + public override double Gamma(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + double num = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num <= 0.0) + { + num = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double num2 = (Math.Log(price / StrikePrice) + (Int_Rate + IV * IV / 2.0) * num) / (IV * Math.Sqrt(num)); + Math.Sqrt(num); + return Math.Exp(-1.0 * num2 * num2 / 2.0) / Math.Sqrt(Math.PI * 2.0) / (price * IV * Math.Sqrt(num)); + } + + public override double TheorPrice(Symbol option, double IV, double Int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return TheorPrice(option.ExpirationDate, option.StrikePrice, option.OptionType, option.Underlier.Last, IV, Int_Rate, shift); + } + + public override double TheorPrice(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + double num = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num <= 0.0) + { + num = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double num2 = (Math.Log(price / StrikePrice) + (Int_Rate + IV * IV / 2.0) * num) / (IV * Math.Sqrt(num)); + double num3 = num2 - IV * Math.Sqrt(num); + if (OptionType == OptionType.Call) + { + return price * NormDist(num2) - StrikePrice * Math.Exp(-1.0 * (Int_Rate * num)) * NormDist(num3); + } + return StrikePrice * Math.Exp(-1.0 * (Int_Rate * num)) * NormDist(0.0 - num3) - price * NormDist(0.0 - num2); + } + + public override double IV(Symbol option, OptionPriceType priceType, double Int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return IV(option.ExpirationDate, option.StrikePrice, option.OptionType, OptionMath.GetOptionLastPrice(option, priceType), option.Underlier.Last, priceType, Int_Rate, shift); + } + + public override double IV(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double optionPrice, double underlierPrice, OptionPriceType priceType, double Int_Rate, double shift) + { + if (double.IsNaN(optionPrice)) + { + return double.NaN; + } + double num = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num <= 0.0) + { + num = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double num2 = 0.0; + double num3 = 0.0; + double num4 = 1E-05; + if (optionPrice == 0.0 || underlierPrice == 0.0 || StrikePrice == 0.0 || num <= 0.0) + { + return 0.0; + } + if (underlierPrice <= optionPrice) + { + return 0.0; + } + double num5 = 0.1; + if (OptionType == OptionType.Call) + { + while (num2 <= optionPrice) + { + while (true) + { + double num6 = (Math.Log(underlierPrice / StrikePrice) + (Int_Rate + num4 * num4 / 2.0) * num) / (num4 * Math.Sqrt(num)); + double x = num6 - num4 * Math.Sqrt(num); + num2 = underlierPrice * NormDist(num6) - StrikePrice * Math.Exp(-1.0 * (Int_Rate * num)) * NormDist(x); + if (!(num2 > optionPrice) || !(num5 > 1E-05) || !(num4 > 0.0001)) + { + break; + } + num4 -= num5; + num5 *= 0.1; + num4 += num5; + } + if (num2 > optionPrice) + { + return num4; + } + num4 += num5; + if (num4 > 10000.0) + { + return double.NaN; + } + } + return num4; + } + while (num3 <= optionPrice) + { + while (true) + { + double num6 = (Math.Log(underlierPrice / StrikePrice) + (Int_Rate + num4 * num4 / 2.0) * num) / (num4 * Math.Sqrt(num)); + double x = num6 - num4 * Math.Sqrt(num); + num3 = StrikePrice * Math.Exp(-1.0 * (Int_Rate * num)) * NormDist(0.0 - x) - underlierPrice * NormDist(0.0 - num6); + if (!(num3 > optionPrice) || !(num5 > 1E-05) || !(num4 > 0.0001)) + { + break; + } + num4 -= num5; + num5 *= 0.1; + num4 += num5; + } + if (num3 > optionPrice) + { + return num4; + } + num4 += num5; + if (num4 > 10000.0) + { + return double.NaN; + } + } + return num4; + } + + public override double Theta(Symbol option, double IV, double int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Theta(option.ExpirationDate, option.StrikePrice, option.OptionType, option.Underlier.Last, IV, int_Rate, shift); + } + + public override double Theta(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double int_Rate, double shift) + { + double num = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num <= 0.0) + { + num = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double num2 = (Math.Log(price / StrikePrice) + (int_Rate + IV * IV / 2.0) * num) / (IV * Math.Sqrt(num)); + double num3 = num2 - IV * Math.Sqrt(num); + if (OptionType == OptionType.Call) + { + return (-1.0 * (price * (Math.Exp(-1.0 * num2 * num2 / 2.0) / Math.Sqrt(Math.PI * 2.0)) * IV) / (2.0 * Math.Sqrt(num)) - int_Rate * StrikePrice * Math.Exp(-1.0 * (int_Rate * num)) * NormDist(num3)) / 365.0; + } + return (-1.0 * (price * (Math.Exp(-1.0 * num2 * num2 / 2.0) / Math.Sqrt(Math.PI * 2.0)) * IV) / (2.0 * Math.Sqrt(num)) + int_Rate * StrikePrice * Math.Exp(-1.0 * (int_Rate * num)) * NormDist(0.0 - num3)) / 365.0; + } + + public override double Vega(Symbol option, double IV, double int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Vega(option.ExpirationDate, option.StrikePrice, option.OptionType, option.Underlier.Last, IV, int_Rate, shift); + } + + public override double Vega(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double int_Rate, double shift) + { + double num = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num <= 0.0) + { + num = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double num2 = (Math.Log(price / StrikePrice) + (int_Rate + IV * IV / 2.0) * num) / (IV * Math.Sqrt(num)); + Math.Sqrt(num); + return price * Math.Sqrt(num) * (Math.Exp(-1.0 * num2 * num2 / 2.0) / Math.Sqrt(Math.PI * 2.0)) / 100.0; + } + + public override double Rho(Symbol option, double IV, double int_Rate, double shift) + { + if (option == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (option.Underlier == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return Rho(option.ExpirationDate, option.StrikePrice, option.OptionType, option.Underlier.Last, IV, int_Rate, shift); + } + + public override double Rho(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double int_Rate, double shift) + { + double num = StrikePrice; + double num2 = ((double)OptionMath.CalculateDaysToExpire(ExpirationDate) - shift) / 365.0; + if (num2 <= 0.0) + { + num2 = (double)OptionMath.CalculateDaysToExpire(ExpirationDate) / 365.0; + } + double num3 = (Math.Log(price / num) + (int_Rate + IV * IV / 2.0) * num2) / (IV * Math.Sqrt(num2)) - IV * Math.Sqrt(num2); + if (OptionType != OptionType.Call) + { + num *= -1.0; + num3 *= -1.0; + } + return num * num2 * Math.Exp(-1.0 * int_Rate * num2) * NormDist(num3) / 100.0; + } + } + public class NativePriceModel : PriceModel + { + public override PriceModels Type => PriceModels.Native; + + public override bool IsCalculationAllowed(Symbol symbol, OptionPriceType priceType) + { + return true; + } + + public override double IV(Symbol option, OptionPriceType priceType, double Int_Rate, double shift) + { + return option.IV; + } + + public override double Delta(Symbol option, double IV, double Int_Rate, double shift) + { + return option.Delta; + } + + public override double Gamma(Symbol option, double IV, double int_Rate, double shift) + { + return option.Gamma; + } + + public override double Vega(Symbol option, double IV, double int_Rate, double shift) + { + return option.Vega; + } + + public override double Theta(Symbol option, double IV, double int_Rate, double shift) + { + return option.Theta; + } + + public override double Rho(Symbol option, double IV, double int_Rate, double shift) + { + return option.Rho; + } + + protected override double NormDist(double x) + { + return double.NaN; + } + + public override double IV(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double optionPrice, double underlierPrice, OptionPriceType priceType, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double TheorPrice(Symbol option, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double TheorPrice(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double Delta(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double Vega(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double Gamma(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double Theta(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + + public override double Rho(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift) + { + return double.NaN; + } + } + public class OptionMath + { + public static double GetOptionLastPrice(Symbol optSymbol, OptionPriceType optionPriceType) + { + double result = double.NaN; + if (optionPriceType == OptionPriceType.Ask) + { + result = optSymbol.Ask; + } + else if (optionPriceType == OptionPriceType.BidAsk && (!optSymbol.Ask.IsNanOrDefault() || optSymbol.Bid.IsNanOrDefault())) + { + result = (optSymbol.Ask + optSymbol.Bid) / 2.0; + } + else + { + switch (optionPriceType) + { + case OptionPriceType.Bid: + result = optSymbol.Bid; + break; + case OptionPriceType.Last: + result = optSymbol.Last; + break; + } + } + return result; + } + + public static int CalculateDaysToExpire(DateTime expDate) + { + return (int)(expDate - Core.Instance.TimeUtils.DateTimeUtcNow).TotalDays + 1; + } + } + public enum PriceModels + { + BlackScholes, + Binominal, + Native + } + public enum OptionPriceType + { + Ask, + Bid, + BidAsk, + Last + } + public abstract class PriceModel + { + public abstract PriceModels Type { get; } + + public static PriceModel CreateModel(PriceModels type) + { + return type switch + { + PriceModels.BlackScholes => new BlackScholesPriceModel(), + PriceModels.Native => new NativePriceModel(), + _ => null, + }; + } + + public virtual bool IsCalculationAllowed(Symbol symbol, OptionPriceType priceType) + { + if (symbol?.Underlier == null) + { + return false; + } + return priceType switch + { + OptionPriceType.Bid => !symbol.Bid.IsNanOrDefault(), + OptionPriceType.Ask => !symbol.Ask.IsNanOrDefault(), + OptionPriceType.Last => !symbol.Last.IsNanOrDefault(), + _ => true, + }; + } + + protected abstract double NormDist(double x); + + public abstract double IV(Symbol option, OptionPriceType priceType, double Int_Rate, double shift); + + public abstract double IV(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double optionPrice, double underlierPrice, OptionPriceType priceType, double Int_Rate, double shift); + + public abstract double TheorPrice(Symbol option, double IV, double Int_Rate, double shift); + + public abstract double TheorPrice(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift); + + public abstract double Delta(Symbol option, double IV, double Int_Rate, double shift); + + public abstract double Delta(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift); + + public abstract double Vega(Symbol option, double IV, double int_Rate, double shift); + + public abstract double Vega(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift); + + public abstract double Gamma(Symbol option, double IV, double int_Rate, double shift); + + public abstract double Gamma(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift); + + public abstract double Theta(Symbol option, double IV, double int_Rate, double shift); + + public abstract double Theta(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift); + + public abstract double Rho(Symbol option, double IV, double int_Rate, double shift); + + public abstract double Rho(DateTime ExpirationDate, double StrikePrice, OptionType OptionType, double price, double IV, double Int_Rate, double shift); + } +} +namespace TradingPlatform.BusinessLayer.GlobalVariables +{ + /// + /// Variable lifetime + /// + [Obfuscation(ApplyToMembers = true, Exclude = true)] + public enum VariableLifetime + { + /// + /// The variable will be removed on exit + /// + SaveSession, + /// + /// The variable will be written to file + /// + SaveFile + } + /// + /// Global variable entry + /// + [Obsolete("Should be removed at future releases")] + public sealed class GlobalVariable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private object ??; + + /// + /// Variable name + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// List<GlobalVariable> global_List=new List<GlobalVariable>(); + /// + /// public override void Init() + /// { + /// if(GlobalVariablesManager.Count()>0) + /// { + /// global_List=GlobalVariablesManager.GetGlobalVariablesList(); + /// foreach (var el in global_List) + /// { + /// Print(el.Name); + /// Print(el.Value); + /// } + /// } + /// } + /// } + /// } + /// + /// + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Variable value + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// List<GlobalVariable> global_List=new List<GlobalVariable>(); + /// public override void Init() + /// { + /// if(GlobalVariablesManager.Count()>0) + /// { + /// global_List=GlobalVariablesManager.GetGlobalVariablesList(); + /// foreach (var el in global_List) + /// { + /// Print(el.Name); + /// Print(el.Value); + /// } + /// } + /// } + /// } + /// } + /// + /// + /// + public object Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Initializes new variable + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// List<GlobalVariable> global_List=new List<GlobalVariable>(); + /// public override void Init() + /// { + /// if(GlobalVariablesManager.Count()>0) + /// { + /// global_List=GlobalVariablesManager.GetGlobalVariablesList(); + /// foreach (var el in global_List) + /// { + /// //Simplified way to retrieve global variable value + /// el.GlobalVariable("new_global_variable_period", period) + /// + /// //However, to obtain certain variable, which belongs to indicator/strategy and to avoid unexpected erasing of data the best practice is to provide to a key holder multiple details such as name, params, hashed password etc. Follow SetValue() example. + /// } + /// } + /// } + /// } + /// } + /// + /// + /// + /// Variable name + /// Variable value + public GlobalVariable(string name, object value) + { + Name = name; + Value = value; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 2); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + defaultInterpolatedStringHandler.AppendFormatted(Value.GetType()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [Obsolete("Should be removed at future releases")] + public static class GlobalVariablesManager + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal GlobalVariable ?(? P_0) + { + return P_0.Variable; + } + } + + private const string ?? = "GlobalVariables.dat"; + + private const int ?? = 100000; + + private static readonly ConcurrentDictionary ??; + + private static string PathToGlobalVariablesFile => Path.Combine(Const.EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + static GlobalVariablesManager() + { + ?? = new ConcurrentDictionary(); + ?(); + } + + /// + /// Sets variable value to a global storage + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// GlobalVariablesManager(){ + /// base.ProjectName = "GlobalVariablesManager"; + /// base.Password=GetHashedPassword(ProjectName); + /// } + /// + /// [InputParameter("Period", 0, 1, 9999)] + /// public int period = 5; + /// + /// public override void OnQuote() + /// { + /// //Simplified way to store a global variable + /// + /// GlobalVariablesManager.SetValue("global_variable_period", period, VariableLifetime.SaveSession); + /// + /// //However, to indicate any variable belongs to certain indicator/strategy and to avoid unexpected erasing of data the best practice is to provide to a key holder multiple details such as name, params, hashed password etc. + /// + /// GlobalVariablesManager.SetValue("global_variable_period" +Symbols.Current.Name+period+Password, period, VariableLifetime.SaveSession); + /// } + /// } + /// } + /// + /// + /// + /// Variable name + /// New value + /// Variable lifetime + public static void SetValue(string name, object value, VariableLifetime lifetime = VariableLifetime.SaveSession) + { + if (!?(value)) + { + throw new NonSerializableObjectException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!??.TryGetValue(name, out var _)) + { + GlobalVariable globalVariable = new GlobalVariable(name, value); + ??.TryAdd(name, new ?(globalVariable)); + } + ??[name].Lifetime = lifetime; + ? ? = ?(value, lifetime == VariableLifetime.SaveFile); + ??[name].Variable.Value = ?.??; + ??[name].ObjectBytes = ?.??; + } + + /// + /// Removes specified variable from global storage + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// public override void Init() + /// { + /// //Simplified way to remove a global variable + /// + /// GlobalVariablesManager.Remove("global_variable_period"); + /// + /// //However, to remove certain variable, which belongs to indicator/strategy and to avoid unexpected erasing of data the best practice is to provide to a key holder multiple details such as name, params, hashed password etc. Follow SetValue() example. + /// } + /// } + /// } + /// + /// + /// + /// Variable name + public static bool Remove(string name) + { + ? value; + return ??.TryRemove(name, out value); + } + + /// + /// Returns variables' count in global storage + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// public override void Init() + /// { + /// if(GlobalVariablesManager.Count()>0) + /// { + /// Print("Your session obtains "+GlobalVariablesManager.Count()+" global variables"); + /// } + /// } + /// } + /// } + /// + /// + /// + /// + public static int Count() + { + return ??.Count; + } + + /// + /// Removes all variables from global storage + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// public override void Init() + /// { + /// GlobalVariablesManager.RemoveAll(); + /// + /// if(GlobalVariablesManager.Count()==0) + /// { + /// Print("Your session does not have any global variables"); + /// } + /// } + /// } + /// } + /// + /// + /// + public static void RemoveAll() + { + ??.Clear(); + } + + /// + /// Check if variable with specified name exists in global storage + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// public override void Init() + /// { + /// //Simplified way to check an existance of a global variable + /// + /// if(GlobalVariablesManager.Exists("global_variable_period")) + /// Print("Your session has this global variable"); + /// else + /// GlobalVariablesManager.SetValue("global_variable_period"); + /// + /// //However, to obtain certain variable, which belongs to indicator/strategy and to avoid unexpected erasing of data the best practice is to provide to a key holder multiple details such as name, params, hashed password etc. Follow SetValue() example. + /// } + /// } + /// } + /// + /// + /// + /// Variable name + /// + public static bool Exists(string name) + { + return ??.ContainsKey(name); + } + + /// + /// Returns variable value by name + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// public override void Init() + /// { + /// //Simplified way to retrieve global variable value + /// + /// if(GlobalVariablesManager.Exists("global_variable_period")) + /// //Always perform a type casting before assigning any variable from global storage + /// period = (int)GlobalVariablesManager.GetValue("global_variable_period"); + /// + /// //However, to obtain certain variable, which belongs to indicator/strategy and to avoid unexpected erasing of data the best practice is to provide to a key holder multiple details such as name, params, hashed password etc. Follow SetValue() example. + /// } + /// } + /// } + /// + /// + /// + /// Variable name + /// Variable value + public static object GetValue(string name) + { + if (!??.TryGetValue(name, out var value)) + { + throw new VariableNotExistsException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), name); + } + return value.Variable.Value; + } + + /// + /// Performs a variable assigning from a global storage if such name exists in a scope + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// public override void Init() + /// { + /// int new_period; + /// + /// //Simplified way to retrieve global variable value + /// + /// if(GlobalVariablesManager.TryGetValue("global_variable_period")) + /// Print("New variable is assigned from globals: " + new_period); + /// if(new_period==period) + /// Print("Matching, no need to re-assign globals: "); + /// else + /// GlobalVariablesManager.SetValue("global_variable_period", period, VariableLifetime.SaveSession); + /// + /// //However, to obtain certain variable, which belongs to indicator/strategy and to avoid unexpected erasing of data the best practice is to provide to a key holder multiple details such as name, params, hashed password etc. Follow SetValue() example. + /// } + /// } + /// } + /// + /// + /// + /// Variable name + /// Variable value + /// True if variable exists + public static bool TryGetValue(string name, out object obj) + { + if (??.TryGetValue(name, out var value)) + { + obj = value.Variable.Value; + return true; + } + obj = null; + return false; + } + + /// + /// Saves all serializable variables to disk + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// Connection myConnection = Connection.CurrentConnection; + /// public override void OnQuote() + /// { + /// if(myConnection.Status==Disconnected) + /// GlobalVariablesManager.Flush(); + /// } + /// } + /// } + /// + /// + /// + public static void Flush() + { + try + { + XmlDocument xmlDocument = new XmlDocument(); + XmlElement xmlElement = xmlDocument.CreateElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (KeyValuePair item in ??) + { + ? value = item.Value; + if (value.Lifetime == VariableLifetime.SaveFile) + { + XmlElement xmlElement2 = xmlDocument.CreateElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xmlElement2.SetAttribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value.Variable.Name); + xmlElement2.SetAttribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ?(value.ObjectBytes)); + xmlElement2.SetAttribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (value.Variable.Value == null).ToString()); + xmlElement.AppendChild(xmlElement2); + } + } + xmlDocument.AppendChild(xmlElement); + using XmlTextWriter xmlTextWriter = new XmlTextWriter(PathToGlobalVariablesFile, Encoding.UTF8); + xmlTextWriter.Formatting = Formatting.Indented; + xmlDocument.WriteContentTo(xmlTextWriter); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + /// + /// Returns all global variables as list + /// + /// + /// + /// + /// using System; + /// using System.Text; + /// using PTLRuntime.NETScript; + /// + /// namespace GlobalVariablesManager + /// { + /// public class GlobalVariablesManager : NETIndicator + /// { + /// List <GlobalVariable>global_List=new List<GlobalVariable>(); + /// public override void Init() + /// { + /// if(GlobalVariablesManager.Count()>0) + /// global_List=GlobalVariablesManager.GetGlobalVariablesList(); + /// + /// foreach (var el in global_List) + /// { + /// Print(el.Name); + /// } + /// } + /// } + /// } + /// + /// + /// + /// Collection of global variables + public static List GetGlobalVariablesList() + { + return ??.Values.Select((? P_0) => P_0.Variable).ToList(); + } + + private static void ?() + { + try + { + if (!File.Exists(PathToGlobalVariablesFile)) + { + return; + } + using XmlReader xmlReader = XmlReader.Create(PathToGlobalVariablesFile); + xmlReader.MoveToContent(); + xmlReader.Read(); + while (!xmlReader.EOF && xmlReader.ReadState == ReadState.Interactive) + { + if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name.Equals(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + try + { + if (!(XNode.ReadFrom(xmlReader) is XElement xElement)) + { + continue; + } + string value = xElement.Attribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + string value2 = xElement.Attribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + if (value2 != null && value2.Equals(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + SetValue(value, null, VariableLifetime.SaveFile); + continue; + } + byte[] array = Convert.FromBase64String(xElement.Attribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value); + using MemoryStream memoryStream = new MemoryStream(); + memoryStream.Write(array, 0, array.Length); + memoryStream.Position = 0L; + object value3 = new BinaryFormatter().Deserialize(memoryStream); + SetValue(value, value3, VariableLifetime.SaveFile); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + else + { + xmlReader.Read(); + } + } + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + } + + private static bool ?(object P_0) + { + if (P_0 == null) + { + return true; + } + if (P_0 is ISerializable) + { + return true; + } + return Attribute.IsDefined(P_0.GetType(), typeof(SerializableAttribute)); + } + + private static ? ?(object P_0, bool P_1) + { + ? ? = new ?(); + if (P_0 == null) + { + return ?; + } + using MemoryStream memoryStream = new MemoryStream(); + BinaryFormatter binaryFormatter = new BinaryFormatter(); + binaryFormatter.Serialize(memoryStream, P_0); + long length = memoryStream.Length; + if (P_1 && length > 100000) + { + throw new TooBigObjectException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + memoryStream.Position = 0L; + byte[] array = new byte[memoryStream.Length]; + memoryStream.Read(array, 0, (int)memoryStream.Length); + memoryStream.Position = 0L; + object ?? = binaryFormatter.Deserialize(memoryStream); + ?.?? = array; + ?.?? = ??; + return ?; + } + + private static string ?(byte[] P_0) + { + return Convert.ToBase64String(P_0, Base64FormattingOptions.None); + } + } +} +namespace ? +{ + internal class ? + { + [CompilerGenerated] + private GlobalVariable ??; + + [CompilerGenerated] + private byte[] ??; + + [CompilerGenerated] + private VariableLifetime ??; + + public GlobalVariable Variable + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = globalVariable; + } + } + + public byte[] ObjectBytes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = array; + } + } + + public VariableLifetime Lifetime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = variableLifetime; + } + } + + internal ?(GlobalVariable P_0) + { + Variable = P_0; + } + } +} +namespace TradingPlatform.BusinessLayer.GlobalVariables +{ + /// + /// Object is non-serializable + /// + [Serializable] + public class NonSerializableObjectException : Exception + { + public NonSerializableObjectException() + { + } + + public NonSerializableObjectException(string message) + : base(message) + { + } + + public NonSerializableObjectException(string message, Exception inner) + : base(message, inner) + { + } + + protected NonSerializableObjectException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} +namespace ? +{ + internal class ? + { + internal byte[] ??; + + internal object ??; + + internal ?() + { + ?? = null; + ?? = new byte[0]; + } + } +} +namespace TradingPlatform.BusinessLayer.GlobalVariables +{ + /// + /// Object too big + /// + [Serializable] + public class TooBigObjectException : Exception + { + public TooBigObjectException() + { + } + + public TooBigObjectException(string message) + : base(message) + { + } + + public TooBigObjectException(string message, Exception inner) + : base(message, inner) + { + } + + protected TooBigObjectException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } + [Serializable] + public class VariableNotExistsException : Exception + { + [CompilerGenerated] + private string ??; + + public string VariableName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public VariableNotExistsException() + { + } + + public VariableNotExistsException(string message) + : base(message) + { + } + + public VariableNotExistsException(string message, Exception inner) + : base(message, inner) + { + } + + public VariableNotExistsException(string message, string variableName) + : base(message) + { + VariableName = variableName; + } + + protected VariableNotExistsException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} +namespace TradingPlatform.BusinessLayer.Utils +{ + public class ActionRepeater : IDisposable + { + private class ? : IDisposable + { + private readonly ActionRepeaterCallback ??; + + private readonly CancellationTokenSource ??; + + private int ??; + + private readonly int ??; + + private Task ??; + + public ?(ActionRepeaterCallback P_0, int P_1) + { + ?? = P_0; + ?? = new CancellationTokenSource(); + ?? = 0; + ?? = P_1; + } + + public void ?() + { + try + { + if (??++ >= ?? && ?? == null) + { + ?? = 0; + ?? = Task.Run(delegate + { + ???.Invoke(??.Token); + }, ??.Token).ContinueWith((Task t) => ?? = null); + } + } + catch + { + } + } + + public void Dispose() + { + ??.Cancel(); + } + + [CompilerGenerated] + private void ?() + { + ???.Invoke(??.Token); + } + + [CompilerGenerated] + private Task ?(Task t) + { + return ?? = null; + } + } + + private readonly Timer ??; + + private readonly TimeSpan ??; + + private readonly IDictionary ??; + + private ?[] ??; + + private readonly object ??; + + public ActionRepeater() + { + ?? = new Timer(?); + ?? = TimeSpan.FromSeconds(1.0); + ?? = new Dictionary(); + ?? = Array.Empty(); + ?? = new object(); + } + + public void BeginRepeat(ActionRepeaterCallback callback, TimeSpan period) + { + lock (??) + { + ??.Add(callback, new ?(callback, (int)Math.Max(1L, period.Ticks / ??.Ticks))); + ?? = ??.Values.ToArray(); + if (??.Any()) + { + ??.Change(??, ??); + } + } + } + + public void EndRepeat(ActionRepeaterCallback callback) + { + lock (??) + { + ??.Remove(callback); + ?? = ??.Values.ToArray(); + } + } + + public void Dispose() + { + lock (??) + { + ?[] array = ??; + for (int i = 0; i < array.Length; i++) + { + array[i].Dispose(); + } + } + ??.Change(-1, -1); + ??.Dispose(); + } + + private void ?(object P_0) + { + ?[] array = ??; + for (int i = 0; i < array.Length; i++) + { + array[i].?(); + } + } + } + public delegate void ActionRepeaterCallback(CancellationToken cancellation); + /// + /// The action wrapper. + /// + public class ActionWrapper : IXElementSerialization + { + [CompilerGenerated] + private List ??; + + /// + /// Gets or Sets the items. + /// + public List Items + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + public ActionWrapper() + { + Items = new List(); + } + + /// + /// Froms the X element. + /// + /// The element. + /// The deserialization info. + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + foreach (XElement item2 in element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (Serializer.DeserializeNode(item2, deserializationInfo) is SettingItem item) + { + Items.Add(item); + } + } + } + + /// + /// Tos the X element. + /// + /// A XElement. + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (SettingItem item in Items) + { + xElement.Add(item.ToXElement()); + } + return xElement; + } + } + /// + /// The aggressor flag calculator. + /// + public class AggressorFlagCalculator : IAggressorFlagCalculator, IDisposable + { + private const int ?? = 1000; + + private ConcurrentDictionary ??; + + /// + /// Initializes a new instance of the class. + /// + public AggressorFlagCalculator() + { + ?? = new ConcurrentDictionary(); + } + + /// + /// Collect bid ask. + /// + /// The symbol. + /// The time ticks. + /// The bid. + /// The ask. + public void CollectBidAsk(string symbol, long timeTicks, double bid, double ask) + { + try + { + if (?? != null && (??.TryGetValue(symbol, out var value) || ??.TryAdd(symbol, value = new AggressorFlagCalculatorItem(1000)))) + { + value.CollectBidAsk(timeTicks, bid, ask); + } + } + catch (Exception exception) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + exception.GetMessageRecursive()); + } + } + + /// + /// Calculate aggressor flag. + /// + /// The symbol. + /// The time ticks. + /// The last. + /// An AggressorFlag. + public AggressorFlag CalculateAggressorFlag(string symbol, long timeTicks, double last) + { + try + { + if (?? == null || !??.TryGetValue(symbol, out var value)) + { + return AggressorFlag.NotSet; + } + return value.CalculateAggressorFlag(timeTicks, last); + } + catch (Exception exception) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + exception.GetMessageRecursive()); + } + return AggressorFlag.NotSet; + } + + /// + /// + /// + public void Dispose() + { + ICollection values = ??.Values; + ?? = null; + foreach (AggressorFlagCalculatorItem item in values) + { + item.Dispose(); + } + } + + /// + /// Calculate aggressor flag. + /// + /// The previous bid. + /// The previous ask. + /// The last. + /// An AggressorFlag. + public static AggressorFlag CalculateAggressorFlag(double previousBid, double previousAsk, double last) + { + if (last >= previousAsk) + { + return AggressorFlag.Buy; + } + if (last <= previousBid) + { + return AggressorFlag.Sell; + } + return AggressorFlag.None; + } + } + public class AggressorFlagCalculatorItem : IDisposable + { + private class ? + { + [CompilerGenerated] + private long ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + public long TimeTicks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = num; + } + } + + public double Bid + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = num; + } + } + + public double Ask + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = num; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 3); + defaultInterpolatedStringHandler.AppendFormatted(TimeTicks); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Bid); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Ask); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + + private readonly int ??; + + private ?[] ??; + + private volatile int ??; + + private volatile int ??; + + public AggressorFlagCalculatorItem(int cacheCapacity) + { + ?? = cacheCapacity; + ?? = new ?[cacheCapacity]; + for (int i = 0; i < cacheCapacity; i++) + { + ??[i] = new ?(); + } + ?? = -1; + ?? = -1; + } + + public void CollectBidAsk(long timeTicks, double bid, double ask) + { + int num = Math.Abs(Interlocked.Increment(ref ??) % ??); + ?[] array = ??; + ? ? = ((array != null) ? array[num] : null); + if (? != null) + { + ?.TimeTicks = timeTicks; + ?.Bid = bid; + ?.Ask = ask; + Interlocked.Increment(ref ??); + } + } + + public AggressorFlag CalculateAggressorFlag(long timeTicks, double last) + { + int num = Math.Abs(?? % ??); + int num2 = num; + do + { + ?[] array = ??; + ? ? = ((array != null) ? array[num2] : null); + if (? == null || ?.TimeTicks == 0L) + { + break; + } + if (?.TimeTicks <= timeTicks) + { + return AggressorFlagCalculator.CalculateAggressorFlag(?.Bid, ?.Ask, last); + } + num2--; + if (num2 < 0) + { + num2 = ?? - 1; + } + } + while (num2 != num); + return AggressorFlag.NotSet; + } + + public void Dispose() + { + ?? = null; + } + } + public interface IAggressorFlagCalculator : IDisposable + { + void CollectBidAsk(string symbol, long timeTicks, double bid, double ask); + + AggressorFlag CalculateAggressorFlag(string symbol, long timeTicks, double last); + } + /// + /// The alert. + /// + public class Alert + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private string ??; + + /// + /// Gets or Sets the text. + /// + public string Text + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the symbol name. + /// + public string SymbolName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the connection name. + /// + public string ConnectionName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the action on confirm. + /// + public Action ActionOnConfirm + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the name. + /// + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + /// + /// The alert data. + /// + [DataContract(Name = "Alert", Namespace = "TradingPlatform")] + public class AlertData : IXElementSerialization + { + /// + /// The name. + /// + [DataMember(Name = "Name")] + public string Name; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private Hashtable ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private int ?? = 1; + + [CompilerGenerated] + private int ?? = 1; + + private const string ?? = "ddMMyyyy HH:mm:ss.ffffff"; + + /// + /// Gets or Sets the columns. + /// + public List Columns + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the groups. + /// + public List Groups + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the actions. + /// + public List Actions + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether enabled. + /// + [DataMember(Name = "Enabled")] + public bool Enabled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the table dictionary. + /// + public Hashtable TableDictionary + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether coloring is alert. + /// + [DataMember(Name = "IsColoringAlert")] + public bool IsColoringAlert + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether filter alert. + /// + [DataMember(Name = "FilterAlert")] + public bool FilterAlert + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether search alert. + /// + [DataMember(Name = "SearchAlert")] + public bool SearchAlert + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether to remove. + /// + public bool ToRemove + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the ID. + /// + public string ID + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the command sender. + /// + public object CommandSender + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets a value indicating whether need confirm trading. + /// + public bool NeedConfirmTrading + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Expiration time + /// + public DateTime ExpiryTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool Expire + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool RepeatAlertActions + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int RepeatMaxCount + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int RepeatPeriodMinutes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + public AlertData() + { + Columns = new List(); + Groups = new List(); + Actions = new List(); + NeedConfirmTrading = true; + } + + /// + /// To the XML element. + /// + /// A XElement. + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Enabled)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsColoringAlert)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), FilterAlert)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), NeedConfirmTrading)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Expire)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpiryTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture))); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), RepeatAlertActions)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), RepeatMaxCount)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), RepeatPeriodMinutes)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchAlert)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ID)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (ConditionGroup group in Groups) + { + xElement2.Add(group.ToXElement()); + } + xElement.Add(xElement2); + XElement xElement3 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (ActionWrapper action in Actions) + { + xElement3.Add(action.ToXElement()); + } + xElement.Add(xElement3); + return xElement; + } + + /// + /// From the XML element. + /// + /// The element. + /// The deserialization info. + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Name = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(); + Enabled = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + IsColoringAlert = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + FilterAlert = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + XElement xElement2 = xElement?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + NeedConfirmTrading = xElement2.ToBool(); + } + XElement xElement3 = xElement?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + Expire = xElement3.ToBool(); + } + XElement xElement4 = xElement?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + ExpiryTime = xElement4.ToDateTime(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + XElement xElement5 = xElement?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + RepeatAlertActions = xElement5.ToBool(); + } + XElement xElement6 = xElement?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + RepeatMaxCount = xElement6.ToInt(); + } + XElement xElement7 = xElement?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + RepeatPeriodMinutes = xElement7.ToInt(); + } + SearchAlert = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + ID = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(); + List list = new List(); + foreach (XElement item in xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + ConditionGroup conditionGroup = new ConditionGroup(); + conditionGroup.FromXElement(item, deserializationInfo); + list.Add(conditionGroup); + } + Groups = list; + List list2 = new List(); + foreach (XElement item2 in xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + ActionWrapper actionWrapper = new ActionWrapper(); + actionWrapper.FromXElement(item2, deserializationInfo); + list2.Add(actionWrapper); + } + Actions = list2; + } + } + /// + /// The arbitrage symbol. + /// + [Serializable] + public class ArbitrageSymbol : IXElementSerialization, IComparable + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private readonly Guid ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private Account ??; + + [CompilerGenerated] + private double ??; + + /// + /// Gets or Sets the index. + /// + public int Index + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets the unique ID. + /// + public Guid UniqueID + { + [CompilerGenerated] + get + { + return ??; + } + } + + /// + /// Gets the symbol id. + /// + public string SymbolId + { + get + { + if (Symbol == null) + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return Symbol.ConnectionId + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Symbol.Id; + } + } + + /// + /// Gets or Sets a value indicating whether is selected. + /// + public bool IsSelected + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the symbol. + /// + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the account. + /// + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Gets or Sets the commission. + /// + public double Commission + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + public ArbitrageSymbol() + { + ?? = Guid.NewGuid(); + } + + /// + /// Compare to. + /// + /// The other. + /// An int. + public int CompareTo(ArbitrageSymbol other) + { + return Index.CompareTo(other.Index); + } + + /// + /// Froms the X element. + /// + /// The element. + /// The deserialization info. + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.XPathSelectElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + BusinessObjectInfo businessObjectInfo = new BusinessObjectInfo(); + businessObjectInfo.FromXElement(xElement, deserializationInfo); + Symbol = Core.Instance.GetSymbol(businessObjectInfo); + } + XElement xElement2 = element.XPathSelectElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + BusinessObjectInfo businessObjectInfo2 = new BusinessObjectInfo(); + businessObjectInfo2.FromXElement(xElement2, deserializationInfo); + Account = Core.Instance.GetAccount(businessObjectInfo2); + } + IsSelected = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + Commission = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(); + } + + /// + /// Tos the X element. + /// + /// A XElement. + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsSelected)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Symbol?.CreateInfo().ToXElement())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Account?.CreateInfo().ToXElement())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Commission)); + return xElement; + } + } + /// + /// The action buffered processor. + /// + public class ActionBufferedProcessor : BufferedProcessor + { + protected override void Process(Action subject) + { + try + { + subject(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + /// + /// The action buffered processor with priority. + /// + public class ActionBufferedProcessorWithPriority : BufferedProcessorWithPriority + { + /// + /// Initializes a new instance of the class. + /// + /// The threads count. + public ActionBufferedProcessorWithPriority(int threadsCount = 1) + : base(threadsCount) + { + } + + protected override void Process(Action action) + { + action?.Invoke(); + } + } + /// + /// The buffered processor. + /// + /// + public abstract class BufferedProcessor + { + [CompilerGenerated] + private sealed class ? + { + public T ??; + + public Task ??; + + public BufferedProcessor ??; + + internal void ?() + { + try + { + ??.State = BufferedProcessorState.ProcessSubject; + ??.Process(??); + } + catch (Exception ex) + { + ??.?(ex.InnerException ?? ex); + } + finally + { + ??.State = BufferedProcessorState.Started; + } + } + + internal void ?(Task P_0) + { + ??.??.Remove(??.Id); + ??.??.Set(); + } + } + + [StructLayout(LayoutKind.Auto)] + [CompilerGenerated] + private struct ? + { + public BufferedProcessor ??; + + public CancellationToken? ??; + } + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private BufferedProcessorState ??; + + protected int ProcessTreadsCount; + + private CancellationTokenSource ??; + + private readonly Queue ??; + + private readonly object ??; + + private readonly ManualResetEventSlim ??; + + private readonly HashSet ??; + + /// + /// Gets the state. + /// + public BufferedProcessorState State + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = bufferedProcessorState; + } + } + + /// + /// Gets the queue depth. + /// + public int QueueDepth => ??.Count; + + public event Action ExceptionOccurred + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + protected BufferedProcessor() + { + ProcessTreadsCount = 1; + ?? = new Queue(); + ?? = new object(); + ?? = new ManualResetEventSlim(initialState: false); + ?? = new HashSet(); + State = BufferedProcessorState.Created; + } + + /// + /// + /// + public virtual void Start() + { + ?? = new CancellationTokenSource(); + if (ProcessTreadsCount == 1) + { + Task.Factory.StartNew(?, ??.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + else + { + Task.Factory.StartNew(?, ??.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + State = BufferedProcessorState.Started; + } + + /// + /// + /// + public virtual void Stop() + { + lock (??) + { + ???.Cancel(); + Clear(); + ??.Set(); + State = BufferedProcessorState.Stopped; + } + } + + /// + /// + /// + /// The subject. + public virtual void Push(T subject) + { + lock (??) + { + ??.Enqueue(subject); + ??.Set(); + } + } + + private void ?() + { + CancellationToken token = ??.Token; + while (true) + { + try + { + if (token.IsCancellationRequested) + { + break; + } + ??.Wait(token); + if (token.IsCancellationRequested) + { + break; + } + while (??.Count > 0) + { + if (token.IsCancellationRequested) + { + return; + } + try + { + T val = default(T); + lock (??) + { + State = BufferedProcessorState.ProcessSubject; + val = ??.Dequeue(); + } + Process(val); + } + catch (Exception ex) + { + ?(ex.InnerException ?? ex); + } + finally + { + State = BufferedProcessorState.Started; + } + } + } + catch (Exception ex2) + { + ?(ex2.InnerException ?? ex2); + } + finally + { + lock (??) + { + if (??.Count == 0) + { + ??.Reset(); + } + } + } + } + } + + private void ?() + { + CancellationToken token = ??.Token; + while (true) + { + try + { + if (token.IsCancellationRequested) + { + break; + } + ??.Wait(token); + if (token.IsCancellationRequested) + { + break; + } + while (??.Count > 0 && ??.Count < ProcessTreadsCount) + { + if (token.IsCancellationRequested) + { + return; + } + T ?? = default(T); + lock (??) + { + ?? = ??.Dequeue(); + } + Task ?? = Task.Factory.StartNew(delegate + { + try + { + State = BufferedProcessorState.ProcessSubject; + Process(??); + } + catch (Exception ex2) + { + ?(ex2.InnerException ?? ex2); + } + finally + { + State = BufferedProcessorState.Started; + } + }); + ??.ContinueWith(delegate + { + ??.Remove(??.Id); + ??.Set(); + }); + if (??.Status != TaskStatus.RanToCompletion && ??.Status != TaskStatus.Canceled && ??.Status != TaskStatus.Faulted) + { + ??.Add(??.Id); + } + } + } + catch (Exception ex) + { + ?(ex.InnerException ?? ex); + } + finally + { + ??.Reset(); + } + } + } + + private void ?(Exception P_0) + { + ???.Invoke(P_0); + } + + [Obfuscation(Exclude = false)] + protected abstract void Process(T P_0); + + protected internal virtual void Clear() + { + ???.Clear(); + } + + /// + /// Wait all messages process. + /// + /// The external token. + public void WaitAllMessagesProcess(CancellationToken? externalToken = null) + { + ? ? = default(?); + ?.?? = this; + ?.?? = externalToken; + if (?(ref ?)) + { + return; + } + do + { + lock (??) + { + if (QueueDepth <= 0 && State != BufferedProcessorState.ProcessSubject) + { + break; + } + } + } + while (!?(ref ?)); + } + + [CompilerGenerated] + private bool ?(ref ? P_0) + { + return ???.IsCancellationRequested ?? P_0.???.IsCancellationRequested ?? true; + } + } + /// + /// The buffered processor state. + /// + public enum BufferedProcessorState + { + Created, + Started, + ProcessSubject, + Stopped + } + public abstract class BufferedProcessorWithPriority + { + [CompilerGenerated] + private sealed class ? + { + public QueueObj ??; + + public Task ??; + + public BufferedProcessorWithPriority ??; + + internal void ?() + { + string name = Thread.CurrentThread.Name; + try + { + Thread.CurrentThread.Name = ??.??; + ??.ProcessMessageNow = true; + ??.Process(??.Value); + ??.ProcessMessageNow = false; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.Message, LoggingLevel.Verbose); + } + finally + { + Thread.CurrentThread.Name = name; + } + } + + internal void ?(Task P_0) + { + lock (??.??) + { + ??.??.Remove(??.Marker); + } + ??.??.Remove(??.Id); + ??.??.Set(); + } + } + + private readonly TasksHolder ??; + + private readonly object ??; + + private readonly ManualResetEvent ??; + + private CancellationTokenSource ??; + + protected int ProcessTreadsCount; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + private readonly HashSet ??; + + private readonly HashSet ??; + + private readonly string ??; + + internal bool Started + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + internal bool ProcessMessageNow + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + protected BufferedProcessorWithPriority(int threadsCount = 1) + { + ?? = Guid.NewGuid().ToShortString(); + ProcessTreadsCount = threadsCount; + ?? = new TasksHolder(2); + ?? = new object(); + ?? = new ManualResetEvent(initialState: false); + ?? = new HashSet(); + ?? = new HashSet(); + } + + public void Start() + { + ?? = new CancellationTokenSource(); + Task.Factory.StartNew(?, ??.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + Started = true; + } + + public virtual void Stop() + { + lock (??) + { + ???.Cancel(); + Clear(); + ??.Set(); + Started = false; + } + } + + protected virtual void Clear() + { + ???.?(); + } + + private void ?() + { + while (true) + { + try + { + ??.WaitOne(); + ??.Reset(); + CancellationTokenSource cancellationTokenSource = ??; + if (cancellationTokenSource != null && cancellationTokenSource.IsCancellationRequested) + { + break; + } + while (??.Count > 0 && ??.Count < ProcessTreadsCount) + { + CancellationTokenSource cancellationTokenSource2 = ??; + if (cancellationTokenSource2 != null && cancellationTokenSource2.IsCancellationRequested) + { + return; + } + QueueObj ?? = null; + lock (??) + { + ?? = ??.Dequeue(??); + if (?? == null) + { + break; + } + ??.Add(??.Marker); + goto IL_00ba; + } + IL_00ba: + Task ?? = Task.Factory.StartNew(delegate + { + string name = Thread.CurrentThread.Name; + try + { + Thread.CurrentThread.Name = ??; + ProcessMessageNow = true; + Process(??.Value); + ProcessMessageNow = false; + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex2.Message, LoggingLevel.Verbose); + } + finally + { + Thread.CurrentThread.Name = name; + } + }); + ??.ContinueWith(delegate + { + lock (??) + { + ??.Remove(??.Marker); + } + ??.Remove(??.Id); + ??.Set(); + }); + if (??.Status != TaskStatus.RanToCompletion && ??.Status != TaskStatus.Canceled && ??.Status != TaskStatus.Faulted) + { + ??.Add(??.Id); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.Message, LoggingLevel.Verbose); + } + } + } + + public void Push(T subject, int priority, string marker) + { + if (Thread.CurrentThread.Name == ??) + { + try + { + Process(subject); + return; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.Message, LoggingLevel.Verbose); + return; + } + } + lock (??) + { + ??.Enqueue(subject, priority, marker); + } + ??.Set(); + } + + [Obfuscation(Exclude = false)] + protected abstract void Process(T P_0); + } +} +namespace ? +{ + internal class ? where ? : IBufferedProcessorValue + { + private readonly Dictionary>> ??; + + private readonly object ??; + + public ?() + { + ?? = new Dictionary>>(); + ?? = new object(); + } + + public void ?(Action P_0, params ?[] messagesTypes) + { + if (P_0 == null) + { + return; + } + lock (??) + { + foreach (? key in messagesTypes) + { + if (??.TryGetValue(key, out var value)) + { + List> value2 = new List>(value) { P_0 }; + ??[key] = value2; + } + else + { + ??.Add(key, new List> { P_0 }); + } + } + } + } + + public void ?(Action P_0, params ?[] messagesTypes) + { + if (P_0 == null) + { + return; + } + lock (??) + { + if (messagesTypes.Length == 0) + { + foreach (KeyValuePair>> item in ??) + { + item.Value.Remove(P_0); + } + return; + } + foreach (? key in messagesTypes) + { + if (??.TryGetValue(key, out var value)) + { + List> list = new List>(value); + list.Remove(P_0); + ??[key] = list; + } + } + } + } + + public void ?(? P_0) + { + List> value; + lock (??) + { + ??.TryGetValue(P_0.Key, out value); + } + if (value == null) + { + return; + } + foreach (Action item in value) + { + try + { + item(P_0); + } + catch + { + } + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils +{ + public interface IBufferedProcessorValue + { + TKey Key { get; } + } + public class QueueObj + { + public readonly T Value; + + public readonly string Marker; + + public QueueObj(T value, string marker) + { + Value = value; + Marker = marker; + } + } + public class TasksHolder + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func>, int> ??; + + internal int ?(List> P_0) + { + return P_0.Count; + } + } + + private readonly List>[] ??; + + public int Count => ??.Sum((List> P_0) => P_0.Count); + + /// + /// + /// + public TasksHolder(int prioritiesCount) + { + ?? = new List>[prioritiesCount]; + for (int i = 0; i < ??.Length; i++) + { + ??[i] = new List>(); + } + } + + public void Enqueue(TTask task, int priority, string marker) + { + if (priority >= ??.Length) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + QueueObj item = new QueueObj(task, marker); + lock (??) + { + ??[priority].Add(item); + } + } + + public QueueObj Dequeue(HashSet markersAtWork) + { + QueueObj queueObj = null; + lock (??) + { + List>[] array = ??; + foreach (List> list in array) + { + foreach (QueueObj item in list) + { + if (!markersAtWork.Contains(item.Marker)) + { + queueObj = item; + list.Remove(item); + break; + } + } + if (queueObj != null) + { + break; + } + } + } + return queueObj; + } + + internal void ?() + { + for (int i = 0; i < ??.Length; i++) + { + ??[i].Clear(); + } + } + } + public class TimeFrameConfig : IXElementSerialization, ICloneable + { + public List TFList; + + [CompilerGenerated] + private HistoryAggregation ??; + + /// + /// ?????????, ?? ???? ????????????????? ?? ???????? ??? "TimeFrameScreen". + /// ??????? ??????????? ????????? ?????. + /// + public HistoryAggregation DefaultAggregation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeFrameConfig() + { + TFList = new List(); + } + + public void AddTF(HistoryAggregation info) + { + TFList.Add(info.ToString()); + } + + public bool IsAllowed(HistoryAggregation otherTf) + { + if (TFList.Count == 0 || otherTf == null) + { + return true; + } + string item = otherTf.ToString(); + return TFList.Contains(item); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (string tF in TFList) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), tF)); + } + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + TFList = new List(); + foreach (XElement item in element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements()) + { + string text = item.Value.ToString(); + if (text.StartsWith(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && text.EndsWith(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) && text != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + text = text.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + TFList.Add(text); + } + } + + public object Clone() + { + return new TimeFrameConfig + { + TFList = new List(TFList), + DefaultAggregation = ((DefaultAggregation == null) ? null : ((HistoryAggregation)DefaultAggregation.Clone())) + }; + } + } + public class ClusterCustomColoringLevel : IXElementSerialization, IEquatable + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public bool IsChecked + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color LeftColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color RightColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string LeftColorLabel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string RightColorLabel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsChecked)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Value)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LeftColor.ToArgb())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), RightColor.ToArgb())); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Value = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(); + IsChecked = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + LeftColor = Color.FromArgb(xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt()); + RightColor = Color.FromArgb(xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt()); + } + } + + public void UpdateLevel(ClusterCustomColoringLevel level) + { + IsChecked = level.IsChecked; + Value = level.Value; + LeftColor = level.LeftColor; + RightColor = level.RightColor; + if (!string.IsNullOrEmpty(level.LeftColorLabel)) + { + LeftColorLabel = level.LeftColorLabel; + } + if (!string.IsNullOrEmpty(level.RightColorLabel)) + { + RightColorLabel = level.RightColorLabel; + } + } + + public bool Equals(ClusterCustomColoringLevel other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (IsChecked == other.IsChecked && Value.Equals(other.Value) && LeftColor.Equals(other.LeftColor) && RightColor.Equals(other.RightColor) && LeftColorLabel == other.LeftColorLabel) + { + return RightColorLabel == other.RightColorLabel; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((ClusterCustomColoringLevel)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(IsChecked, Value, LeftColor, RightColor, LeftColorLabel, RightColorLabel); + } + } + public sealed class ColorStyleWidth : IXElementSerialization, ICloneable + { + public Color Color; + + public LineStyle Style; + + public int Width; + + public bool DisableColor; + + public bool DisableStyle; + + public bool DisableWidth; + + public bool CheckBoxVisible; + + public bool Checked; + + public bool AllLineStyles; + + public ColorStyleWidth() + { + Width = 1; + Checked = true; + } + + public ColorStyleWidth(Color color, LineStyle Style, int Width) + : this() + { + Color = color; + this.Style = Style; + this.Width = Width; + } + + public void ApplyFromClone(ColorStyleWidth clone) + { + Color = Color.FromArgb(clone.Color.ToArgb()); + Style = clone.Style; + Width = clone.Width; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Color.ToArgb())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Style)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Width)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Color = Color.FromArgb(xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt()); + Style = (LineStyle)xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + Width = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + } + + public object Clone() + { + return new ColorStyleWidth + { + AllLineStyles = AllLineStyles, + CheckBoxVisible = CheckBoxVisible, + Checked = Checked, + Color = Color, + DisableColor = DisableColor, + DisableStyle = DisableStyle, + DisableWidth = DisableWidth, + Style = Style, + Width = Width + }; + } + } + public class ColumnBaseInformation : IComparable, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private TableBaseType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public TableBaseType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = tableBaseType; + } + } + + public string HeaderText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public bool IsIndicatorColumn + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = flag; + } + } + + public ColumnBaseInformation() + { + } + + public ColumnBaseInformation(string name, TableBaseType type, string headerText, bool isIndicatorColumn) + { + Name = name; + Type = type; + HeaderText = headerText; + IsIndicatorColumn = isIndicatorColumn; + } + + public int CompareTo(object obj) + { + return Name.CompareTo(obj); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Type.ToString())); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Name = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(); + Type = (TableBaseType)Enum.Parse(typeof(TableBaseType), xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString()); + } + } + public class ConditionGroup : IXElementSerialization + { + [CompilerGenerated] + private List ?? = new List(); + + public List ConditionItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + foreach (XElement item in element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + ConditionItem conditionItem = new ConditionItem(); + conditionItem.FromXElement(item, deserializationInfo); + list.Add(conditionItem); + } + ConditionItems = list; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (ConditionItem conditionItem in ConditionItems) + { + xElement.Add(conditionItem.ToXElement()); + } + return xElement; + } + } + public class ConditionItem : IXElementSerialization + { + [CompilerGenerated] + private ColumnBaseInformation ??; + + [CompilerGenerated] + private TableConditionType ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private ColumnBaseInformation ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + public ColumnBaseInformation Column + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TableConditionType ConditionType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object ConditionValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ColumnBaseInformation Column2 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Column1Offset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Column2Offset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ColumnBaseInformation columnBaseInformation = new ColumnBaseInformation(); + columnBaseInformation.FromXElement(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), deserializationInfo); + Column = columnBaseInformation; + ConditionType = (TableConditionType)Enum.Parse(typeof(TableConditionType), element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString()); + ConditionValue = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(); + if (element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) != null) + { + Column1Offset = int.Parse(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString()); + } + if (element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) != null) + { + Column2Offset = int.Parse(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString()); + } + if (element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) != null) + { + ColumnBaseInformation columnBaseInformation2 = new ColumnBaseInformation(); + columnBaseInformation2.FromXElement(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), deserializationInfo); + Column2 = columnBaseInformation2; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Column.ToXElement())); + if (Column2 != null) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Column2.ToXElement())); + } + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ConditionType.ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ConditionValue?.ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Column1Offset.ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Column2Offset.ToString())); + return xElement; + } + } + public static class Const + { + public const double DOUBLE_UNDEFINED = double.NaN; + + public const string SETTINGS_FOLDER_NAME = "Settings"; + + public const string SCRIPTS_FOLDER_NAME = "Scripts"; + + public const string INDICATORS_FOLDER_NAME = "Indicators"; + + public const string STRATEGIES_FOLDER_NAME = "Strategies"; + + public const string PLACE_ORDER_STRATEGIES_FOLDER_NAME = "PlaceOrderStrategies"; + + public const string SCRIPTS_DATA_FOLDER_NAME = "ScriptsData"; + + public const string MEDIA_FOLDER_NAME = "Media"; + + public const string MESSENGERS_FOLDER_NAME = "Messengers"; + + private const string ?? = "History"; + + internal const string ?? = "history.db"; + + private const string ?? = "VolumeAnalysis"; + + internal const string ?? = "volume-analysis.db"; + + private const string ?? = "UserTradesCache"; + + public const string USER_TRADES_STORAGE_FILE_NAME = "user-trades.db"; + + public const string ORDERS_HISTORY_STORAGE_FILE_NAME = "orders-history.db"; + + public static readonly string EXECUTING_FOLDER; + + public static readonly string PLUGINS_FOLDER; + + public static readonly string HISTORY_PATH; + + public static readonly string VOLUME_ANALYSIS_PATH; + + public static readonly string USER_TRADES_CACHE_PATH; + + public static readonly string LOGS_FOLDER_PATH; + + public static readonly string CUSTOM_SCRIPTS_PATH; + + public static readonly string SCRIPTS_DATA_PATH; + + public static readonly string DEFAULT_INDICATORS_RELATIVE_PATH; + + public static readonly string CUSTOM_INDICATORS_PATH; + + public static readonly string DEFAULT_STRATEGIES_RELATIVE_PATH; + + public static readonly string CUSTOM_STRATEGIES_PATH; + + public static readonly string DEFAULT_PLACE_ORDER_STRATEGIES_RELATIVE_PATH; + + public static readonly string CUSTOM_PLACE_ORDER_STRATEGIES_PATH; + + public static readonly string CUSTOM_PLUGINS_PATH; + + public static readonly string CUSTOM_VENDORS_PATH; + + public static readonly string CUSTOM_BIN_PATH; + + public static readonly string TEMP_PATH; + + public static readonly string MEDIA_PATH; + + public static readonly string MESSENGERS_PATH; + + public const string PLUGINS_FOLDER_NAME = "plug-ins"; + + public const string VENDORS_FOLDER_NAME = "Vendors"; + + public const string BIN_FOLDER_NAME = "bin"; + + public const string NOT_AVAILABLE_STRING = "N/A"; + + public const string CONSOLE_SCREEN_STRING = "*console#"; + + public const string TEMP_STRING = "Temp"; + + public const string LOGS_FOLDER_NAME = "Logs"; + + static Const() + { + EXECUTING_FOLDER = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + PLUGINS_FOLDER = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + HISTORY_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + VOLUME_ANALYSIS_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + USER_TRADES_CACHE_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + LOGS_FOLDER_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_SCRIPTS_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + SCRIPTS_DATA_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DEFAULT_INDICATORS_RELATIVE_PATH = Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_INDICATORS_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DEFAULT_STRATEGIES_RELATIVE_PATH = Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_STRATEGIES_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DEFAULT_STRATEGIES_RELATIVE_PATH = Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_STRATEGIES_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DEFAULT_PLACE_ORDER_STRATEGIES_RELATIVE_PATH = Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_PLACE_ORDER_STRATEGIES_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_PLUGINS_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_VENDORS_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + CUSTOM_BIN_PATH = Path.Combine(CUSTOM_SCRIPTS_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + TEMP_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + MEDIA_PATH = Path.Combine(EXECUTING_FOLDER, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + MESSENGERS_PATH = Path.Combine(MEDIA_PATH, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + public static class CoreMath + { + public static int GetValuePrecision(decimal value) + { + value = Math.Abs(value); + decimal num = value - (decimal)(long)value; + int num2 = 0; + if (num != 0m) + { + num2 = 1; + while (true) + { + decimal num3 = num * (decimal)Math.Pow(10.0, num2); + if (!(num3 - (decimal)(long)num3 > 0m)) + { + break; + } + num2++; + } + } + return num2; + } + + public static double RoundToIncrement(double value, double increment) + { + if (increment <= 0.0 || double.IsNaN(value)) + { + return value; + } + return (double)((decimal)(long)Math.Round((decimal)value / (decimal)increment, MidpointRounding.AwayFromZero) * (decimal)increment); + } + + public static double FloorToIncrement(double value, double increment) + { + if (increment <= 0.0 || double.IsNaN(value)) + { + return value; + } + return (double)((decimal)(long)Math.Floor((decimal)value / (decimal)increment) * (decimal)increment); + } + + public static double ProcessNaN(double value, double defaultValue = 0.0) + { + if (!double.IsNaN(value)) + { + return value; + } + return defaultValue; + } + + public static double GetWeightedAverage(IEnumerable<(double, double)> array, Symbol symbol = null) + { + double num = 0.0; + double num2 = 0.0; + foreach (var item3 in array) + { + double item = item3.Item1; + double item2 = item3.Item2; + num += item * item2; + num2 += item2; + } + if (num2 == 0.0) + { + return double.NaN; + } + double num3 = num / num2; + return symbol?.RoundPriceToTickSize(num3) ?? num3; + } + } + public class CrossRateCache : IDisposable + { + private readonly struct ? : IEquatable + { + private readonly string ??; + + private readonly string ??; + + public ?(string P_0, string P_1) + { + ?? = P_0; + ?? = P_1; + } + + public bool Equals(? other) + { + if (?? == other.??) + { + return ?? == other.??; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj is ? other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (((?? != null) ? ??.GetHashCode() : 0) * 397) ^ ((?? != null) ? ??.GetHashCode() : 0); + } + + public override string ToString() + { + return ?? + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ??; + } + } + + private readonly Dictionary ??; + + public CrossRateCache() + { + ?? = new Dictionary(); + } + + public void ProcessPrice(string baseAsset, string quoteAsset, double price) + { + if (!double.IsNaN(price)) + { + ? key = new ?(baseAsset, quoteAsset); + ??[key] = price; + if (price != 0.0) + { + key = new ?(quoteAsset, baseAsset); + ??[key] = 1.0 / price; + } + } + } + + public bool TryGetCrossRate(string fromAsset, string toAsset, out double crossRate) + { + if (fromAsset == toAsset) + { + crossRate = 1.0; + return true; + } + ? key = new ?(fromAsset, toAsset); + if (??.TryGetValue(key, out crossRate)) + { + return !double.IsNaN(crossRate); + } + return false; + } + + public void Dispose() + { + ??.Clear(); + } + } + public sealed class DateTimeRange : IXElementSerialization, IComparable + { + private const string ?? = "RangeSelector"; + + [CompilerGenerated] + private Period ??; + + [CompilerGenerated] + private Period? ??; + + [CompilerGenerated] + private DateTimeRangeType ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private Connection ??; + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = period; + } + } + + public Period? EndOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = period; + } + } + + public DateTimeRangeType RangeType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTimeRangeType; + } + } + + public DateTime From + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public DateTime To + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public Connection TimeSourceConnection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTimeRange() + { + } + + public DateTimeRange(Period period) + : this() + { + SetRange(period); + } + + public DateTimeRange(Period period, DateTimeRangeType dateTimeRangeType) + : this() + { + SetRange(period, dateTimeRangeType); + } + + public DateTimeRange(Period period, Period endOffset, DateTimeRangeType dateTimeRangeType) + : this() + { + ?(period, endOffset, dateTimeRangeType); + } + + public DateTimeRange(DateTime from, DateTime to) + : this() + { + SetRange(from, to); + } + + public DateTimeRange(DateTimeRange original) + : this() + { + RangeType = original.RangeType; + Period = original.Period; + EndOffset = original.EndOffset; + From = original.From; + To = original.To; + Update(); + } + + public void SetRange(Period period) + { + if (RangeType == DateTimeRangeType.Custom) + { + throw new ArgumentException(); + } + Period = period; + Update(); + } + + public void SetRange(Period period, DateTimeRangeType rangeType) + { + if (rangeType == DateTimeRangeType.Custom) + { + throw new ArgumentException(); + } + RangeType = rangeType; + Period = period; + Update(); + } + + private void ?(Period P_0, Period P_1, DateTimeRangeType P_2) + { + if (P_2 == DateTimeRangeType.Custom) + { + throw new ArgumentException(); + } + RangeType = P_2; + Period = P_0; + EndOffset = P_1; + Update(); + } + + public void SetRange(DateTime from, DateTime to) + { + if (!?(from, to)) + { + throw new ArgumentOutOfRangeException(); + } + From = from; + To = to; + RangeType = DateTimeRangeType.Custom; + } + + public void Update() + { + if (RangeType != DateTimeRangeType.Custom) + { + (DateTime from, DateTime to) tuple = ?(Period, EndOffset, RangeType, TimeSourceConnection); + DateTime item = tuple.from; + DateTime item2 = tuple.to; + From = item; + To = item2; + } + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + XElement xElement2 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + RangeType = (DateTimeRangeType)xElement2.ToInt(); + } + XElement xElement3 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + if (xElement3 != null) + { + Period period = default(Period); + period.FromXElement(xElement3, deserializationInfo); + Period = period; + } + XElement xElement4 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + XElement xElement5 = xElement4.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + if (xElement5 != null) + { + Period value = default(Period); + value.FromXElement(xElement5, deserializationInfo); + EndOffset = value; + } + } + if (RangeType != DateTimeRangeType.Custom) + { + Update(); + return; + } + XElement xElement6 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + From = xElement6.ToDateTime(toUTC: true); + } + XElement xElement7 = xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + To = xElement7.ToDateTime(toUTC: true); + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)RangeType)); + xElement.Add(Period.ToXElement()); + if (EndOffset.HasValue) + { + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement2.Add(EndOffset.Value.ToXElement()); + xElement.Add(xElement2); + } + if (RangeType == DateTimeRangeType.Custom) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), From)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), To)); + } + return xElement; + } + + private static (DateTime from, DateTime to) ?(Period P_0, Period? P_1, DateTimeRangeType P_2, Connection P_3) + { + return ?(P_0, P_1, P_2, DayOfWeek.Monday, P_3); + } + + private static (DateTime from, DateTime to) ?(Period P_0, Period? P_1, DateTimeRangeType P_2, DayOfWeek P_3, Connection P_4) + { + DateTime dateTime = Core.Instance.TimeUtils.DateTimeUtcNow; + if (P_4 != null) + { + dateTime = P_4.ServerTime; + } + DateTime item = dateTime; + DateTime item2 = dateTime; + switch (P_2) + { + case DateTimeRangeType.FixedStart: + switch (P_0.BasePeriod) + { + case BasePeriod.Tick: + item = item.AddTicks(P_0.PeriodMultiplier); + break; + case BasePeriod.Second: + { + double num = dateTime.TimeOfDay.TotalSeconds % (double)P_0.PeriodMultiplier; + item = dateTime.AddSeconds(0.0 - num); + item2 = item.AddTicks(P_0.Ticks); + break; + } + case BasePeriod.Minute: + { + dateTime = dateTime.TrimSeconds(); + double num3 = dateTime.TimeOfDay.TotalMinutes % (double)P_0.PeriodMultiplier; + item = dateTime.AddMinutes(0.0 - num3); + item2 = item.AddTicks(P_0.Ticks); + break; + } + case BasePeriod.Hour: + { + dateTime = dateTime.TrimSeconds(); + double num2 = dateTime.TimeOfDay.TotalHours % (double)P_0.PeriodMultiplier; + item = dateTime.AddHours(0.0 - num2); + item2 = item.AddTicks(P_0.Ticks); + break; + } + case BasePeriod.Day: + item = dateTime.TrimSeconds().Date.AddDays(-(P_0.PeriodMultiplier - 1)); + item2 = item.AddDays(P_0.PeriodMultiplier); + break; + case BasePeriod.Week: + { + DateTime dateTime2 = dateTime.TrimSeconds(); + while (dateTime2.DayOfWeek != P_3) + { + dateTime2 = dateTime2.AddDays(-1.0); + } + item = dateTime2.Date; + item2 = item.AddDays(7 * P_0.PeriodMultiplier); + break; + } + case BasePeriod.Month: + item = new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddMonths(-(P_0.PeriodMultiplier - 1)); + item2 = item.AddMonths(P_0.PeriodMultiplier); + break; + case BasePeriod.Year: + item = new DateTime(dateTime.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddYears(-(P_0.PeriodMultiplier - 1)); + item2 = item.AddYears(P_0.PeriodMultiplier); + break; + } + break; + case DateTimeRangeType.Slide: + item = dateTime.AddTicks(-P_0.Ticks); + break; + } + if (P_1.HasValue) + { + item = item.AddTicks(-P_1.Value.Ticks); + item2 = item2.AddTicks(-P_1.Value.Ticks); + } + return (from: item, to: item2); + } + + private bool ?(DateTime P_0, DateTime P_1) + { + return P_1.Ticks >= P_0.Ticks; + } + + public string ToShortDateString() + { + return Core.Instance.TimeUtils.GetFormatedDate(From.ToSelectedTimeZone()) + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Core.Instance.TimeUtils.GetFormatedDate(To.ToSelectedTimeZone()); + } + + [NotPublished] + public static bool operator ==(DateTimeRange dateTimeRange1, DateTimeRange dateTimeRange2) + { + return dateTimeRange1.Equals(dateTimeRange2); + } + + [NotPublished] + public static bool operator !=(DateTimeRange dateTimeRange1, DateTimeRange dateTimeRange2) + { + return !dateTimeRange1.Equals(dateTimeRange2); + } + + public int CompareTo(object obj) + { + if (!(obj is DateTimeRange dateTimeRange)) + { + return 0; + } + int num = RangeType.CompareTo(dateTimeRange.RangeType); + if (num != 0) + { + return num; + } + if (RangeType == DateTimeRangeType.Custom) + { + num = From.CompareTo(dateTimeRange.From); + if (num != 0) + { + return num; + } + num = To.CompareTo(dateTimeRange.To); + if (num != 0) + { + return num; + } + } + else + { + num = Period.CompareTo(dateTimeRange.Period); + if (num != 0) + { + return num; + } + } + return 0; + } + + public override bool Equals(object obj) + { + if (!(obj is DateTimeRange dateTimeRange)) + { + return false; + } + bool flag = RangeType == dateTimeRange.RangeType; + if (!flag) + { + return flag; + } + if (RangeType == DateTimeRangeType.Custom) + { + flag = From == dateTimeRange.From; + if (!flag) + { + return flag; + } + flag = To == dateTimeRange.To; + if (!flag) + { + return flag; + } + } + else + { + flag = Period == dateTimeRange.Period; + if (!flag) + { + return flag; + } + flag = EndOffset == dateTimeRange.EndOffset; + if (!flag) + { + return flag; + } + } + return true; + } + + public override int GetHashCode() + { + int hashCode = RangeType.GetHashCode(); + if (RangeType == DateTimeRangeType.Custom) + { + return hashCode ^ (From.GetHashCode() ^ To.GetHashCode()); + } + if (EndOffset.HasValue) + { + return hashCode ^ (Period.GetHashCode() ^ (EndOffset.GetHashCode() * 397)); + } + return hashCode ^ Period.GetHashCode(); + } + } + public enum DateTimeRangeType + { + Slide, + FixedStart, + Custom + } + public class DealTicketLimiter + { + private readonly TimeSpan ??; + + private readonly object ??; + + private bool ??; + + public DealTicketLimiter(TimeSpan delay) + { + ?? = delay; + ?? = new object(); + ?? = true; + } + + public bool AllowDealTicket(TimeSpan? currentDelay = null) + { + lock (??) + { + if (!??) + { + return false; + } + ?? = false; + Task.Delay(currentDelay ?? ??).ContinueWith((Task P_0) => ?? = true); + return true; + } + } + + [CompilerGenerated] + private bool ?(Task P_0) + { + return ?? = true; + } + } + public class EntityLifecycleEventArgs : EventArgs + { + [CompilerGenerated] + private readonly EntityLifecycle ??; + + public EntityLifecycle Lifecycle + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } + public class FibonacciLevelOptions : ICloneable, IXElementSerialization + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private Font ??; + + [CompilerGenerated] + private ColorStyleWidth ??; + + [CompilerGenerated] + private int[] ??; + + public double Level + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool IsEnabled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool UseCustom + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color CaptionFontColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Font CaptionFont + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ColorStyleWidth Line + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int[] screenPoints + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public FibonacciLevelOptions() + { + UseCustom = false; + screenPoints = new int[4]; + } + + public FibonacciLevelOptions(double level) + : this() + { + Level = level; + } + + public virtual FibonacciLevelOptions Clone() + { + return new FibonacciLevelOptions + { + UseCustom = UseCustom, + IsEnabled = IsEnabled, + Line = (Line.Clone() as ColorStyleWidth), + CaptionFontColor = CaptionFontColor, + CaptionFont = CaptionFont, + Level = Level + }; + } + + private object ?() + { + return Clone(); + } + + object ICloneable.Clone() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + public virtual XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Level)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), UseCustom)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsEnabled)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CaptionFontColor.ToArgb())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CaptionFont.FontFamily.Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CaptionFont.Size)); + xElement.Add(Line.ToXElement()); + int[] array = screenPoints; + foreach (int num in array) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), num)); + } + return xElement; + } + + public virtual void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Level = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(); + UseCustom = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + IsEnabled = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + CaptionFontColor = Color.FromArgb(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt()); + CaptionFont = new Font(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(), (float)element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(), GraphicsUnit.Pixel); + Line = new ColorStyleWidth(); + Line.FromXElement(element, deserializationInfo); + List list = new List(); + foreach (XElement item in element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + list.Add(item.ToInt()); + } + screenPoints = list.ToArray(); + } + } + public class FormatSettings + { + [CompilerGenerated] + private bool ??; + + public bool DisplayQuantityInLots + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public static class GlobalSettings + { + [CompilerGenerated] + private static bool ??; + + public static bool AbbreviateCryptoPrices + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public abstract class HistoryItemBarCreator + { + protected Period targetPeriod; + + [CompilerGenerated] + private Period ??; + + public Period HistoryPeriod + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + protected HistoryItemBarCreator(Period targetPeriod) + { + this.targetPeriod = targetPeriod; + } + + protected virtual DateTime FindNearestDateTimeFromUnixStartTime(DateTime targetDateTime, long sessionOffset) + { + long num = 621355968000000000L; + long num2 = (targetDateTime.Ticks - (num + sessionOffset)) / targetPeriod.Ticks; + return new DateTime(num + sessionOffset + num2 * targetPeriod.Ticks, targetDateTime.Kind); + } + + public static HistoryItemBarCreator CreateHistoryAggregator(Period targetPeriod) + { + return targetPeriod.BasePeriod switch + { + BasePeriod.Second => new ?(targetPeriod), + BasePeriod.Minute => new ?(targetPeriod), + BasePeriod.Hour => new ?(targetPeriod), + BasePeriod.Day => new ?(targetPeriod), + BasePeriod.Week => new ?(targetPeriod), + BasePeriod.Month => new ?(targetPeriod), + BasePeriod.Year => new ?(targetPeriod), + _ => null, + }; + } + + public abstract void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder); + } +} +namespace ? +{ + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime2 = dateTime; + if (base.HistoryPeriod.BasePeriod == BasePeriod.Day) + { + if (targetPeriod.PeriodMultiplier > 1) + { + long num = dateTime.TimeOfDay.Ticks - 864000000000L; + dateTime2 = dateTime.AddTicks(-num); + dateTime2 = FindNearestDateTimeFromUnixStartTime(dateTime2, sessionOffset).AddTicks(num); + } + } + else if (targetPeriod.PeriodMultiplier > 1) + { + dateTime2 = FindNearestDateTimeFromUnixStartTime(dateTime, sessionOffset); + } + DateTime dateTime3 = dateTime2.AddDays(targetPeriod.PeriodMultiplier); + leftBorder = dateTime2.Ticks; + rightBorder = dateTime3.Ticks - 1; + } + } + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime2 = ((targetPeriod.PeriodMultiplier == 1 && sessionOffset == 0L) ? new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, 0, 0, dateTime.Kind) : FindNearestDateTimeFromUnixStartTime(dateTime, sessionOffset)); + DateTime dateTime3 = dateTime2.AddHours(targetPeriod.PeriodMultiplier); + leftBorder = dateTime2.Ticks; + rightBorder = dateTime3.Ticks - 1; + } + } + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime2 = ((targetPeriod.PeriodMultiplier == 1 && sessionOffset == 0L) ? new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0, dateTime.Kind) : FindNearestDateTimeFromUnixStartTime(dateTime, sessionOffset)); + DateTime dateTime3 = dateTime2.AddMinutes(targetPeriod.PeriodMultiplier); + leftBorder = dateTime2.Ticks; + rightBorder = dateTime3.Ticks - 1; + } + } + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime3; + if (base.HistoryPeriod.BasePeriod != BasePeriod.Month) + { + DateTime dateTime2 = dateTime.AddHours(12.0); + while (dateTime2.Day > 1) + { + dateTime2 = dateTime2.AddDays(-1.0); + } + dateTime3 = dateTime2.AddHours(-12.0); + } + else + { + long num = (dateTime.Day - 1) * 864000000000L + dateTime.TimeOfDay.Ticks; + DateTime targetDateTime = dateTime.AddTicks(-num); + dateTime3 = FindNearestDateTimeFromUnixStartTime(targetDateTime, sessionOffset).AddTicks(num); + } + DateTime dateTime4 = dateTime3; + dateTime4 = dateTime4.AddMonths(targetPeriod.PeriodMultiplier); + leftBorder = dateTime3.Ticks; + rightBorder = dateTime4.Ticks - 1; + } + + protected override DateTime FindNearestDateTimeFromUnixStartTime(DateTime targetDateTime, long sessionOffset) + { + DateTime dateTime = new DateTime(621355968000000000L, DateTimeKind.Utc); + while (dateTime <= targetDateTime) + { + dateTime = dateTime.AddMonths(targetPeriod.PeriodMultiplier); + } + return dateTime.AddMonths(-targetPeriod.PeriodMultiplier); + } + } + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime2 = ((targetPeriod.PeriodMultiplier == 1) ? new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Kind) : FindNearestDateTimeFromUnixStartTime(dateTime, sessionOffset)); + DateTime dateTime3 = dateTime2.AddSeconds(targetPeriod.PeriodMultiplier); + leftBorder = dateTime2.Ticks; + rightBorder = dateTime3.Ticks - 1; + } + } + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime3; + if (base.HistoryPeriod.BasePeriod != BasePeriod.Week) + { + DateTime dateTime2 = dateTime.AddHours(12.0); + while (dateTime2.DayOfWeek != DayOfWeek.Monday) + { + dateTime2 = dateTime2.AddDays(-1.0); + } + dateTime3 = dateTime2.AddHours(-12.0); + } + else + { + dateTime3 = FindNearestDateTimeFromUnixStartTime(dateTime, sessionOffset).AddTicks(dateTime.TimeOfDay.Ticks); + } + DateTime dateTime4 = dateTime3.AddDays(targetPeriod.PeriodMultiplier * 7); + leftBorder = dateTime3.Ticks; + rightBorder = dateTime4.Ticks - 1; + } + + protected override DateTime FindNearestDateTimeFromUnixStartTime(DateTime targetDateTime, long sessionOffset) + { + DateTime dateTime = new DateTime(621355968000000000L, DateTimeKind.Utc); + dateTime = dateTime.AddDays(-((int)(dateTime.DayOfWeek + 6) % 7)); + long num = (targetDateTime.Ticks - (dateTime.Ticks + sessionOffset)) / targetPeriod.Ticks; + return new DateTime(dateTime.Ticks + sessionOffset + num * targetPeriod.Ticks, targetDateTime.Kind); + } + } + internal sealed class ? : HistoryItemBarCreator + { + public ?(Period P_0) + : base(P_0) + { + } + + public override void FindBarBorders(DateTime dateTime, long sessionOffset, out long leftBorder, out long rightBorder) + { + DateTime dateTime2 = dateTime.AddHours(12.0); + while (dateTime2.Month > 1) + { + dateTime2 = dateTime2.AddMonths(-1); + } + while (dateTime2.Day > 1) + { + dateTime2 = dateTime2.AddDays(-1.0); + } + DateTime dateTime3 = dateTime2.AddHours(-12.0); + DateTime dateTime4 = dateTime3; + for (int i = 0; i < targetPeriod.PeriodMultiplier; i++) + { + dateTime4 = dateTime4.AddDays(DateTime.IsLeapYear(dateTime2.Year) ? 366 : 365); + } + leftBorder = dateTime3.Ticks; + rightBorder = dateTime4.Ticks - 1; + } + } +} +namespace TradingPlatform.BusinessLayer.Utils +{ + public static class HistoryStepsCalculator + { + public static List> GetSteps(DateTime from, DateTime to, BasePeriod basePeriod, int multiplier, ISessionsContainer sessionsContainer, TimeZone timezone) + { + List> list = new List>(); + try + { + long sessionOffset = sessionsContainer.GetSessionOffset(timezone, basePeriod == BasePeriod.Week, applyNegativeSignForInDaySession: false); + long num = Period.TicksInBasePeriod(basePeriod) * multiplier; + long num2 = from.Ticks / num * num + sessionOffset; + long num3; + for (num3 = (to.Ticks / num + 1) * num + sessionOffset; num3 < to.Ticks; num3 += num) + { + } + if (num3 > to.Ticks) + { + while (num3 - num > to.Ticks) + { + num3 -= num; + } + } + while (num2 > from.Ticks) + { + num2 -= num; + } + if (num2 < from.Ticks) + { + for (; num2 + num < from.Ticks; num2 += num) + { + } + } + switch (basePeriod) + { + case BasePeriod.Month: + num2 = new DateTime(from.Year, from.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(sessionOffset).Ticks; + num3 = new DateTime(to.Year, to.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddMonths(1).AddTicks(sessionOffset).Ticks; + break; + case BasePeriod.Year: + num2 = new DateTime(from.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(sessionOffset).Ticks; + num3 = new DateTime(to.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddYears(1).AddTicks(sessionOffset).Ticks; + break; + } + DateTime date = new DateTime(num2, DateTimeKind.Utc); + while (date.Ticks < num3) + { + Interval item = GetNextStep(date, basePeriod, multiplier); + date = item.To; + if (sessionsContainer != null) + { + TimeSpan timeSpan = SessionsExtensions.?(item.From, sessionsContainer.TimeZone); + if (timeSpan != TimeSpan.Zero) + { + item = new Interval(item.From - timeSpan, item.To - timeSpan); + } + } + list.Add(item); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return list; + } + + public static Interval GetNextStep(DateTime date, BasePeriod basePeriod, int multiplier) + { + long value = Period.TicksInBasePeriod(basePeriod) * multiplier; + DateTime dateTime = date; + DateTime to = basePeriod switch + { + BasePeriod.Month => AddMonths(dateTime, multiplier), + BasePeriod.Year => dateTime.AddYears(multiplier), + _ => date.AddTicks(value), + }; + return new Interval(dateTime, to); + } + + /// + /// https://stackoverflow.com/questions/3060381/datetime-addmonths-adding-only-month-not-days + /// ????????: + /// (29 Feb).AddMonth(1) = 29 March + /// + public static DateTime AddMonths(DateTime date, int monthsCount) + { + if (date.Day != DateTime.DaysInMonth(date.Year, date.Month)) + { + return date.AddMonths(monthsCount); + } + return date.AddDays(1.0).AddMonths(monthsCount).AddDays(-1.0); + } + } + public readonly struct Interval : IEquatable> where T : IComparable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, bool> ??; + + public static Func, T> ??; + + public static Func, T> ??; + + internal bool ?(Interval P_0) + { + return !P_0.IsEmpty; + } + + internal T ?(Interval P_0) + { + return P_0.Min; + } + + internal T ?(Interval P_0) + { + return P_0.Max; + } + } + + [CompilerGenerated] + private readonly T ??; + + [CompilerGenerated] + private readonly T ??; + + public T From + { + [CompilerGenerated] + get + { + return ??; + } + } + + public T To + { + [CompilerGenerated] + get + { + return ??; + } + } + + public T Min + { + get + { + if (!IsReversal) + { + return From; + } + return To; + } + } + + public T Max + { + get + { + if (!IsReversal) + { + return To; + } + return From; + } + } + + public bool IsReversal => From.CompareTo(To) > 0; + + public bool IsEmpty => From.CompareTo(To) == 0; + + public static Interval Default => new Interval(default(T), default(T)); + + public Interval(T from, T to) + { + ?? = from; + ?? = to; + } + + public Interval Reverse() + { + return new Interval(To, From); + } + + public bool Contains(T value) + { + ref T reference = ref value; + T val = default(T); + if (val == null) + { + val = reference; + reference = ref val; + } + T min = Min; + if (reference.CompareTo(min) < 0) + { + return false; + } + ref T reference2 = ref value; + val = default(T); + if (val == null) + { + val = reference2; + reference2 = ref val; + } + T max = Max; + if (reference2.CompareTo(max) > 0) + { + return false; + } + return true; + } + + public Interval Intersect(Interval other) + { + T val = default(T); + T to = default(T); + if (Contains(other.Min)) + { + val = other.Min; + to = (Contains(other.Max) ? other.Max : Max); + } + else if (Contains(other.Max)) + { + val = Min; + to = other.Max; + } + else if (other.Contains(Min) && other.Contains(Max)) + { + return this; + } + return new Interval(val, to); + } + + public IEnumerable> Subtract(IEnumerable> intervals) + { + if (IsEmpty) + { + yield break; + } + if (!intervals.Any()) + { + yield return this; + yield break; + } + Interval interval = this; + Interval[] array = (from P_0 in intervals.Select(((Interval)interval).Intersect) + where !P_0.IsEmpty + orderby P_0.Min, P_0.Max descending + select P_0).ToArray(); + T val = Min; + Interval[] array2 = array; + T val2; + for (int num = 0; num < array2.Length; num++) + { + Interval interval2 = array2[num]; + if (interval2 == this) + { + yield break; + } + ref T reference = ref val; + val2 = default(T); + if (val2 == null) + { + val2 = reference; + reference = ref val2; + } + T max = Max; + if (reference.CompareTo(max) == 0) + { + yield break; + } + ref T reference2 = ref val; + val2 = default(T); + if (val2 == null) + { + val2 = reference2; + reference2 = ref val2; + } + T max2 = interval2.Max; + if (reference2.CompareTo(max2) > 0) + { + continue; + } + ref T reference3 = ref val; + val2 = default(T); + if (val2 == null) + { + val2 = reference3; + reference3 = ref val2; + } + T min = interval2.Min; + if (reference3.CompareTo(min) >= 0) + { + ref T reference4 = ref val; + val2 = default(T); + if (val2 == null) + { + val2 = reference4; + reference4 = ref val2; + } + T max3 = interval2.Max; + if (reference4.CompareTo(max3) < 0) + { + val = interval2.Max; + continue; + } + } + Interval interval3 = new Interval(val, interval2.Min); + val = interval2.Max; + yield return interval3; + } + ref T reference5 = ref val; + val2 = default(T); + if (val2 == null) + { + val2 = reference5; + reference5 = ref val2; + } + T max4 = Max; + if (reference5.CompareTo(max4) != 0) + { + yield return new Interval(val, Max); + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(From, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(To, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public bool Equals(Interval other) + { + if (EqualityComparer.Default.Equals(From, other.From)) + { + return EqualityComparer.Default.Equals(To, other.To); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj is Interval other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return HashCode.Combine(EqualityComparer.Default.GetHashCode(From), EqualityComparer.Default.GetHashCode(To)); + } + + public static bool operator ==(Interval left, Interval right) + { + return left.Equals(right); + } + + public static bool operator !=(Interval left, Interval right) + { + return !left.Equals(right); + } + } + public class LimitedCollection : ICollection, IEnumerable, IEnumerable + { + public const int DEFAULT_CAPACITY = 100; + + private readonly IList ??; + + [CompilerGenerated] + private readonly int ??; + + public int Capacity + { + [CompilerGenerated] + get + { + return ??; + } + } + + public bool IsFull => Count == Capacity; + + public int Count => ??.Count; + + bool ICollection.IsReadOnly => false; + + public LimitedCollection(int capacity = 100) + { + ?? = new List(capacity); + ?? = capacity; + } + + public void Add(T item) + { + lock (??) + { + if (IsFull) + { + ??.Remove(??[0]); + } + ??.Add(item); + } + } + + public void Clear() + { + ??.Clear(); + } + + public bool Contains(T item) + { + return ??.Contains(item); + } + + public bool Remove(T item) + { + return ??.Remove(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + ??.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + lock (??) + { + return new List(??).GetEnumerator(); + } + } + + private IEnumerator ?() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } + [Serializable] + public class LineOptions : IXElementSerialization, ICloneable, IEquatable + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private Font ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ?? = 10; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private LineStyle ??; + + public bool Enabled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithCheckBox + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithNumeric + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool WithColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Font Font + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Width + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int MaximumWidth + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color Color + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public LineStyle LineStyle + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Enabled)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), WithCheckBox)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), WithNumeric)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), WithColor)); + xElement.Add(Font.ToXElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Width)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MaximumWidth)); + xElement.Add(Color.ToXElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)LineStyle)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Enabled = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + WithCheckBox = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + WithNumeric = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + WithColor = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + Font = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToFont(); + Width = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + MaximumWidth = xElement.ToInt(); + } + Color = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToColor(); + LineStyle = (LineStyle)element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + } + + public object Clone() + { + LineOptions lineOptions = new LineOptions + { + Color = Color, + Enabled = Enabled, + LineStyle = LineStyle, + Width = Width, + WithCheckBox = WithCheckBox, + WithColor = WithColor, + WithNumeric = WithNumeric, + MaximumWidth = MaximumWidth + }; + if (Font != null) + { + lineOptions.Font = (Font)Font.Clone(); + } + return lineOptions; + } + + public bool Equals(LineOptions other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (Enabled == other.Enabled && WithCheckBox == other.WithCheckBox && WithNumeric == other.WithNumeric && WithColor == other.WithColor && object.Equals(Font, other.Font) && Width == other.Width && MaximumWidth == other.MaximumWidth && Color.Equals(other.Color)) + { + return LineStyle == other.LineStyle; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((LineOptions)obj); + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(Enabled); + hashCode.Add(WithCheckBox); + hashCode.Add(WithNumeric); + hashCode.Add(WithColor); + hashCode.Add(Font); + hashCode.Add(Width); + hashCode.Add(MaximumWidth); + hashCode.Add(Color); + hashCode.Add((int)LineStyle); + return hashCode.ToHashCode(); + } + } +} +namespace ? +{ + internal class ? : IEnumerable, IEnumerable + { + private readonly Dictionary ??; + + private readonly List ??; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + public virtual int Count => ??.Count; + + public virtual ? this[? P_0] + { + get + { + if (P_0 != null && ?? != null && ??.ContainsKey(P_0)) + { + return ??[P_0]; + } + return default(?); + } + set + { + if (!??.ContainsKey(val)) + { + this.?(val, val2); + return; + } + ??[val] = val2; + ??[??[val]] = val2; + } + } + + public virtual ICollection Keys => ??.Keys; + + public virtual ICollection Values => ??.Values; + + public ?() + { + ?? = new Dictionary(); + ?? = new List(); + ?? = new Dictionary(); + ?? = new Dictionary(); + } + + public static ? ?() + { + return new ?(); + } + + private void ?(int P_0) + { + while (P_0 <= ??.Count) + { + ? val = ??[P_0]; + ??[P_0 - 1] = val; + ??[val] = P_0 - 1; + P_0++; + } + ??.Remove(P_0 - 1); + } + + private int ?(? P_0, ? P_1) + { + ??.Add(P_0, P_1); + ??.Add(P_1); + int num = ??.Count - 1; + ??.Add(P_0, num); + ??.Add(num, P_0); + return num; + } + + private void ?(int P_0) + { + ??.RemoveAt(P_0); + ? key = ??[P_0]; + ??.Remove(key); + ??.Remove(key); + ??.Remove(P_0); + ?(P_0 + 1); + } + + public virtual ? ?(int P_0) + { + return ??[P_0]; + } + + public virtual ?[] ?() + { + ?[] array = new ?[??.Count]; + int num = 0; + foreach (? value in ??.Values) + { + array[num++] = value; + } + return array; + } + + public virtual int ?(? P_0, ? P_1) + { + return this.?(P_0, P_1); + } + + public virtual void ?(? P_0) + { + if (??.ContainsKey(P_0)) + { + ??.Remove(P_0); + int num = ??[P_0]; + ??.RemoveAt(num); + ??.Remove(P_0); + ??.Remove(num); + ?(num + 1); + } + } + + public virtual void ?(int P_0) + { + ?(P_0); + } + + public virtual void ?(int P_0, int P_1) + { + ??.RemoveRange(P_0, P_1); + for (int i = P_0; i < P_0 + P_1; i++) + { + ? key = ??[i]; + ??.Remove(key); + ??.Remove(key); + ??.Remove(i); + } + while (P_0 < ??.Count) + { + ? val = ??[P_0 + P_1]; + if (val != null) + { + ??[P_0] = val; + ??[val] = P_0; + } + P_0++; + } + for (int j = ??.Count; j < ??.Count + P_1; j++) + { + ??.Remove(j); + } + } + + public virtual void ?(? P_0) + { + ?(??.IndexOf(P_0)); + } + + public virtual ? ?(int P_0) + { + return ??[P_0]; + } + + public virtual void ?() + { + ??.Clear(); + ??.Clear(); + ??.Clear(); + ??.Clear(); + } + + public virtual bool ?(? P_0) + { + return ??.ContainsKey(P_0); + } + + public virtual bool ?(? P_0) + { + return ??.ContainsValue(P_0); + } + + public virtual IEnumerator GetEnumerator() + { + return ??.GetEnumerator(); + } + + private IEnumerator ?() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + + public virtual bool ?(? P_0, out ? P_1) + { + return ??.TryGetValue(P_0, out P_1); + } + } + internal class ? : ? + { + private readonly object ??; + + public override int Count + { + get + { + lock (??) + { + return base.Count; + } + } + } + + public override ? this[? P_0] + { + get + { + lock (??) + { + return base[P_0]; + } + } + set + { + lock (??) + { + base[val] = val2; + } + } + } + + public override ICollection Keys + { + get + { + lock (??) + { + return base.Keys; + } + } + } + + public override ICollection Values + { + get + { + lock (??) + { + return base.Values; + } + } + } + + public ?() + { + ?? = new object(); + } + + public override ? ?(int P_0) + { + lock (??) + { + return base.?(P_0); + } + } + + public override ?[] ?() + { + lock (??) + { + return base.?(); + } + } + + public override int ?(? P_0, ? P_1) + { + lock (??) + { + return base.?(P_0, P_1); + } + } + + public override void ?(? P_0) + { + lock (??) + { + base.?(P_0); + } + } + + public override void ?(int P_0) + { + lock (??) + { + base.?(P_0); + } + } + + public override void ?(int P_0, int P_1) + { + lock (??) + { + base.?(P_0, P_1); + } + } + + public override void ?(? P_0) + { + lock (??) + { + base.?(P_0); + } + } + + public override ? ?(int P_0) + { + lock (??) + { + return base.?(P_0); + } + } + + public override void ?() + { + lock (??) + { + base.?(); + } + } + + public override bool ?(? P_0) + { + lock (??) + { + return base.?(P_0); + } + } + + public override bool ?(? P_0) + { + lock (??) + { + return base.?(P_0); + } + } + + public override IEnumerator GetEnumerator() + { + lock (??) + { + return base.GetEnumerator(); + } + } + + public override bool ?(? P_0, out ? P_1) + { + lock (??) + { + return base.?(P_0, out P_1); + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils +{ + public class Map : IEnumerable>, IEnumerable + { + private readonly Dictionary ??; + + private readonly Dictionary ??; + + public Map() + { + ?? = new Dictionary(); + ?? = new Dictionary(); + } + + public void Add(T1 item1, T2 item2) + { + ??.Add(item1, item2); + ??.Add(item2, item1); + } + + public void Remove(T1 item1, T2 item2) + { + ??.Remove(item1); + ??.Remove(item2); + } + + public void Clear() + { + ??.Clear(); + ??.Clear(); + } + + public bool TryGetDirect(T1 key, out T2 value) + { + return ??.TryGetValue(key, out value); + } + + public bool TryGetReverse(T2 key, out T1 value) + { + return ??.TryGetValue(key, out value); + } + + public bool ContainsDirect(T1 key) + { + return ??.ContainsKey(key); + } + + public bool ContainsReverse(T2 key) + { + return ??.ContainsKey(key); + } + + public IEnumerator> GetEnumerator() + { + return ??.GetEnumerator(); + } + + private IEnumerator ?() + { + return ((IEnumerable)??).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } + public class MinotauroFibonacciLevelOptions : FibonacciLevelOptions + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private Color ??; + + [CompilerGenerated] + private string ??; + + public bool ShowExtension + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ShowExtensionLine + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ShowBaseLevel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string BaseLevelText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double ExtensionLevel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color ExtensionBackColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Color ExtensionBorderColor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ExtensionLabel + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MinotauroFibonacciLevelOptions(double level) + : base(level) + { + ShowBaseLevel = true; + ShowExtensionLine = true; + } + + public MinotauroFibonacciLevelOptions() + { + ShowExtensionLine = true; + } + + public override FibonacciLevelOptions Clone() + { + return new MinotauroFibonacciLevelOptions + { + UseCustom = base.UseCustom, + Line = base.Line, + CaptionFontColor = base.CaptionFontColor, + CaptionFont = base.CaptionFont, + Level = base.Level, + ShowExtension = ShowExtension, + ShowExtensionLine = ShowExtensionLine, + ShowBaseLevel = ShowBaseLevel, + ExtensionLevel = ExtensionLevel, + ExtensionBackColor = ExtensionBackColor, + ExtensionBorderColor = ExtensionBorderColor, + ExtensionLabel = ExtensionLabel, + BaseLevelText = BaseLevelText + }; + } + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ShowExtension)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ShowExtensionLine)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ShowBaseLevel)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExtensionLevel)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExtensionBackColor.ToArgb())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExtensionBorderColor.ToArgb())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExtensionLabel)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BaseLevelText)); + return xElement; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + ShowExtension = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + ShowExtensionLine = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + ShowBaseLevel = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + ExtensionLevel = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToDouble(); + ExtensionBackColor = Color.FromArgb(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt()); + ExtensionBorderColor = Color.FromArgb(element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt()); + ExtensionLabel = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(); + BaseLevelText = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString(); + } + } + public class DotNetNaturalSortComparer : IComparer + { + private readonly StringComparison ??; + + private readonly IComparer ??; + + private const byte ?? = 0; + + private const byte ?? = 1; + + private const byte ?? = 2; + + private const byte ?? = 3; + + public DotNetNaturalSortComparer(StringComparison stringComparison) + { + ?? = stringComparison; + } + + public DotNetNaturalSortComparer(IComparer stringComparer) + { + ?? = stringComparer; + } + + public int Compare(string str1, string str2) + { + if (str1 == str2) + { + return 0; + } + if (str1 == null) + { + return -1; + } + if (str2 == null) + { + return 1; + } + int length = str1.Length; + int length2 = str2.Length; + int num = 0; + int num2 = 0; + int num12; + while (true) + { + int i = num; + byte b = 0; + for (; i < length; i++) + { + byte b2 = ?(str1[i]); + if (b == 0) + { + b = b2; + } + else if (b != b2) + { + break; + } + } + int j = num2; + byte b3 = 0; + for (; j < length2; j++) + { + byte b4 = ?(str2[j]); + if (b3 == 0) + { + b3 = b4; + } + else if (b3 != b4) + { + break; + } + } + int num3 = b.CompareTo(b3); + if (num3 != 0) + { + return num3; + } + if (b == 0) + { + return 0; + } + int num4 = i - num; + int num5 = j - num2; + if (b == 2) + { + int num6 = Math.Max(num4, num5); + int num7 = num6 - num4; + int num8 = num6 - num5; + for (int k = 0; k < num6; k++) + { + char c = ((k < num7) ? '0' : str1[num + k - num7]); + char value = ((k < num8) ? '0' : str2[num2 + k - num8]); + int num9 = c.CompareTo(value); + if (num9 != 0) + { + return num9; + } + } + int num10 = num7.CompareTo(num8); + if (num10 != 0) + { + return num10; + } + } + else if (?? != null) + { + string x = str1.Substring(num, num4); + string y = str2.Substring(num2, num5); + int num11 = ??.Compare(x, y); + if (num11 != 0) + { + return num11; + } + } + else + { + int length3 = Math.Min(num4, num5); + num12 = string.Compare(str1, num, str2, num2, length3, ??); + if (num12 == 0) + { + num12 = num4 - num5; + } + if (num12 != 0) + { + break; + } + } + num = i; + num2 = j; + } + return num12; + } + + private static byte ?(char P_0) + { + if (P_0 < 'a') + { + if (P_0 < 'A') + { + if (P_0 < '0' || P_0 > '9') + { + return 1; + } + return 2; + } + if (P_0 > 'Z') + { + return 1; + } + return 3; + } + if (P_0 > 'z') + { + if (P_0 >= '\u0080') + { + if (!char.IsLetter(P_0)) + { + return 1; + } + return 3; + } + return 1; + } + return 3; + } + } + public class PerformedRequestEventArgs : RequestEventArgs + { + [CompilerGenerated] + private readonly object ??; + + public object RequestResult + { + [CompilerGenerated] + get + { + return ??; + } + } + + public PerformedRequestEventArgs(RequestParameters requestParameters, object requestResult) + : base(requestParameters) + { + ?? = requestResult; + } + } + public class PnlAlertsContainer + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal PnlAlertItem ?(PnlAlertItem P_0) + { + return new PnlAlertItem(P_0); + } + } + + [CompilerGenerated] + private PnlAlertItem[] ??; + + public Action OnAlertEnabilityChanged; + + public PnlAlertItem[] PnlAlerts + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public PnlAlertsContainer() + { + PnlAlerts = new PnlAlertItem[0]; + } + + public PnlAlertsContainer Clone() + { + PnlAlertsContainer pnlAlertsContainer = new PnlAlertsContainer(); + if (PnlAlerts.Length != 0) + { + pnlAlertsContainer.PnlAlerts = PnlAlerts.Select((PnlAlertItem P_0) => new PnlAlertItem(P_0)).ToArray(); + } + return pnlAlertsContainer; + } + } + public class PnlAlertItem : ITriggerItem, IEquatable + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + public bool IsChecked + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TargetValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Increment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int Precision + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public PnlAlertItem() + { + IsChecked = false; + TargetValue = 1.0; + Increment = 1.0; + Precision = 1; + } + + public PnlAlertItem(PnlAlertItem source) + { + IsChecked = source.IsChecked; + Symbol = source.Symbol; + TargetValue = source.TargetValue; + Increment = source.Increment; + Precision = source.Precision; + } + + public bool Equals(PnlAlertItem other) + { + if (other == null) + { + return false; + } + if (other == this) + { + return true; + } + if (Symbol.Equals(other.Symbol)) + { + return TargetValue.Equals(other.TargetValue); + } + return false; + } + } + public class TimeInTradeContainer + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal TimeInTradeItem ?(TimeInTradeItem P_0) + { + return new TimeInTradeItem(P_0); + } + } + + [CompilerGenerated] + private TimeInTradeItem[] ??; + + public Action OnItemEnabilityChanged; + + public TimeInTradeItem[] TimeInTradeItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeInTradeContainer() + { + TimeInTradeItems = new TimeInTradeItem[0]; + } + + public TimeInTradeContainer Clone() + { + TimeInTradeContainer timeInTradeContainer = new TimeInTradeContainer(); + if (TimeInTradeItems.Length != 0) + { + timeInTradeContainer.TimeInTradeItems = TimeInTradeItems.Select((TimeInTradeItem P_0) => new TimeInTradeItem(P_0)).ToArray(); + } + return timeInTradeContainer; + } + } + public class TimeInTradeItem : ITriggerItem, IEquatable + { + private bool ??; + + [CompilerGenerated] + private Symbol ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private TimeInTradePlDirection ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private bool ??; + + public bool IsChecked + { + get + { + return ??; + } + set + { + NeedTimeResetToNow = value; + ?? = value; + } + } + + public Symbol Symbol + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int TimeInSeconds + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeInTradePlDirection PLDirection + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime ActivatedTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public bool NeedTimeResetToNow + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeInTradeItem() + { + } + + public TimeInTradeItem(TimeInTradeItem source) + : this() + { + IsChecked = source.IsChecked; + Symbol = source.Symbol; + TimeInSeconds = source.TimeInSeconds; + PLDirection = source.PLDirection; + ActivatedTime = source.ActivatedTime; + } + + public bool Equals(TimeInTradeItem other) + { + if (other == null) + { + return false; + } + if (other == this) + { + return true; + } + if (IsChecked == other.IsChecked && Symbol.Equals(other.Symbol) && TimeInSeconds.Equals(other.TimeInSeconds)) + { + return PLDirection.Equals(other.PLDirection); + } + return false; + } + + public override bool Equals(object obj) + { + return Equals(obj as TimeInTradeItem); + } + + public void ResetTriggerTime(bool toNow = false) + { + ActivatedTime = (toNow ? Core.Instance.TimeUtils.DateTimeUtcNow : default(DateTime)); + NeedTimeResetToNow = false; + } + } + public interface ITriggerItem + { + bool IsChecked { get; } + + Symbol Symbol { get; } + } + public enum TimeInTradePlDirection + { + [EnumMember(Value = "Any")] + Any, + [EnumMember(Value = "Positive")] + Positive, + [EnumMember(Value = "Negative")] + Negative + } + public class RequestEventArgs : EventArgs + { + [CompilerGenerated] + private readonly RequestParameters ??; + + public RequestParameters RequestParameters + { + [CompilerGenerated] + get + { + return ??; + } + } + + public RequestEventArgs(RequestParameters requestParameters) + { + ?? = requestParameters; + } + } + public class Rss : List, ICloneable, IXElementSerialization + { + public object Clone() + { + Rss rss = new Rss(); + using Enumerator enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + RssItem current = enumerator.Current; + rss.Add(current.Clone() as RssItem); + } + return rss; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement == null) + { + if (element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Add(new RssItem + { + Name = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + Url = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + Add(new RssItem + { + Name = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + Url = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + Add(new RssItem + { + Name = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + Url = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }); + } + return; + } + foreach (XElement item in xElement?.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + Add(new RssItem + { + Active = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(), + Name = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value, + Url = item.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value + }); + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + using Enumerator enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + RssItem current = enumerator.Current; + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(xElement2); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), current.Active)); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), current.Name)); + xElement2.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), current.Url)); + } + return xElement; + } + } + [DataContract(Name = "RssItem", Namespace = "TradingPlatform")] + public class RssItem : ICloneable + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + private string ??; + + [CompilerGenerated] + private bool ??; + + [DataMember(Name = "Active")] + public bool Active + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Name")] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Url")] + public string Url + { + get + { + return ??; + } + set + { + if (!(?? == value)) + { + ?? = value; + Subscribed = false; + } + } + } + + public bool Subscribed + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object Clone() + { + return new RssItem + { + Active = Active, + Name = Name, + Url = Url, + Subscribed = Subscribed + }; + } + } + public class SubscriptionsCache : IDisposable + { + private class ? : IDisposable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, bool> ??; + + public static Func, string> ??; + + internal bool ?(KeyValuePair P_0) + { + return P_0.Value > 0; + } + + internal string ?(KeyValuePair P_0) + { + return P_0.Key; + } + } + + private readonly IDictionary ??; + + private readonly object ??; + + public ?() + { + ?? = new Dictionary(); + ?? = new object(); + } + + public bool ?(string P_0) + { + lock (??) + { + ?(P_0); + ??[P_0]++; + return ??[P_0] == 1; + } + } + + public bool ?(string P_0) + { + lock (??) + { + ?(P_0); + ??[P_0] = Math.Max(0, ??[P_0] - 1); + return ??[P_0] == 0; + } + } + + public bool ?(string P_0) + { + lock (??) + { + if (!??.ContainsKey(P_0)) + { + return false; + } + return ??[P_0] > 0; + } + } + + public string[] ?() + { + lock (??) + { + return (from P_0 in ?? + where P_0.Value > 0 + select P_0.Key).ToArray(); + } + } + + private void ?(string P_0) + { + if (!??.ContainsKey(P_0)) + { + ??[P_0] = 0; + } + } + + public void Dispose() + { + lock (??) + { + ??.Clear(); + } + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func> ??; + + internal IEnumerable ?(? P_0) + { + return P_0.?(); + } + } + + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(? P_0) + { + return P_0.?(??); + } + } + + private readonly IDictionary ??; + + public SubscriptionsCache() + { + ?? = new Dictionary(); + foreach (SubscribeQuoteType value in Enum.GetValues(typeof(SubscribeQuoteType))) + { + ??[value] = new ?(); + } + } + + public bool AddSubscription(SubscribeQuoteType subscribeQuoteType, string symbolId) + { + return ??[subscribeQuoteType].?(symbolId); + } + + public bool RemoveSubscription(SubscribeQuoteType subscribeQuoteType, string symbolId) + { + return ??[subscribeQuoteType].?(symbolId); + } + + public bool IsSubscribed(SubscribeQuoteType subscribeQuoteType, string symbolId) + { + return ??[subscribeQuoteType].?(symbolId); + } + + public bool HasAnySubscription(string symbolId) + { + return ??.Values.Any((? P_0) => P_0.?(symbolId)); + } + + public string[] FindSubscribedSymbols(SubscribeQuoteType subscribeQuoteType) + { + return ??[subscribeQuoteType].?(); + } + + public string[] FindAllSubscribedSymbols() + { + return ??.Values.SelectMany((? P_0) => P_0.?()).Distinct().ToArray(); + } + + public void Dispose() + { + foreach (? value in ??.Values) + { + value.Dispose(); + } + } + } + public enum TableBaseType + { + Numeric, + String, + Date + } + public enum TableConditionType + { + [Description("=")] + Equal, + [Description("!=")] + NonEqual, + [Description("Contains")] + Present, + [Description("Not contains")] + NotPresent, + [Description(">")] + More, + [Description(">=")] + MoreEqual, + [Description("<")] + Less, + [Description("<=")] + LessEqual, + [Description("Cross")] + Cross, + [Description("Cross Above")] + CrossAbove, + [Description("Cross Below")] + CrossBelow + } + public class UpdatableDataSource + { + private T ??; + + private DateTime ??; + + private readonly Func ??; + + private readonly TimeSpan ??; + + private readonly object ??; + + public UpdatableDataSource(Func updateFunc, TimeSpan expirationPeriod) + { + ?? = updateFunc; + ?? = expirationPeriod; + ?? = new object(); + } + + public bool TryGetData(out T value, CancellationToken cancellation) + { + ?(cancellation); + return TryGetData(out value); + } + + public bool TryGetData(out T value) + { + value = ??; + return !EqualityComparer.Default.Equals(value, default(T)); + } + + private void ?(CancellationToken P_0) + { + if (?? == null) + { + return; + } + lock (??) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + if (dateTimeUtcNow - ?? < ??) + { + return; + } + try + { + ?? = ??(P_0); + } + catch + { + } + finally + { + ?? = dateTimeUtcNow; + } + } + } + } + public class VolumeAnalysisParameters + { + [CompilerGenerated] + private VolumeAnalysisPluginType ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private object ??; + + [CompilerGenerated] + private SymbolVolumeType ??; + + public Action RefreshChart; + + [CompilerGenerated] + private ISessionsContainer ??; + + [CompilerGenerated] + private TimeZone ??; + + public VolumeAnalysisPluginType Type + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object Parameter + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public object Chart + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SymbolVolumeType SymbolVolumeType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ISessionsContainer SessionsContainer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeZone CurrentTimezone + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public enum VolumeAnalysisPluginType + { + Cluster, + TimeStatistics, + TimeHistogram, + LeftProfile, + RightProfile, + StepProfile, + PowerTrades, + VWAP, + VIPAnalysis + } +} +namespace TradingPlatform.BusinessLayer.Utils.UserTradesLocalStorage +{ + public class UsersTradesStorage : DataStorage + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, bool> ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(Interval P_0) + { + return !P_0.IsEmpty; + } + + internal string ?(MessageTrade P_0) + { + return P_0.TradeId; + } + + internal MessageTrade ?(MessageTrade P_0) + { + return P_0; + } + } + + [CompilerGenerated] + private sealed class ? + { + public UsersTradesStorage ??; + + public UserTradesInterval ??; + + internal void ?() + { + ??.??.Save(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Interval ??; + + internal Interval ?(Interval P_0) + { + return P_0.Intersect(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Trade ??; + + public UsersTradesStorage ??; + + internal void ?() + { + DateTime dateTime = ??.DateTime.AddTicks(1L); + if (??.DateTime <= ??.??) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.DateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.??.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture)); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + Interval interval = new Interval(??.DateTime.AddTicks(-1L), ??.DateTime.AddTicks(1L)); + UserTradesInterval userTradesInterval = ??.??.Load(interval); + Dictionary dictionary = userTradesInterval.Trades.ToDictionary(UsersTradesStorage.?.??.?, UsersTradesStorage.?.??.?); + MessageTrade messageTrade = ??.BuildMessage(); + dictionary[messageTrade.TradeId] = messageTrade; + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(72, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(userTradesInterval.Trades.Count()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(dictionary.Count); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + ??.??.Save(new UserTradesInterval + { + Trades = dictionary.Values, + Interval = interval + }); + } + else + { + ??.??.Save(new UserTradesInterval + { + Trades = new MessageTrade[1] { ??.BuildMessage() }, + Interval = new Interval(??.??, dateTime) + }); + ??.?? = dateTime; + } + } + } + + private static readonly Type ??; + + private readonly IUserTradesLocalStorage ??; + + private readonly string ??; + + private DateTime ??; + + public bool IsRealtimeCollectingAllowed => !string.IsNullOrEmpty(??); + + static UsersTradesStorage() + { + try + { + ?? = AssemblyLoader.LoadTypes(Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), typeof(IUserTradesLocalStorage), null, SearchOption.AllDirectories)?.FirstOrDefault(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public UsersTradesStorage(IUserTradesLocalStorage storage, string localFilePath, string connectionId) + : base(storage, localFilePath) + { + ?? = storage; + ?? = connectionId; + ?? = Core.Instance.TimeUtils.DateTimeUtcNow; + if (IsRealtimeCollectingAllowed) + { + Core.Instance.TradeAdded += ?; + } + } + + public override void Dispose() + { + Core.Instance.TradeAdded -= ?; + base.Dispose(); + } + + public static UsersTradesStorage Create(string connectionString, string connectionId) + { + if (?? == null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IUserTradesLocalStorage obj = Activator.CreateInstance(??) as IUserTradesLocalStorage; + if (obj == null) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + string directoryName = Path.GetDirectoryName(connectionString); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + return new UsersTradesStorage(obj, connectionString, connectionId); + } + + public void Save(UserTradesInterval historyInterval) + { + CheckDisposed(); + PushAction(delegate + { + ??.Save(historyInterval); + }); + } + + public IList Load(Interval requestParameters, out List> historyParametersForServerRequest) + { + CheckDisposed(); + List list = new List(); + historyParametersForServerRequest = new List>(); + UsersTradesStorageInfo info = ??.GetInfo(); + if (!info.StoredIntervals.Any()) + { + historyParametersForServerRequest.Add(requestParameters); + return list; + } + Interval ?? = requestParameters; + Interval[] collection = ??.Subtract(info.StoredIntervals).ToArray(); + historyParametersForServerRequest.AddRange(collection); + Interval[] array = (from P_0 in info.StoredIntervals + select P_0.Intersect(??) into P_0 + where !P_0.IsEmpty + select P_0).ToArray(); + foreach (Interval interval in array) + { + UserTradesInterval item = ??.Load(interval); + list.Add(item); + } + return list; + } + + private void ?(Trade P_0) + { + if (P_0.ConnectionId != ??) + { + return; + } + PushAction(delegate + { + DateTime to = P_0.DateTime.AddTicks(1L); + if (P_0.DateTime <= ??) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(74, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.DateTime.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture)); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + Interval interval = new Interval(P_0.DateTime.AddTicks(-1L), P_0.DateTime.AddTicks(1L)); + UserTradesInterval userTradesInterval = ??.Load(interval); + Dictionary dictionary = userTradesInterval.Trades.ToDictionary(UsersTradesStorage.?.??.?, UsersTradesStorage.?.??.?); + MessageTrade messageTrade = P_0.BuildMessage(); + dictionary[messageTrade.TradeId] = messageTrade; + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(72, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(userTradesInterval.Trades.Count()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(dictionary.Count); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + ??.Save(new UserTradesInterval + { + Trades = dictionary.Values, + Interval = interval + }); + } + else + { + ??.Save(new UserTradesInterval + { + Trades = new MessageTrade[1] { P_0.BuildMessage() }, + Interval = new Interval(??, to) + }); + ?? = to; + } + }); + } + } + public class UsersTradesStorageInfo + { + [CompilerGenerated] + private List> ??; + + public List> StoredIntervals + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public UsersTradesStorageInfo() + { + StoredIntervals = new List>(); + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.UpdatesProvider +{ + public class DifferenceObserver + { + [CompilerGenerated] + private ApplyDifferencePredicate ??; + + private readonly IDictionary> ??; + + public ApplyDifferencePredicate ApplyDifferencePredicate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DifferenceObserver() + { + ?? = new Dictionary>(); + } + + public void RegisterType(Type type, params string[] propertyNamesToObserve) + { + List list = new List(); + ??[type] = list; + PropertyInfo[] properties = type.GetProperties(); + foreach (PropertyInfo propertyInfo in properties) + { + if (propertyInfo.CanRead && propertyInfo.CanWrite && (propertyNamesToObserve.Length == 0 || propertyNamesToObserve.Contains(propertyInfo.Name))) + { + list.Add(propertyInfo); + } + } + } + + public IEnumerable GetDifference(T entity1, T entity2, bool updateEntity1 = false) + { + Type typeFromHandle = typeof(T); + if (!??.TryGetValue(typeFromHandle, out var value)) + { + yield break; + } + foreach (PropertyInfo item in value) + { + object? value2 = item.GetValue(entity1); + object value3 = item.GetValue(entity2); + if (!object.Equals(value2, value3)) + { + if (updateEntity1 && (ApplyDifferencePredicate?.Invoke(item.Name, value3) ?? true)) + { + item.SetValue(entity1, value3); + } + yield return item.Name; + } + } + } + + public void UpdateEntity(T entity1, T entity2) + { + Type typeFromHandle = typeof(T); + if (!??.TryGetValue(typeFromHandle, out var value)) + { + return; + } + foreach (PropertyInfo item in value) + { + object? value2 = item.GetValue(entity1); + object value3 = item.GetValue(entity2); + if (!object.Equals(value2, value3)) + { + ApplyDifferencePredicate applyDifferencePredicate = ApplyDifferencePredicate; + if (applyDifferencePredicate == null || applyDifferencePredicate(item.Name, value3)) + { + item.SetValue(entity1, value3); + } + } + } + } + } + public delegate bool ApplyDifferencePredicate(string propertyName, object propertyValue); + public class UpdatesProvider + { + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + private IDictionary ??; + + private readonly object ??; + + private readonly DifferenceObserver ??; + + [CompilerGenerated] + private bool ??; + + public TValue[] Items + { + get + { + lock (??) + { + return ??.Values.ToArray(); + } + } + } + + public bool UpdateItem + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ApplyDifferencePredicate ApplyDifferencePredicate + { + get + { + return ??.ApplyDifferencePredicate; + } + set + { + ??.ApplyDifferencePredicate = value; + } + } + + public event Action ItemAdded + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ItemUpdated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action ItemRemoved + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public UpdatesProvider(IDictionary items, params string[] propertyNamesToObserve) + { + ?? = new Dictionary(items); + ?? = new object(); + ?? = new DifferenceObserver(); + ??.RegisterType(typeof(TValue), propertyNamesToObserve); + UpdateItem = true; + } + + public void ProcessItems(IDictionary newCache) + { + newCache = new Dictionary(newCache); + lock (??) + { + IEnumerable enumerable = newCache.Keys.Except(??.Keys); + IEnumerable enumerable2 = ??.Keys.Except(newCache.Keys); + IEnumerable enumerable3 = ??.Keys.Intersect(newCache.Keys); + foreach (TKey item in enumerable) + { + ?(newCache[item]); + } + foreach (TKey item2 in enumerable2) + { + ?(??[item2]); + } + foreach (TKey item3 in enumerable3) + { + TValue entity = ??[item3]; + TValue val = newCache[item3]; + if (??.GetDifference(entity, val, UpdateItem).ToArray().Any()) + { + ?(val); + } + } + ?? = newCache; + } + } + + public void ProcessNewItem(TKey key, TValue newItem) + { + Action action = null; + lock (??) + { + if (??.TryGetValue(key, out var value)) + { + if (!??.GetDifference(value, newItem, UpdateItem).Any()) + { + return; + } + action = ?; + } + else + { + action = ?; + } + ??[key] = newItem; + } + action(newItem); + } + + public void RemoveItem(TKey key, TValue item) + { + lock (??) + { + if (!??.ContainsKey(key)) + { + return; + } + ??.Remove(key); + } + ?(item); + } + + public bool TryGetValue(TKey key, out TValue value) + { + lock (??) + { + return ??.TryGetValue(key, out value); + } + } + + private void ?(TValue P_0) + { + try + { + ???.Invoke(P_0); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + private void ?(TValue P_0) + { + try + { + ???.Invoke(P_0); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + private void ?(TValue P_0) + { + try + { + ???.Invoke(P_0); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.TradingProtection +{ + public class TradingProtector : ICustomizable + { + [CompilerGenerated] + private bool ??; + + private Period ??; + + private int ??; + + private readonly ConcurrentQueue ??; + + private TimeSpan ??; + + public bool Enabled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Period Period + { + get + { + return ??; + } + set + { + ?? = value; + ?? = ??.Duration; + } + } + + public int Limit + { + get + { + return ??; + } + set + { + ?? = Math.Max(0, value); + } + } + + public IList Settings + { + get + { + SettingItemRelationVisibility relation = new SettingItemRelationVisibility(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), true); + List list = new List(); + list.Add(new SettingItemBooleanSwitcher(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Enabled) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SortIndex = 5 + }); + list.Add(new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Period) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + SortIndex = 10, + ExcludedPeriods = new BasePeriod[1], + Relation = relation + }); + list.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Limit) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + Minimum = 0, + SortIndex = 20, + Relation = relation + }); + return list; + } + set + { + Period = value.GetValueOrDefault(Period, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Limit = value.GetValueOrDefault(Limit, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Enabled = value.GetValueOrDefault(Enabled, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Period = value.GetValueOrDefault(Period, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Limit = value.GetValueOrDefault(Limit, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + internal TradingProtector() + { + Enabled = true; + Period = Period.SECOND1; + Limit = 10; + ?? = new ConcurrentQueue(); + } + + public bool IsOperationAllowed() + { + if (!Enabled) + { + return true; + } + bool num = ??.Count < Limit; + if (num) + { + ??.Enqueue(Core.Instance.TimeUtils.DateTimeUtcNow); + } + return num; + } + + internal void ?() + { + if (Enabled && ??.Ticks > 0) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + DateTime result; + while (??.TryPeek(out result) && dateTimeUtcNow - result > ??) + { + ??.TryDequeue(out var _); + } + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.TaskSchedulers +{ + public class DegreeOfParallelismTaskScheduler : TaskScheduler, IDisposable + { + [CompilerGenerated] + private readonly int ??; + + private List ??; + + private readonly object ??; + + private int ??; + + public sealed override int MaximumConcurrencyLevel + { + [CompilerGenerated] + get + { + return ??; + } + } + + public DegreeOfParallelismTaskScheduler(int maxDegreeOfParallelism) + { + if (maxDegreeOfParallelism < 1) + { + throw new ArgumentOutOfRangeException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?? = maxDegreeOfParallelism; + ?? = new List(); + ?? = new object(); + ?? = 0; + } + + protected sealed override void QueueTask(Task task) + { + lock (??) + { + if (?? == null) + { + return; + } + ??.Add(task); + if (?? >= MaximumConcurrencyLevel) + { + return; + } + ??++; + } + ThreadPool.UnsafeQueueUserWorkItem(delegate + { + try + { + Task task2; + while (?(out task2)) + { + try + { + if (task2 != null) + { + TryExecuteTask(task2); + } + } + catch + { + } + } + } + finally + { + ??--; + } + }, null); + } + + protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) + { + if (taskWasPreviouslyQueued) + { + if (TryDequeue(task)) + { + return TryExecuteTask(task); + } + return false; + } + return TryExecuteTask(task); + } + + protected sealed override bool TryDequeue(Task task) + { + lock (??) + { + return ???.Remove(task) ?? false; + } + } + + protected sealed override IEnumerable GetScheduledTasks() + { + return ???.ToArray(); + } + + public void Dispose() + { + lock (??) + { + ?? = null; + } + } + + [CompilerGenerated] + private bool ?(out Task P_0) + { + P_0 = null; + lock (??) + { + if (?? == null || ??.Count == 0) + { + return false; + } + P_0 = ??[0]; + ??.RemoveAt(0); + return true; + } + } + + [CompilerGenerated] + private void ?(object? P_0) + { + try + { + Task task; + while (?(out task)) + { + try + { + if (task != null) + { + TryExecuteTask(task); + } + } + catch + { + } + } + } + finally + { + ??--; + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.Sounds +{ + public static class Sound + { + private static class ? + { + public const string ?? = "connectionFinished.wav"; + + public const string ?? = "connectionLost.wav"; + + public const string ?? = "orderFilled.wav"; + + public const string ?? = "orderRejected.wav"; + + public const string ?? = "PositionClosed.wav"; + + public const string ?? = "DefaultAlert.wav"; + + public const string ?? = "OrderCreated.wav"; + + public const string ?? = "Update.wav"; + } + + public static string ConnectionFinished; + + public static string ConnectionLost; + + public static string OrderCreatedCancelledReplaced; + + public static string OrderFilled; + + public static string OrderRejected; + + public static string PositionClosed; + + public static string DefaultAlert; + + public static string UpdateAvailable; + + [CompilerGenerated] + private static readonly Dictionary ??; + + public static Dictionary Defaults + { + [CompilerGenerated] + get + { + return ??; + } + } + + static Sound() + { + ConnectionFinished = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ConnectionLost = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + OrderCreatedCancelledReplaced = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + OrderFilled = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + OrderRejected = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + PositionClosed = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + DefaultAlert = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + UpdateAvailable = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?? = new Dictionary + { + [ConnectionFinished] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [ConnectionLost] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [OrderCreatedCancelledReplaced] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [OrderFilled] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [OrderRejected] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [PositionClosed] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [DefaultAlert] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + [UpdateAvailable] = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + } + } + public class SoundItem : IXElementSerialization + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public bool Enabled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public string CurrentPath + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SoundItem() + { + } + + public SoundItem(string name) + { + Enabled = true; + Name = name; + CurrentPath = Sound.Defaults[name]; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Enabled = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToBool(); + Name = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + CurrentPath = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Enabled)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CurrentPath)); + return xElement; + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.Storage +{ + public interface IOrdersHistoryLocalStorage : ILocalStorage + { + void Save(OrdersHistoryInterval interval); + + OrdersHistoryInterval Load(Interval interval); + + void Delete(Interval interval); + + OrdersHistoryStorageInfo GetInfo(); + } + public class OrdersHistoryInterval + { + [CompilerGenerated] + private Interval ??; + + [CompilerGenerated] + private IEnumerable ??; + + public Interval Interval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IEnumerable OrdersHistory + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public sealed class OrdersHistoryStorage : DataStorage + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, bool> ??; + + internal bool ?(Interval P_0) + { + return !P_0.IsEmpty; + } + } + + [CompilerGenerated] + private sealed class ? + { + public OrdersHistoryStorage ??; + + public OrdersHistoryInterval ??; + + internal void ?() + { + ??.??.Save(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public Interval ??; + + internal Interval ?(Interval P_0) + { + return P_0.Intersect(??); + } + } + + private static readonly Type ??; + + private readonly IOrdersHistoryLocalStorage ??; + + static OrdersHistoryStorage() + { + try + { + ?? = AssemblyLoader.LoadTypes(Path.Combine(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), typeof(IOrdersHistoryLocalStorage), null, SearchOption.AllDirectories)?.FirstOrDefault(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public OrdersHistoryStorage(IOrdersHistoryLocalStorage storage, string localFilePath, string connectionId) + : base(storage, localFilePath) + { + ?? = storage; + } + + public static OrdersHistoryStorage Create(string connectionString, string connectionId) + { + if (?? == null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IOrdersHistoryLocalStorage obj = Activator.CreateInstance(??) as IOrdersHistoryLocalStorage; + if (obj == null) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + string directoryName = Path.GetDirectoryName(connectionString); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + return new OrdersHistoryStorage(obj, connectionString, connectionId); + } + + public void Save(OrdersHistoryInterval historyInterval) + { + CheckDisposed(); + PushAction(delegate + { + ??.Save(historyInterval); + }); + } + + public IList Load(Interval requestParameters, out List> historyParametersForServerRequest) + { + CheckDisposed(); + List list = new List(); + historyParametersForServerRequest = new List>(); + OrdersHistoryStorageInfo info = ??.GetInfo(); + if (!info.StoredIntervals.Any()) + { + historyParametersForServerRequest.Add(requestParameters); + return list; + } + Interval ?? = requestParameters; + Interval[] collection = ??.Subtract(info.StoredIntervals).ToArray(); + historyParametersForServerRequest.AddRange(collection); + Interval[] array = (from P_0 in info.StoredIntervals + select P_0.Intersect(??) into P_0 + where !P_0.IsEmpty + select P_0).ToArray(); + foreach (Interval interval in array) + { + OrdersHistoryInterval item = ??.Load(interval); + list.Add(item); + } + return list; + } + } + public sealed class OrdersHistoryStorageInfo + { + [CompilerGenerated] + private List> ??; + + public List> StoredIntervals + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OrdersHistoryStorageInfo() + { + StoredIntervals = new List>(); + } + } + public abstract class DataStorage : ActionBufferedProcessor, IDisposable + { + [CompilerGenerated] + private sealed class ? + { + public DataStorage ??; + + public Action ??; + + internal void ?() + { + if (!??.??) + { + ???.Invoke(); + } + } + } + + [CompilerGenerated] + private sealed class ? + { + public DataStorage ??; + + public Action ??; + + public ManualResetEventSlim ??; + + internal void ?() + { + try + { + if (!??.??) + { + ???.Invoke(); + } + } + finally + { + ??.Set(); + } + } + } + + private readonly ILocalStorage ??; + + private readonly List ??; + + private readonly object ??; + + private bool ??; + + protected DataStorage(ILocalStorage storage, string localFilePath) + { + ?? = storage ?? throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ??.Connect(localFilePath); + ?? = new List(); + ?? = new object(); + Start(); + } + + public virtual void Dispose() + { + CheckDisposed(); + ?? = true; + try + { + Clear(); + WaitAllMessagesProcess(); + Stop(); + ??.Disconnect(); + lock (??) + { + foreach (ManualResetEventSlim item in ??) + { + item.Set(); + } + ??.Clear(); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + protected void CheckDisposed() + { + if (!??) + { + return; + } + throw new ObjectDisposedException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + protected void PushAction(Action action) + { + Push(delegate + { + if (!??) + { + action?.Invoke(); + } + }); + } + + protected void WaitForAction(Action action) + { + ManualResetEventSlim ?? = new ManualResetEventSlim(initialState: false); + lock (??) + { + ??.Add(??); + } + Push(delegate + { + try + { + if (!??) + { + action?.Invoke(); + } + } + finally + { + ??.Set(); + } + }); + ??.Wait(); + lock (??) + { + ??.Remove(??); + } + } + } + public interface ILocalStorage + { + void Connect(string connectionString); + + void Disconnect(); + } + public interface IUserTradesLocalStorage : ILocalStorage + { + void Save(UserTradesInterval interval); + + UserTradesInterval Load(Interval interval); + + void Delete(Interval interval); + + UsersTradesStorageInfo GetInfo(); + } + public class UserTradesInterval + { + [CompilerGenerated] + private Interval ??; + + [CompilerGenerated] + private IEnumerable ??; + + public Interval Interval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IEnumerable Trades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.Storage.InMemory +{ + public class QuotesInMemoryStorage where TQuote : MessageQuote + { + [CompilerGenerated] + private sealed class ? + { + public Interval ??; + + internal bool ?(TQuote P_0) + { + return ??.Contains(P_0.Time); + } + } + + [CompilerGenerated] + private readonly int ??; + + private readonly List ??; + + private readonly TimeSpan ??; + + private const int ?? = 1000; + + private int ??; + + public int MaxCapacity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public QuotesInMemoryStorage(TimeSpan desiredDepth) + { + ?? = new List(); + ?? = desiredDepth; + MaxCapacity = 100000; + } + + public void Put(TQuote item) + { + try + { + if (??++ >= 1000) + { + ?? = 0; + ?(item); + } + ??.Add(item); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + private TQuote[] ?() + { + try + { + return ??.ToArray(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return null; + } + + public bool TryGet(Interval interval, out TQuote[] items, out Interval remainingInterval) + { + remainingInterval = Interval.Default; + items = Array.Empty(); + TQuote[] array = ?(); + TQuote val = ((array != null) ? array.FirstOrDefault() : null); + if (val == null) + { + return false; + } + if (interval.To <= val.Time) + { + return false; + } + items = array.Where((TQuote P_0) => interval.Contains(P_0.Time)).ToArray(); + if (interval.From < val.Time) + { + remainingInterval = new Interval(interval.From, val.Time); + } + return true; + } + + private void ?(TQuote P_0) + { + if (??.Count <= 1) + { + return; + } + int num = 0; + foreach (TQuote item in ??) + { + if (P_0.Time - item.Time > ??) + { + num++; + continue; + } + break; + } + num--; + if (num >= 1) + { + num = Math.Max(??.Count - MaxCapacity, num); + ??.RemoveRange(0, num); + } + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.Limitation +{ + public class Limiter : IDisposable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal ? ?(Limit P_0) + { + return new ?(P_0); + } + } + + [CompilerGenerated] + private sealed class ? + { + public RequestType ??; + + internal bool ?(? P_0) + { + return P_0.?(??); + } + } + + private readonly ?[] ??; + + private readonly Timer ??; + + public Limiter(LimitationMetadata metadata) + { + ?? = metadata.Limits.Select((Limit P_0) => new ?(P_0)).ToArray(); + ?? = new Timer(?, null, TimeSpan.FromMilliseconds(100.0), TimeSpan.FromMilliseconds(100.0)); + } + + public void Wait(RequestType requestType, CancellationToken cancellationToken) + { + ?[] array = ??.Where((? P_0) => P_0.?(requestType)).ToArray(); + for (int num = 0; num < array.Length; num++) + { + array[num].?(cancellationToken); + } + } + + public void Dispose() + { + ??.Change(-1, -1); + ??.Dispose(); + } + + private void ?(object P_0) + { + ?[] array = ??; + for (int i = 0; i < array.Length; i++) + { + array[i].?(); + } + } + } +} +namespace ? +{ + internal class ? + { + private readonly ? ??; + + private readonly HashSet ??; + + public ?(Limit P_0) + { + ? obj; + if (P_0.Interval != LimitInterval.FloatingWindow) + { + ? ?2 = new ?(P_0.Period, P_0.Value); + obj = ?2; + } + else + { + ? ?2 = new ?(P_0.Period, P_0.Value); + obj = ?2; + } + ?? = obj; + HashSet hashSet = new HashSet(); + RequestType[] requestTypes = P_0.RequestTypes; + foreach (RequestType item in requestTypes) + { + hashSet.Add(item); + } + ?? = hashSet; + } + + public void ?(CancellationToken P_0) + { + ??.?(P_0); + } + + public void ?() + { + ??.?(); + } + + public bool ?(RequestType P_0) + { + return ??.Contains(P_0); + } + } + internal class ? : ? + { + private readonly Period ??; + + private readonly int ??; + + private DateTime ??; + + private readonly ManualResetEvent ??; + + private int ??; + + public ?(Period P_0, int P_1) + { + ?? = P_0; + ?? = P_1; + ?(); + ?? = new ManualResetEvent(initialState: false); + } + + public void ?(CancellationToken P_0) + { + if (?? < Interlocked.Increment(ref ??)) + { + ??.Reset(); + WaitHandle.WaitAny(new WaitHandle[2] { ??, P_0.WaitHandle }); + if (!P_0.IsCancellationRequested) + { + ?(P_0); + } + } + } + + public void ?() + { + if (!(Core.Instance.TimeUtils.DateTimeUtcNow < ??)) + { + ?(); + ?? = 0; + ??.Set(); + } + } + + private void ?() + { + ?? = Core.Instance.TimeUtils.DateTimeUtcNow.CeilingTo(??); + } + } + internal class ? : ? + { + private class ? + { + [CompilerGenerated] + private readonly DateTime ??; + + private readonly ManualResetEventSlim ??; + + public DateTime ExpirationTime + { + [CompilerGenerated] + get + { + return ??; + } + } + + public ?(DateTime P_0) + { + ?? = P_0; + ?? = new ManualResetEventSlim(); + } + + public void ?() + { + ??.Set(); + } + + public void ?(CancellationToken P_0) + { + ??.Wait(P_0); + } + } + + private readonly Period ??; + + private readonly int ??; + + private readonly Queue ??; + + private readonly object ??; + + public ?(Period P_0, int P_1) + { + ?? = P_0; + ?? = P_1; + ?? = new Queue(); + ?? = new object(); + } + + public void ?(CancellationToken P_0) + { + ? result; + lock (??) + { + if (??.Count < ??) + { + ??.Enqueue(new ?(Core.Instance.TimeUtils.DateTimeUtcNow + ??.Duration)); + return; + } + ??.TryPeek(out result); + } + if (result != null) + { + result.?(P_0); + if (!P_0.IsCancellationRequested) + { + ?(P_0); + } + } + } + + public void ?() + { + lock (??) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + ? result; + while (??.Count > 0 && ??.TryPeek(out result) && !(result.ExpirationTime > dateTimeUtcNow)) + { + ??.Dequeue(); + result.?(); + } + } + } + } + internal interface ? + { + void ?(CancellationToken P_0); + + void ?(); + } +} +namespace TradingPlatform.BusinessLayer.Utils.Extensions +{ + public static class GuidExtensions + { + public static string ToShortString(this Guid guid) + { + return Regex.Replace(Convert.ToBase64String(guid.ToByteArray()), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + } + public static class RulesManagerExtensions + { + public static bool IsAllowedBySymbol(this RulesManager rulesManager, Symbol symbol, string ruleName) + { + if (symbol != null) + { + if (rulesManager.IsAllowed(ruleName, symbol).Status != TradingOperationStatus.Allowed) + { + if (symbol != null) + { + return symbol.State == BusinessObjectState.Fake; + } + return false; + } + return true; + } + return false; + } + } + public static class TimeSpanExtensions + { + public static string ToReadable(this TimeSpan timespan) + { + if (timespan.Ticks <= 0) + { + return null; + } + if (timespan.Days > 365) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 2); + defaultInterpolatedStringHandler.AppendFormatted(timespan.Days / 365); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(timespan.Days % 365); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + if (timespan.Days > 0) + { + return timespan.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (timespan.Hours > 0) + { + return timespan.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (timespan.Minutes > 0) + { + return timespan.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return timespan.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + public static string ToReadableLong(this TimeSpan timespan) + { + if (timespan.Ticks <= 0) + { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + if (timespan.Days > 365) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder3 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(4, 2, stringBuilder2); + handler.AppendFormatted(timespan.Days / 365); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + handler.AppendFormatted(timespan.Days % 365); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder3.Append(ref handler); + } + if (timespan.Days > 0 && timespan.Days < 365) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder4 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); + handler.AppendFormatted(timespan.Days); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder4.Append(ref handler); + } + if (timespan.Hours > 0) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder5 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); + handler.AppendFormatted(timespan.Hours); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder5.Append(ref handler); + } + if (timespan.Minutes > 0) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder6 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); + handler.AppendFormatted(timespan.Minutes); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder6.Append(ref handler); + } + if (timespan.Seconds > 0) + { + StringBuilder stringBuilder2 = stringBuilder; + StringBuilder stringBuilder7 = stringBuilder2; + StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(1, 1, stringBuilder2); + handler.AppendFormatted(timespan.Seconds); + handler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder7.Append(ref handler); + } + return stringBuilder.ToString(); + } + + public static TimeSpan ConvertTimeZone(this TimeSpan timeSpan, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone) + { + return TimeZoneInfo.ConvertTime(new DateTime(DateTime.UtcNow.Date.Ticks + timeSpan.Ticks, DateTimeKind.Unspecified), sourceTimeZone, destinationTimeZone).TimeOfDay; + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.EqualityComparers +{ + public class BusinessObjectEqualityComparer : IEqualityComparer + { + public bool Equals(BusinessObject x, BusinessObject y) + { + if (x == y) + { + return true; + } + if (x == null) + { + return false; + } + if (y == null) + { + return false; + } + if (x.GetType() != y.GetType()) + { + return false; + } + if (x.ConnectionId == y.ConnectionId && x.State == y.State) + { + return x.UniqueId == y.UniqueId; + } + return false; + } + + public int GetHashCode(BusinessObject obj) + { + return (int)(((uint)(((obj.ConnectionId != null) ? obj.ConnectionId.GetHashCode() : 0) * 397) ^ (uint)obj.State) * 397) ^ ((obj.UniqueId != null) ? obj.UniqueId.GetHashCode() : 0); + } + } + public class ListEqualityComparer : IEqualityComparer> + { + private readonly IEqualityComparer ??; + + public ListEqualityComparer(IEqualityComparer itemEqualityComparer) + { + ?? = itemEqualityComparer; + } + + public bool Equals(IList x, IList y) + { + if (x == y) + { + return true; + } + if (x == null) + { + return false; + } + if (y == null) + { + return false; + } + if (x.GetType() != y.GetType()) + { + return false; + } + if (x.Count != y.Count) + { + return false; + } + for (int i = 0; i < x.Count; i++) + { + TItem x2 = x[i]; + TItem y2 = y[i]; + if (!??.Equals(x2, y2)) + { + return false; + } + } + return true; + } + + public int GetHashCode(IList list) + { + int num = list.Count.GetHashCode(); + foreach (TItem item in list) + { + num = (num * 397) ^ ??.GetHashCode(item); + } + return num; + } + } + public class PropertyInfoEqualityComparer : IEqualityComparer + { + public bool Equals(PropertyInfo x, PropertyInfo y) + { + if ((object)x == y) + { + return true; + } + if ((object)x == null) + { + return false; + } + if ((object)y == null) + { + return false; + } + if (x.GetType() != y.GetType()) + { + return false; + } + return object.Equals(x.Name, y.Name); + } + + public int GetHashCode(PropertyInfo obj) + { + return obj.Name.GetHashCode(); + } + } + public class SettingItemNameEqualityComparer : IEqualityComparer + { + public bool Equals(SettingItem x, SettingItem y) + { + if (x == y) + { + return true; + } + if (x == null) + { + return false; + } + if (y == null) + { + return false; + } + if (x.GetType() != y.GetType()) + { + return false; + } + return x.Name == y.Name; + } + + public int GetHashCode(SettingItem obj) + { + if (obj.Name == null) + { + return 0; + } + return obj.Name.GetHashCode(); + } + } + public class UniqueIdEqualityComparer : IEqualityComparer + { + public bool Equals(IUniqueID x, IUniqueID y) + { + if (x == y) + { + return true; + } + if (x == null) + { + return false; + } + if (y == null) + { + return false; + } + if (x.GetType() != y.GetType()) + { + return false; + } + return x.UniqueId == y.UniqueId; + } + + public int GetHashCode(IUniqueID obj) + { + if (obj.UniqueId == null) + { + return 0; + } + return obj.UniqueId.GetHashCode(); + } + } +} +namespace TradingPlatform.BusinessLayer.Utils.Comparers +{ + public class TimeInForceComparer : IComparer + { + public int Compare(TimeInForce x, TimeInForce y) + { + return ?(x) - ?(y); + } + + private static int ?(TimeInForce P_0) + { + return P_0 switch + { + TimeInForce.GTC => 0, + TimeInForce.Day => 1, + _ => 10, + }; + } + } +} +namespace TradingPlatform.BusinessLayer.Settings.OTP +{ + public class OTPHolder : IXElementSerialization, ICloneable + { + [CompilerGenerated] + private string ??; + + public Action Callback; + + public string OTPValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public void RequestOTP(string title, string text) + { + Core.Instance.RequestOTP(this, title, text); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OTPValue)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + OTPValue = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + } + + public object Clone() + { + return new OTPHolder + { + OTPValue = OTPValue + }; + } + } + [Serializable] + [DataContract] + public sealed class SettingItemOTP : SettingItem + { + public override SettingItemType Type => SettingItemType.OTP; + + [DataMember(Name = "Value")] + [ProtoMember(1, IsRequired = true)] + private OTPHolder ValueOTPHolder + { + get + { + return (OTPHolder)value; + } + set + { + value = oTPHolder; + } + } + + public SettingItemOTP() + { + } + + public SettingItemOTP(string name, OTPHolder value, int sortIndex = 0) + : base(name, value, sortIndex) + { + } + + private SettingItemOTP(SettingItemOTP P_0) + : base(P_0) + { + } + + [NotPublished] + public override SettingItem GetCopy() + { + return new SettingItemOTP(this); + } + + [NotPublished] + public static implicit operator OTPHolder(SettingItemOTP item) + { + return (OTPHolder)item.Value; + } + + [NotPublished] + protected override bool IsValueTypeValid(object value) + { + return value is OTPHolder; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + OTPHolder oTPHolder = new OTPHolder(); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + oTPHolder.FromXElement(xElement, deserializationInfo); + ValueOTPHolder = oTPHolder; + } + } + } +} +namespace TradingPlatform.BusinessLayer.Settings.Condition +{ + public sealed class ConditionData : IXElementSerialization + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal ConditionSet ?(ConditionSet P_0) + { + return new ConditionSet(P_0); + } + } + + [CompilerGenerated] + private List ??; + + /// + /// Gets or Sets the groups. + /// + public List ConditionGroups + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ConditionData() + { + ConditionGroups = new List(); + } + + public ConditionData(ConditionData conditions) + { + ConditionGroups = conditions.ConditionGroups.Select((ConditionSet P_0) => new ConditionSet(P_0)).ToList(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (ConditionSet conditionGroup in ConditionGroups) + { + xElement2.Add(conditionGroup.ToXElement()); + } + xElement.Add(xElement2); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement? xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + List list = new List(); + foreach (XElement item in xElement.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Elements()) + { + ConditionSet conditionSet = new ConditionSet(); + conditionSet.FromXElement(item, deserializationInfo); + list.Add(conditionSet); + } + ConditionGroups = list; + } + } + public sealed class ConditionItem : IXElementSerialization + { + [CompilerGenerated] + private ConditionOperandBase ??; + + [CompilerGenerated] + private ConditionOperandBase ??; + + [CompilerGenerated] + private TableConditionType ??; + + public ConditionOperandBase Operand1 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ConditionOperandBase Operand2 + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TableConditionType ConditionType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ConditionItem() + { + } + + public ConditionItem(ConditionItem conditionItem) + { + ConditionType = conditionItem.ConditionType; + Operand1 = conditionItem.Operand1?.Clone() as ConditionOperandBase; + Operand2 = conditionItem.Operand2?.Clone() as ConditionOperandBase; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ConditionType = (TableConditionType)Enum.Parse(typeof(TableConditionType), element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value.ToString()); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + XElement element2 = xElement.Elements().FirstOrDefault(); + Operand1 = ConditionOperandBase.CreateFromXml(element2, deserializationInfo); + Operand1.FromXElement(element2, deserializationInfo); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + XElement element3 = xElement2.Elements().FirstOrDefault(); + Operand2 = ConditionOperandBase.CreateFromXml(element3, deserializationInfo); + Operand2.FromXElement(element3, deserializationInfo); + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ConditionType.ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Operand1.ToXElement())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Operand2.ToXElement())); + return xElement; + } + } + public sealed class ConditionSet : IXElementSerialization + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal ConditionItem ?(ConditionItem P_0) + { + return new ConditionItem(P_0); + } + } + + [CompilerGenerated] + private List ??; + + public List ConditionItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ConditionSet() + { + ConditionItems = new List(); + } + + public ConditionSet(ConditionSet conditionSet) + { + ConditionItems = conditionSet.ConditionItems.Select((ConditionItem P_0) => new ConditionItem(P_0)).ToList(); + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + List list = new List(); + foreach (XElement item in element.Elements(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + ConditionItem conditionItem = new ConditionItem(); + conditionItem.FromXElement(item, deserializationInfo); + list.Add(conditionItem); + } + ConditionItems = list; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (ConditionItem conditionItem in ConditionItems) + { + xElement.Add(conditionItem.ToXElement()); + } + return xElement; + } + } + public abstract class ConditionOperandBase : IXElementSerialization, IComparable, ICloneable + { + protected const string XML_TYPE = "Type"; + + public abstract string Name { get; } + + public abstract ConditionOperandBaseType ValueType { get; } + + public static ConditionOperandBase CreateFromXml(XElement element, DeserializationInfo deserializationInfo) + { + string text = element?.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value; + if (text != null) + { + switch (text.Length) + { + case 19: + switch (text[14]) + { + case 't': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandCustomString(); + case 'y': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandCustomSymbol(); + } + break; + case 21: + switch (text[7]) + { + case 'C': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandCustomSelector(); + case 'O': + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandObjectProperty(); + } + break; + case 17: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandCustomDate(); + case 20: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandCustomAccount(); + case 29: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return new OperandObjectPropertySelector(); + } + } + return null; + } + + public abstract object Clone(); + + public int CompareTo(object obj) + { + return Name.CompareTo((obj as ConditionOperandBase)?.Name); + } + + public abstract void FromXElement(XElement element, DeserializationInfo deserializationInfo); + + public abstract XElement ToXElement(); + } + public sealed class OperandCustomString : ConditionOperandBase + { + [CompilerGenerated] + private string ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override ConditionOperandBaseType ValueType => ConditionOperandBaseType.String; + + public string Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OperandCustomString() + { + } + + public OperandCustomString(OperandCustomString operandCustomString) + { + Value = operandCustomString.Value; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Value = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.Value ?? string.Empty; + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Value)); + return xElement; + } + + public override object Clone() + { + return new OperandCustomString(this); + } + } + public sealed class OperandCustomDate : ConditionOperandBase + { + private const string ?? = "ddMMyyyy HH:mm:ss.ffffff"; + + [CompilerGenerated] + private DateTime ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override ConditionOperandBaseType ValueType => ConditionOperandBaseType.Date; + + public DateTime Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OperandCustomDate() + { + } + + public OperandCustomDate(OperandCustomDate operandCustomDate) + { + Value = operandCustomDate.Value; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + Value = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())?.ToDateTime(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? default(DateTime); + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Value.ToString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CultureInfo.InvariantCulture))); + return xElement; + } + + public override object Clone() + { + return new OperandCustomDate(this); + } + } + public sealed class OperandObjectProperty : ConditionOperandBase + { + private string ??; + + private ConditionOperandBaseType ??; + + public override string Name => ??; + + public override ConditionOperandBaseType ValueType => ??; + + public OperandObjectProperty() + { + } + + public OperandObjectProperty(string name, ConditionOperandBaseType valueType) + { + ?? = name; + ?? = valueType; + } + + public OperandObjectProperty(OperandObjectProperty operandCustomDate) + { + ?? = operandCustomDate.Name; + ?? = operandCustomDate.ValueType; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ?? = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + ?? = (ConditionOperandBaseType)element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).ToInt(); + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)ValueType)); + return xElement; + } + + public override object Clone() + { + return new OperandObjectProperty(this); + } + } + public sealed class OperandCustomSymbol : ConditionOperandBase + { + [CompilerGenerated] + private Symbol ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override ConditionOperandBaseType ValueType => ConditionOperandBaseType.Symbol; + + public Symbol Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OperandCustomSymbol() + { + } + + public OperandCustomSymbol(OperandCustomSymbol operandCustomDate) + { + Value = operandCustomDate.Value; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + SymbolInfo empty = SymbolInfo.Empty; + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + empty.FromXElement(xElement, deserializationInfo); + if (!(empty == BusinessObjectInfo.Empty) && !(empty == SymbolInfo.Empty)) + { + Value = Core.Instance.GetSymbol(empty); + } + } + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add((Value?.CreateInfo() ?? BusinessObjectInfo.Empty).ToXElement()); + return xElement; + } + + public override object Clone() + { + return new OperandCustomSymbol(this); + } + } + public sealed class OperandCustomAccount : ConditionOperandBase + { + [CompilerGenerated] + private Account ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override ConditionOperandBaseType ValueType => ConditionOperandBaseType.Account; + + public Account Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OperandCustomAccount() + { + } + + public OperandCustomAccount(OperandCustomAccount operandCustomDate) + { + Value = operandCustomDate.Value; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + SymbolInfo empty = SymbolInfo.Empty; + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + empty.FromXElement(xElement, deserializationInfo); + if (!(empty == BusinessObjectInfo.Empty) && !(empty == SymbolInfo.Empty)) + { + Value = Core.Instance.GetAccount(empty); + } + } + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add((Value?.CreateInfo() ?? BusinessObjectInfo.Empty).ToXElement()); + return xElement; + } + + public override object Clone() + { + return new OperandCustomAccount(this); + } + } + public sealed class OperandCustomSelector : ConditionOperandBase + { + [CompilerGenerated] + private SelectItem ??; + + public override string Name => 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public override ConditionOperandBaseType ValueType => ConditionOperandBaseType.Selector; + + public SelectItem SelectedItem + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OperandCustomSelector() + { + } + + public OperandCustomSelector(OperandCustomSelector operandCustomSelector) + { + SelectedItem = operandCustomSelector.SelectedItem; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + string value = xElement.Value; + if (int.TryParse(value, out var result)) + { + SelectedItem = new SelectItem(string.Empty, result); + } + else + { + SelectedItem = new SelectItem(string.Empty, value); + } + } + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + string content = string.Empty; + if (SelectedItem == null) + { + content = string.Empty; + } + else if (SelectedItem.Value is int || SelectedItem.Value is Enum) + { + content = ((int)(object)SelectedItem.Value).ToString(); + } + else if (SelectedItem.Value != null) + { + content = SelectedItem.Value.ToString(); + } + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), content)); + return xElement; + } + + public override object Clone() + { + return new OperandCustomSelector(this); + } + } + public sealed class OperandObjectPropertySelector : ConditionOperandBase + { + private string ??; + + public List Items; + + public override string Name => ??; + + public override ConditionOperandBaseType ValueType => ConditionOperandBaseType.Selector; + + public OperandObjectPropertySelector() + { + } + + public OperandObjectPropertySelector(string name, List items) + { + ?? = name; + Items = items; + } + + public OperandObjectPropertySelector(OperandObjectPropertySelector operandCustomDate) + { + ?? = operandCustomDate.Name; + Items = operandCustomDate.Items; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ?? = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value; + } + + public override XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GetType().Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + return xElement; + } + + public override object Clone() + { + return new OperandObjectPropertySelector(this); + } + } + public enum ConditionOperandBaseType + { + Numeric, + Date, + String, + Symbol, + Account, + Selector + } + [Serializable] + [DataContract] + public sealed class SettingItemCondition : SettingItem + { + [CompilerGenerated] + private List ??; + + public override SettingItemType Type => SettingItemType.Condition; + + public List AvailableOperands + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + private ConditionData ValueConditionData + { + get + { + return Value as ConditionData; + } + set + { + Value = conditionData; + } + } + + public SettingItemCondition() + { + } + + public SettingItemCondition(string name, object value, List operands, int sortIndex = 0) + : base(name, value, sortIndex) + { + AvailableOperands = operands; + } + + private SettingItemCondition(SettingItemCondition P_0) + : base(P_0) + { + AvailableOperands = new List(P_0.AvailableOperands); + } + + public override SettingItem GetCopy() + { + return new SettingItemCondition(this); + } + + protected override bool IsValueTypeValid(object value) + { + return value is ConditionData; + } + + protected override void ValueFromXElement(XElement element, DeserializationInfo deserializationInfo) + { + ConditionData conditionData = new ConditionData(); + conditionData.FromXElement(element, deserializationInfo); + value = conditionData; + } + } +} +namespace TradingPlatform.BusinessLayer.Settings.Comparers +{ + public class SettingItemNameComparer : IEqualityComparer + { + public bool Equals(SettingItem x, SettingItem y) + { + if (x == y) + { + return true; + } + if (x == null) + { + return false; + } + if (y == null) + { + return false; + } + if (x.GetType() != y.GetType()) + { + return false; + } + return string.Equals(x.Name, y.Name, StringComparison.InvariantCulture); + } + + public int GetHashCode(SettingItem obj) + { + if (obj.Name == null) + { + return 0; + } + return StringComparer.InvariantCulture.GetHashCode(obj.Name); + } + } +} +namespace TradingPlatform.BusinessLayer.Native +{ + /// + /// Specifies constants that define which mouse button was pressed. + /// + [Flags] + public enum NativeMouseButtons + { + /// + /// No mouse button was pressed. + /// + None = 0, + /// + /// The left mouse button was pressed. + /// + Left = 0x100000, + /// + /// The right mouse button was pressed. + /// + Right = 0x200000, + /// + /// The middle mouse button was pressed. + /// + Middle = 0x400000, + /// + /// The first XButton was pressed. + /// + XButton1 = 0x800000, + /// + /// The second XButton was pressed. + /// + XButton2 = 0x1000000 + } + public class NativeMouseEventArgs + { + [CompilerGenerated] + private readonly NativeMouseButtons ??; + + [CompilerGenerated] + private readonly int ??; + + [CompilerGenerated] + private readonly int ??; + + [CompilerGenerated] + private readonly int ??; + + [CompilerGenerated] + private readonly int ??; + + [CompilerGenerated] + private bool ??; + + public NativeMouseButtons Button + { + [CompilerGenerated] + get + { + return ??; + } + } + + public int Clicks + { + [CompilerGenerated] + get + { + return ??; + } + } + + public int X + { + [CompilerGenerated] + get + { + return ??; + } + } + + public int Y + { + [CompilerGenerated] + get + { + return ??; + } + } + + public int Delta + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Point Location => new Point(X, Y); + + /// + /// Gets or sets a value indicating whether the event was handled. + /// true to bypass the control's default handling; otherwise, false to also pass the event along to the default control handler. + /// + public bool Handled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public NativeMouseEventArgs(NativeMouseButtons button, int clicks, int x, int y, int delta) + { + ?? = x; + ?? = y; + ?? = clicks; + ?? = button; + ?? = delta; + } + } +} +namespace TradingPlatform.BusinessLayer.Modules +{ + public abstract class OrderPlacingStrategy : ExecutionEntity + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(SettingItem P_0) + { + return P_0.VisibilityMode != VisibilityMode.Hidden; + } + + internal string ?(SettingItem P_0) + { + return P_0.ToString(); + } + } + + [CompilerGenerated] + private sealed class ? + { + public DateTime ??; + + public DateTime ??; + + internal bool ?(LoggerEvent P_0) + { + return P_0.Date > ??; + } + + internal bool ?(LoggerEvent P_0) + { + return P_0.Date < ??; + } + } + + private OrderPlacingStrategyState ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + public readonly DateTime CreationTime; + + private readonly List ??; + + [CompilerGenerated] + private PlaceOrderRequestParameters ??; + + public OrderPlacingStrategyState State + { + get + { + return ??; + } + private set + { + ?? = orderPlacingStrategyState; + ???.Invoke(??); + } + } + + public PlaceOrderRequestParameters LastPlaceRequest + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public event Action StateChanged + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + /// + /// Event occurred when write a new log + /// + public event Action NewLog + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public OrderPlacingStrategy() + { + CreationTime = Core.Instance.TimeUtils.DateTimeUtcNow; + ?? = new List(); + } + + public TradingOperationResult PlaceOrder(PlaceOrderRequestParameters placeOrderRequest) + { + if (State != OrderPlacingStrategyState.Ready) + { + return TradingOperationResult.CreateError(placeOrderRequest.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + try + { + State = OrderPlacingStrategyState.Processing; + LastPlaceRequest = placeOrderRequest; + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + OnPlaceOrder(placeOrderRequest.Clone() as PlaceOrderRequestParameters); + } + catch (TaskCanceledException) + { + } + catch (OperationCanceledException) + { + } + catch (AggregateException ex3) when (ex3.InnerException is TaskCanceledException) + { + } + catch (Exception exception) + { + Exception ex4 = exception.GetInnerExceptionsRecursive().Last(); + string text = base.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex4.Message; + Log(text, StrategyLoggingLevel.Error); + State = OrderPlacingStrategyState.Error; + placeOrderRequest.Symbol.ConnectionCache.Push(MessageDealTicket.CreateRefuseDealTicket(text)); + return TradingOperationResult.CreateError(placeOrderRequest.RequestId, text); + } + finally + { + if (State == OrderPlacingStrategyState.Processing) + { + State = OrderPlacingStrategyState.Finished; + Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + return TradingOperationResult.CreateSuccess(placeOrderRequest.RequestId); + } + + public void Cancel() + { + if (State != OrderPlacingStrategyState.Processing) + { + return; + } + try + { + State = OrderPlacingStrategyState.Cancelling; + OnCancel(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + State = OrderPlacingStrategyState.Cancelled; + } + } + + public void Remove() + { + Core.Instance.OrderPlacingStrategies.?(this); + } + + public override void Dispose() + { + if (State == OrderPlacingStrategyState.Processing) + { + Cancel(); + } + ??.Clear(); + base.Dispose(); + } + + public virtual string FormatParameters() + { + return string.Join(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), from P_0 in Settings + where P_0.VisibilityMode != VisibilityMode.Hidden + select P_0.ToString()); + } + + /// + /// Get logs from the strategy for specified date range + /// + /// + /// + /// + public LoggerEvent[] GetLogs(DateTime from, DateTime to) + { + return (from P_0 in ?? + where P_0.Date > @from + where P_0.Date < to + select P_0).ToArray(); + } + + protected abstract void OnPlaceOrder(PlaceOrderRequestParameters placeOrderRequest); + + protected abstract void OnCancel(); + + /// + /// Write log message + /// + /// + /// + protected void Log(string message, StrategyLoggingLevel level = StrategyLoggingLevel.Info) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + LoggingLevel type = LoggingLevel.System; + switch (level) + { + case StrategyLoggingLevel.Trading: + type = LoggingLevel.Trading; + break; + case StrategyLoggingLevel.Error: + type = LoggingLevel.Error; + break; + } + LoggerEvent loggerEvent = new LoggerEvent + { + Date = dateTimeUtcNow, + Event = message, + Type = type + }; + ??.Add(loggerEvent); + ???.Invoke(loggerEvent); + } + } + public enum OrderPlacingStrategyState + { + Ready, + Processing, + Finished, + Cancelling, + Cancelled, + Error + } +} +namespace TradingPlatform.BusinessLayer.Modules.PlaceOrderStrategies +{ + public sealed class OrderPlacingStrategyInfo : ScriptInfo, IComparable + { + [CompilerGenerated] + private string ??; + + public string ObsoleteText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + internal OrderPlacingStrategyInfo(ConstructorInfo P_0, ScriptCreationType P_1, string P_2, string P_3) + : base(P_0, P_1, P_2, P_3) + { + } + + protected override void Initialize(string relativePath, string assemblyName) + { + using OrderPlacingStrategy orderPlacingStrategy = ctor.Invoke(null) as OrderPlacingStrategy; + base.Name = orderPlacingStrategy.Name; + base.Description = orderPlacingStrategy.Description; + base.Version = orderPlacingStrategy.Version; + base.Settings = orderPlacingStrategy.Settings as List; + base.Key = new ScriptKey(base.ScriptCreationType, relativePath, assemblyName, base.Name); + if (orderPlacingStrategy.GetType().GetCustomAttributes(typeof(ObsoleteAttribute), inherit: true).FirstOrDefault() is ObsoleteAttribute obsoleteAttribute) + { + ObsoleteText = obsoleteAttribute.Message; + } + } + + internal OrderPlacingStrategy ?() + { + OrderPlacingStrategy orderPlacingStrategy = ctor?.Invoke(null) as OrderPlacingStrategy; + if (orderPlacingStrategy != null) + { + orderPlacingStrategy.Key = base.Key; + } + return orderPlacingStrategy; + } + + public int CompareTo(object obj) + { + if (!(obj is OrderPlacingStrategyInfo orderPlacingStrategyInfo)) + { + return 0; + } + return string.Compare(base.Key.ToString(), orderPlacingStrategyInfo.Key.ToString(), StringComparison.Ordinal); + } + } +} +namespace TradingPlatform.BusinessLayer.LocalOrders +{ + public class LocalOrder : BindableEntity, IOrder, ITradingObject, IUniqueID, IDisposable + { + public class OrderTypeRules + { + private readonly IDictionary ??; + + private ? ??; + + internal OrderTypeRules() + { + ?? = new Dictionary(); + } + + public void SetRule(string ruleName, T value) + { + ? ? = new ?(ruleName, value); + ??[ruleName] = ?; + ?(?); + } + + internal void ?(? P_0) + { + ?? = P_0; + foreach (Rule value in ??.Values) + { + ?(value); + } + } + + private void ?(Rule P_0) + { + if (?? != null) + { + if (??.Rules.?(P_0.Name)) + { + ??.Rules[P_0.Name] = P_0; + } + else + { + ??.Rules.?(P_0.Name, P_0); + } + } + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private readonly Account ??; + + private readonly Symbol ??; + + [CompilerGenerated] + private readonly Side ??; + + private readonly OrderType ??; + + [CompilerGenerated] + private TimeInForce ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private OrderStatus ??; + + [CompilerGenerated] + private DateTime ??; + + private double ??; + + private double ??; + + private double ??; + + private double ??; + + private string ??; + + [CompilerGenerated] + private AdditionalInfoCollection ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private readonly OrderTypeRules ??; + + public string UniqueId => Id; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public Symbol Symbol + { + get + { + return ??; + } + init + { + ?? = value; + if (OrderType != null) + { + OrderType.ConnectionId = Symbol.ConnectionId; + } + } + } + + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public OrderType OrderType + { + get + { + return ??; + } + init + { + ?? = value; + if (OrderType != null) + { + OrderType.ConnectionId = Symbol?.ConnectionId; + Rules.?(OrderType); + } + } + } + + public string OrderTypeId => OrderType?.Id; + + public TimeInForce TimeInForce + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string GroupId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public OrderStatus Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = orderStatus; + } + } + + public DateTime LastUpdateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public double TotalQuantity + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public double Price + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public double TriggerPrice + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public double TrailOffset + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public string Comment + { + get + { + return ??; + } + set + { + SetValue(ref ??, value, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public string PositionId => null; + + public SlTpHolder StopLoss => null; + + public SlTpHolder TakeProfit => null; + + public SlTpHolder[] StopLossItems => Array.Empty(); + + public SlTpHolder[] TakeProfitItems => Array.Empty(); + + public string ConnectionId => Symbol?.ConnectionId; + + public DateTime ExpirationTime => default(DateTime); + + public BusinessObjectState State => BusinessObjectState.Normal; + + public double RemainingQuantity => TotalQuantity; + + public double FilledQuantity => 0.0; + + public string OriginalStatus => null; + + public double AverageFillPrice => double.NaN; + + public AdditionalInfoCollection AdditionalInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OrderTypeRules Rules + { + [CompilerGenerated] + get + { + return ??; + } + } + + public event Action Updated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public LocalOrder() + { + ?? = new OrderTypeRules(); + base.PropertyChanged += ?; + } + + public void Dispose() + { + base.PropertyChanged -= ?; + } + + private void ?(object P_0, PropertyChangedEventArgs P_1) + { + LastUpdateTime = Core.Instance.TimeUtils.DateTimeUtcNow; + ?(); + } + + public override string ToString() + { + double price = (double.IsNaN(TriggerPrice) ? Price : TriggerPrice); + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 7); + defaultInterpolatedStringHandler.AppendFormatted(Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderType.Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TimeInForce.Format(ExpirationTime)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Symbol.FormatQuantity(TotalQuantity)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Symbol); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Symbol.FormatPrice(price)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Account); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + internal void ?(ModifyOrderRequestParameters P_0) + { + TimeInForce = P_0.TimeInForce; + ?? = P_0.Quantity; + ?? = P_0.Price; + ?? = P_0.TriggerPrice; + ?? = P_0.TrailOffset; + ?? = P_0.Comment; + AdditionalInfo?.?(P_0.AdditionalParameters); + ?(); + } + + private void ?() + { + ???.Invoke(this); + } + } + public class LocalOrderEventArgs : EntityLifecycleEventArgs + { + [CompilerGenerated] + private readonly LocalOrder ??; + + public LocalOrder LocalOrder + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } + public class LocalOrdersManager : IDisposable, IEnumerable, IEnumerable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, string> ??; + + internal string ?(KeyValuePair P_0) + { + return P_0.Key; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Connection ??; + + internal bool ?(KeyValuePair P_0) + { + return P_0.Value.ConnectionId == ??.Id; + } + } + + private readonly IDictionary ??; + + private readonly object ??; + + [CompilerGenerated] + private EventHandler ??; + + public event EventHandler Updated + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public LocalOrdersManager() + { + ?? = new Dictionary(); + ?? = new object(); + } + + public void Initialize() + { + Core.Instance.Connections.ConnectionStateChanged += ?; + } + + public string AddOrder(LocalOrder localOrder) + { + localOrder.Id = Guid.NewGuid().ToShortString(); + lock (??) + { + ??.Add(localOrder.Id, localOrder); + } + localOrder.Updated += ?; + ?(localOrder, EntityLifecycle.Created); + return localOrder.Id; + } + + public bool RemoveOrder(string orderId) + { + LocalOrder value; + lock (??) + { + if (??.TryGetValue(orderId, out value)) + { + ??.Remove(orderId); + } + } + if (value == null) + { + return false; + } + value.Updated -= ?; + value.Dispose(); + ?(value, EntityLifecycle.Removed); + return true; + } + + public bool TryHandleTradingOperationRequest(TradingRequestParameters requestParameters, out TradingOperationResult result) + { + result = null; + if (!(requestParameters is ModifyOrderRequestParameters modifyOrderRequestParameters)) + { + if (requestParameters is CancelOrderRequestParameters cancelOrderRequestParameters) + { + return ?(cancelOrderRequestParameters, out result); + } + return false; + } + return ?(modifyOrderRequestParameters, out result); + } + + private bool ?(ModifyOrderRequestParameters P_0, out TradingOperationResult P_1) + { + P_1 = null; + if (!?(P_0.OrderId, out var localOrder)) + { + return false; + } + localOrder.?(P_0); + P_1 = TradingOperationResult.CreateSuccess(P_0.RequestId); + return true; + } + + private bool ?(CancelOrderRequestParameters P_0, out TradingOperationResult P_1) + { + bool flag = RemoveOrder(P_0.OrderId); + P_1 = (flag ? TradingOperationResult.CreateSuccess(P_0.RequestId) : TradingOperationResult.CreateError(P_0.RequestId, string.Empty)); + return flag; + } + + public void Dispose() + { + Core.Instance.Connections.ConnectionStateChanged -= ?; + lock (??) + { + foreach (LocalOrder value in ??.Values) + { + value.Updated -= ?; + } + ??.Clear(); + } + } + + private void ?(object P_0, ConnectionStateChangedEventArgs P_1) + { + if (P_1.NewState != ConnectionState.Disconnected && P_1.NewState != ConnectionState.ConnectionLost) + { + return; + } + Connection ?? = P_0 as Connection; + if (?? == null) + { + return; + } + List list; + lock (??) + { + list = (from keyValuePair in ?? + where keyValuePair.Value.ConnectionId == ??.Id + select keyValuePair.Key).ToList(); + } + foreach (string item in list) + { + RemoveOrder(item); + } + } + + private bool ?(string P_0, out LocalOrder P_1) + { + P_1 = null; + lock (??) + { + ??.TryGetValue(P_0, out P_1); + } + return P_1 != null; + } + + private void ?(IOrder P_0) + { + if (P_0 is LocalOrder localOrder) + { + ?(localOrder, EntityLifecycle.Changed); + } + } + + private void ?(LocalOrder P_0, EntityLifecycle P_1) + { + ???.InvokeSafely(this, new LocalOrderEventArgs + { + LocalOrder = P_0, + Lifecycle = P_1 + }); + } + + public IEnumerator GetEnumerator() + { + lock (??) + { + return ??.Values.GetEnumerator(); + } + } + + private IEnumerator ?() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + //ILSpy generated this explicit interface implementation from .override directive in ? + return this.?(); + } + } +} +namespace TradingPlatform.BusinessLayer.Licence +{ + public sealed class LicenceItem + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly DateTime ??; + + [CompilerGenerated] + private readonly DateTime ??; + + public string LicenceKey + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public string Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public DateTime StartDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public DateTime EndDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } +} +namespace ? +{ + internal sealed class ? : JsonConverter + { + private const string ?? = "StartDateTicks"; + + private const string ?? = "EndDateTicks"; + + public override LicenceItem Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) + { + string text = null; + string licenceKey = string.Empty; + string value = null; + DateTime startDate = default(DateTime); + DateTime endDate = default(DateTime); + while (reader.Read()) + { + JsonTokenType tokenType = reader.TokenType; + switch (tokenType) + { + case JsonTokenType.EndObject: + return new LicenceItem + { + LicenceKey = licenceKey, + Value = value, + StartDate = startDate, + EndDate = endDate + }; + case JsonTokenType.PropertyName: + text = reader.GetString(); + break; + case JsonTokenType.String: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + value = reader.GetString(); + } + } + else + { + licenceKey = reader.GetString(); + } + break; + case JsonTokenType.Number: + if (!(text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + if (text == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + endDate = new DateTime(reader.GetInt64(), DateTimeKind.Utc); + } + } + else + { + startDate = new DateTime(reader.GetInt64(), DateTimeKind.Utc); + } + break; + default: + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(20, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(tokenType); + throw new ArgumentOutOfRangeException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + case JsonTokenType.None: + case JsonTokenType.StartObject: + case JsonTokenType.StartArray: + case JsonTokenType.EndArray: + case JsonTokenType.Comment: + case JsonTokenType.True: + case JsonTokenType.False: + case JsonTokenType.Null: + break; + } + } + return null; + } + + public override void Write(Utf8JsonWriter writer, LicenceItem value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value.LicenceKey); + writer.WriteString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value.LicenceKey); + writer.WriteNumber(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value.StartDate.Ticks); + writer.WriteNumber(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value.EndDate.Ticks); + writer.WriteEndObject(); + } + } +} +namespace TradingPlatform.BusinessLayer.Licence +{ + /// + /// Constants for licence keys + /// + public static class CoreLicenceKeys + { + public const string BASIC_PACKAGE = "BASIC_PACKAGE"; + + public const string PREMIUM_PACKAGE = "PREMIUM_PACKAGE"; + + public const string PREMIUM_PLUS_PACKAGE = "PREMIUM_PLUS_PACKAGE"; + + public const string ALL_IN_ONE_PACKAGE = "ALLINONE_PACKAGE"; + + public const string CRYPTO_PACKAGE = "CRYPTO_PACKAGE"; + + public const string CRYPTO_INDIA_PACKAGE = "CRYPTO_INDIA_PACKAGE"; + + public const string VOLUMEANALYSIS_PACKAGE = "VOLUMEANALYSIS_PACKAGE"; + + public const string POWERTRADES_PACKAGE = "POWERTRADES_PACKAGE"; + + public const string DOMSURFACE_PACKAGE = "DOMSURFACE_PACKAGE"; + + public const string ORDERFLOW_PACKAGE = "ORDERFLOW_PACKAGE"; + + public const string TPOCHART_PACKAGE = "TPOCHART_PACKAGE"; + + public const string MULTI_ASSET_PACKAGE = "MULTI_ASSET_PACKAGE"; + + public const string OPTIONS_PACKAGE = "OPTIONS_PACKAGE"; + + public const string CUSTOMER = "CUSTOMER"; + + public const string PROP_LICENSE = "PROP_LICENSE"; + + public const string MIRROR_TRADING = "MIRROR_TRADING"; + + public const string TRADING_SIGNAL_PACKAGE = "TRADING_SIGNAL_PACKAGE"; + + public const string EXTENDED_HISTOR?_PACKAGE = "EXTENDED_HISTOR?_PACKAGE "; + + public const string QUANTOWER_LITE = "QUANTOWER_LITE"; + + public const string QUANTOWER_ADVANCED_EQUITY = "QUANTOWER_ADVANCED_EQUITY"; + + public const string QUANTOWER_ADVANCED_INDICES = "QUANTOWER_ADVANCED_INDICES"; + + public const string QUANTOWER_ADVANCED_COMMODITY = "QUANTOWER_ADVANCED_COMMODITY"; + + public const string QUANTOWER_ADVANCED_EQUITY_COMMODITIES = "QUANTOWER_ADVANCED_EQUITY_COMMODITIES"; + + public const string TRUEDATA_NSECD_PACKAGE = "TRUEDATA_NSECD_PACKAGE"; + + public const string TRUEDATA_NSECM_PACKAGE = "TRUEDATA_NSECM_PACKAGE"; + + public const string TRUEDATA_NSEFO_PACKAGE = "TRUEDATA_NSEFO_PACKAGE"; + + public const string TRUEDATA_MCX_PACKAGE = "TRUEDATA_MCX_PACKAGE"; + + public const string TRUEDATA_VELOCITY = "TRUEDATA_VELOCITY"; + + public const string CEDROMARKETDATA_PACKAGE = "CEDROMARKETDATA_PACKAGE"; + + public static string GetRuleDescription(string ruleId) + { + if (ruleId != null) + { + switch (ruleId.Length) + { + case 14: + { + char c = ruleId[0]; + if (c != 'C') + { + switch (c) + { + case 'M': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 'Q': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + break; + } + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + goto IL_0363; + } + case 20: + { + char c = ruleId[0]; + if (c != 'C') + { + if (c != 'P' || !(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + goto IL_0363; + } + case 19: + switch (ruleId[0]) + { + case 'M': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 'P': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + break; + case 15: + switch (ruleId[0]) + { + case 'P': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 'O': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + break; + case 16: + switch (ruleId[0]) + { + case 'A': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 'T': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + break; + case 22: + switch (ruleId[0]) + { + case 'V': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 'T': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + break; + case 17: + switch (ruleId[0]) + { + case 'O': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 'T': + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + break; + case 13: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 18: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 8: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 12: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 25: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 26: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 28: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 37: + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 23: + { + if (!(ruleId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + IL_0363: + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + return ruleId; + } + } + /// + /// User licences info store + /// + public sealed class LicencesManager : IDisposable, ICustomizable + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(LicenceItem P_0) + { + return P_0.LicenceKey != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + + internal string ?(LicenceItem P_0) + { + return P_0.LicenceKey; + } + + internal bool ?(LicenceItem P_0) + { + return P_0.EndDate >= Core.Instance.TimeUtils.DateTimeUtcNow; + } + } + + private const string ?? = "https://gateway.accounts.quantower.com/"; + + private const string ?? = "refresh_token"; + + [CompilerGenerated] + private EventHandler ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + private ConnectionState ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private UserInfo ??; + + [CompilerGenerated] + private string ??; + + private IDictionary ??; + + private HttpClient ??; + + private HttpClient ??; + + private Timer ??; + + private string ??; + + private string ??; + + private string ??; + + private string ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + private LicenceItem ??; + + /// + /// Current state of connection to licence server + /// + public ConnectionState State + { + get + { + return ??; + } + private set + { + if (?? != connectionState) + { + LicenseManagerEventArgs e = new LicenseManagerEventArgs(??, connectionState); + ?? = connectionState; + ???.InvokeSafely(this, e); + } + } + } + + public string LastErrorText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + /// + /// Current connected user info + /// + public UserInfo CurrentUser + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = userInfo; + } + } + + public string AccessToken + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public IList Settings + { + get + { + return new List + { + new SettingItemPassword(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new PasswordHolder(??, SavePassword: true, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) + }; + } + set + { + foreach (SettingItem item in value) + { + if (!(item.Name == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + continue; + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + if (!string.IsNullOrEmpty(?? = (item.Value as PasswordHolder)?.Password)) + { + Task.Factory.StartNew(delegate + { + if (State == ConnectionState.Disconnected && !string.IsNullOrEmpty(??)) + { + State = ConnectionState.Connecting; + ?(); + } + }).Wait(); + } + else if (item.Value is PasswordHolder { FailedToRestorePassword: not false }) + { + LastErrorText = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Error); + State = ConnectionState.Disconnected; + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + } + } + + /// + /// All active licences that user have + /// + public IEnumerable AllLicenceItems => ??.Values; + + public event EventHandler StateChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public event Action LicenceRulesUpdated + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + public event Action LicenceCheckError + { + [CompilerGenerated] + add + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Combine(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + [CompilerGenerated] + remove + { + Action action = ??; + Action action2; + do + { + action2 = action; + Action value2 = (Action)Delegate.Remove(action2, value); + action = Interlocked.CompareExchange(ref ??, value2, action2); + } + while ((object)action != action2); + } + } + + internal LicencesManager() + { + ?? = ConnectionState.Disconnected; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + ?? = new LicenceItem + { + LicenceKey = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + StartDate = DateTime.UtcNow.AddDays(-10.0), + EndDate = DateTime.UtcNow.AddYears(100) + }; + } + + internal void ?() + { + ?? = new ReadOnlyDictionary(new Dictionary()); + ?? = new HttpClient(new HttpClientHandler + { + ServerCertificateCustomValidationCallback = ? + }); + ?? = new HttpClient(new HttpClientHandler + { + ServerCertificateCustomValidationCallback = ? + }); + } + + public void Dispose() + { + ?(); + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + } + + public void ConnectToAuthServer() + { + if (State != ConnectionState.Disconnected) + { + return; + } + LastErrorText = null; + try + { + ?? = ?(); + if (string.IsNullOrEmpty(??)) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + AccessToken = string.Empty; + ?? = string.Empty; + ?? = string.Empty; + OidcClient oidcClient = ?(); + LoginRequest request = new LoginRequest + { + BrowserDisplayMode = DisplayMode.Visible, + BrowserTimeout = 300 + }; + LoginResult result = oidcClient.LoginAsync(request).Result; + State = ConnectionState.Connecting; + AccessToken = result.AccessToken; + ?? = result.RefreshToken; + ?? = result.IdentityToken; + if (result.IsError) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + result.Error, LoggingLevel.Error); + State = ConnectionState.Disconnected; + return; + } + UserInfoResult result2 = oidcClient.GetUserInfoAsync(AccessToken).Result; + if (result2.IsError) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + result2.Error, LoggingLevel.Error); + } + else + { + CurrentUser = new UserInfo(result2.Claims); + } + ?? = ?(); + if (string.IsNullOrEmpty(??)) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?(); + ?(); + State = ConnectionState.Connected; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + LastErrorText = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.Message; + State = ConnectionState.Disconnected; + } + } + + public void Disconnect() + { + if (State != ConnectionState.Connected) + { + return; + } + State = ConnectionState.Disconnecting; + try + { + OidcClient oidcClient = ?(); + LogoutRequest request = new LogoutRequest + { + IdTokenHint = ?? + }; + oidcClient.LogoutAsync(request).Wait(); + ?(); + ?? = null; + LastErrorText = null; + State = ConnectionState.Disconnected; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + State = ConnectionState.Disconnected; + } + } + + /// + /// Check that user have licence + /// + public LicenceItem GetLicenceRuleItem(string itemKey) + { + if (Encryptor.UnicDeviceId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || Encryptor.UnicDeviceId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || Encryptor.UnicDeviceId == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + return ??; + } + ??.TryGetValue(itemKey, out var value); + return value; + } + + public void OnLicenceCheckError(string errorText, string licenceItemKey) + { + ??.InvokeSafely(errorText, licenceItemKey); + } + + private void ?() + { + if (?? == null) + { + ?? = new Timer(?); + ??.Change(TimeSpan.Zero, TimeSpan.FromMinutes(2.0)); + } + } + + private void ?(object P_0) + { + try + { + ?(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + private void ?() + { + ImmutableDictionary immutableDictionary = (from P_0 in ?() + where P_0.LicenceKey != 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + select P_0).ToImmutableDictionary((LicenceItem P_0) => P_0.LicenceKey); + if (?(??, immutableDictionary)) + { + ?? = new ReadOnlyDictionary(immutableDictionary); + ???.Invoke(); + } + } + + private void ?() + { + LastErrorText = null; + try + { + AccessToken = string.Empty; + ?? = string.Empty; + ?? = ?(); + OidcClient oidcClient = ?(); + RefreshTokenResult result = oidcClient.RefreshTokenAsync(??).Result; + if (result.IsError) + { + LastErrorText = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + result.Error, LoggingLevel.Error); + ?(); + State = ConnectionState.Disconnected; + return; + } + AccessToken = result.AccessToken; + ?? = result.RefreshToken; + ?? = result.IdentityToken; + UserInfoResult result2 = oidcClient.GetUserInfoAsync(AccessToken).Result; + if (result2.IsError) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + result2.Error, LoggingLevel.Error); + } + else + { + CurrentUser = new UserInfo(result2.Claims); + } + ?? = ?(); + ?(); + ?(); + State = ConnectionState.Connected; + } + catch (Exception ex) + { + WebException ex2 = ex.GetInnerExceptionsRecursive().OfType().FirstOrDefault(); + if (ex2 != null && ex2.Status == WebExceptionStatus.ConnectFailure) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + else + { + ?(); + } + LastErrorText = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.Message; + Core.Instance.Loggers.Log(ex); + State = ConnectionState.Disconnected; + } + } + + private string ?() + { + try + { + UriBuilder uriBuilder = new UriBuilder(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Path = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + if (Dns.GetHostAddresses(uriBuilder.Host).Contains(IPAddress.Loopback)) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + HttpResponseMessage result = ??.GetAsync(uriBuilder.Uri).Result; + if (result.IsSuccessStatusCode) + { + ? result2 = result.Content.ReadFromJsonAsync>().Result; + if (result2.IsSuccess) + { + return result2.Value; + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + return null; + } + + private string ?() + { + try + { + UriBuilder uriBuilder = new UriBuilder(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Path = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + if (Dns.GetHostAddresses(uriBuilder.Host).Contains(IPAddress.Loopback)) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + HttpResponseMessage result = ??.GetAsync(uriBuilder.Uri).Result; + if (result.IsSuccessStatusCode) + { + ?> result2 = result.Content.ReadFromJsonAsync>>().Result; + if (!result2.IsSuccess) + { + return null; + } + if (!result2.Value.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value)) + { + return null; + } + return value; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, null, LoggingLevel.Verbose); + } + return null; + } + + private IEnumerable ?() + { + try + { + UriBuilder uriBuilder = new UriBuilder(??) + { + Path = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + if (Dns.GetHostAddresses(uriBuilder.Host).Contains(IPAddress.Loopback)) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ??.SetBearerToken(AccessToken); + HttpResponseMessage result = ??.GetAsync(uriBuilder.Uri).Result; + if (result.IsSuccessStatusCode) + { + JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new ?()); + return result.Content.ReadFromJsonAsync(jsonSerializerOptions).Result; + } + if (result.StatusCode == HttpStatusCode.Unauthorized) + { + UriBuilder uriBuilder2 = new UriBuilder(??) + { + Path = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + HttpResponseMessage result2 = ??.GetAsync(uriBuilder2.Uri).Result; + if (!result2.IsSuccessStatusCode) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(result2.StatusCode); + throw new Exception(defaultInterpolatedStringHandler.ToStringAndClear()); + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (State == ConnectionState.Connected) + { + ?(); + ?(); + } + } + else if (result.StatusCode == HttpStatusCode.NotFound) + { + throw new Exception(HttpStatusCode.NotFound.ToString()); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ex.Message, LoggingLevel.Error); + } + return ???.Values.Where((LicenceItem P_0) => P_0.EndDate >= Core.Instance.TimeUtils.DateTimeUtcNow).ToArray() ?? Array.Empty(); + } + + private void ?() + { + AccessToken = null; + CurrentUser = null; + ?? = new ReadOnlyDictionary(new Dictionary()); + ???.Invoke(); + ?(); + } + + private void ?() + { + if (?? != null) + { + ??.Dispose(); + ?? = null; + } + } + + private OidcClient ?() + { + int value = 55650; + try + { + value = TcpIpHelper.GetRandomUnusedPort; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(31, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(value); + string text = defaultInterpolatedStringHandler.ToStringAndClear(); + string[] value2 = new string[5] + { + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + return new OidcClient(new OidcClientOptions + { + Authority = ??, + ClientId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + ClientSecret = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + RedirectUri = text, + PostLogoutRedirectUri = text, + Scope = string.Join(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), value2), + Browser = new ?(false, value) + { + ?? = Core.Instance.OAuthBrowserCreator + }, + ClockSkew = TimeSpan.FromMinutes(5.0) + (Core.Instance.TimeUtils.DateTimeUtcNow - DateTime.UtcNow).Duration() + }); + } + + private bool ?(HttpRequestMessage P_0, X509Certificate2 P_1, X509Chain P_2, SslPolicyErrors P_3) + { + if (P_1.Issuer == P_1.Subject) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return false; + } + return P_3 == SslPolicyErrors.None; + } + + private static bool ?(IDictionary P_0, IDictionary P_1) + { + if (P_0.Count != P_1.Count) + { + return true; + } + foreach (string key in P_0.Keys) + { + if (!P_0.TryGetValue(key, out var value)) + { + return true; + } + if (!P_1.TryGetValue(key, out var value2)) + { + return true; + } + if (value.StartDate != value2.StartDate) + { + return true; + } + if (value.EndDate != value2.EndDate) + { + return true; + } + if (value.Value != value2.Value) + { + return true; + } + } + return false; + } + + [CompilerGenerated] + private void ?() + { + if (State == ConnectionState.Disconnected && !string.IsNullOrEmpty(??)) + { + State = ConnectionState.Connecting; + ?(); + } + } + } + public class LicenseManagerEventArgs : EventArgs + { + [CompilerGenerated] + private readonly ConnectionState ??; + + [CompilerGenerated] + private readonly ConnectionState ??; + + public ConnectionState PreviousState + { + [CompilerGenerated] + get + { + return ??; + } + } + + public ConnectionState NewState + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal LicenseManagerEventArgs(ConnectionState P_0, ConnectionState P_1) + { + ?? = P_0; + ?? = P_1; + } + } +} +namespace ? +{ + internal class ? + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private ? ??; + + [JsonPropertyName("ErrorText")] + public string ErrorText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = text; + } + } + + [JsonPropertyName("isSuccess")] + public bool IsSuccess + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + + [JsonPropertyName("value")] + public ? Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = val; + } + } + } +} +namespace TradingPlatform.BusinessLayer.Licence +{ + public interface IOAuthBrowserControl + { + event Action BrowserClosed; + + event Action Navigated; + + void ShowBrowser(string url, bool allowOpenNewWindow); + + void CloseBrowser(); + } + public interface IOAuthBrowserCreator + { + IOAuthBrowserControl CreateBrowser(bool showBrowserWindow); + } + public abstract class LoopbackBase : IDisposable + { + protected readonly TaskCompletionSource taskSource; + + public LoopbackBase() + { + taskSource = new TaskCompletionSource(); + } + + public abstract Task WaitForCallbackAsync(CancellationToken token); + + public void CancelWaiting() + { + if (taskSource.TrySetCanceled()) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + } + + public virtual void Dispose() + { + } + } + /// + /// The loopback http listener without kestrel. + /// + public sealed class LoopbackHttpListenerWithoutKestrel : LoopbackBase, IDisposable + { + [CompilerGenerated] + private sealed class ? + { + public LoopbackHttpListenerWithoutKestrel ??; + + public CancellationToken ??; + + internal void ?() + { + ??.?(); + } + + internal void ?() + { + Task.Delay(TimeSpan.FromMinutes(30.0), ??).Wait(??); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + ??.taskSource.SetException(new TimeoutException()); + } + } + + private readonly HttpListener ??; + + /// + /// Initializes a new instance of the class. + /// + /// The port. + public LoopbackHttpListenerWithoutKestrel(int port) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(18, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(port); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + string text = defaultInterpolatedStringHandler.ToStringAndClear(); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + text, LoggingLevel.Verbose); + ?? = new HttpListener(); + ??.Prefixes.Add(text); + ??.Start(); + } + + /// + /// Dispose + /// + public override void Dispose() + { + Task.Run(async delegate + { + await Task.Delay(500); + ??.Stop(); + ??.Close(); + }); + } + + private void ?(string P_0, HttpListenerResponse P_1) + { + using Stream stream = P_1.OutputStream; + try + { + P_1.StatusCode = 200; + P_1.ContentType = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + string s = string.Format(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + byte[] bytes = Encoding.UTF8.GetBytes(s); + P_1.ContentLength64 = bytes.Length; + stream.WriteAsync(bytes, 0, bytes.Length); + taskSource.TrySetResult(P_0); + } + catch + { + P_1.StatusCode = 400; + } + } + + private void ?() + { + try + { + HttpListenerContext context = ??.GetContext(); + if (context.Request.HttpMethod == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() || context.Request.HttpMethod == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + string query = context.Request.Url.Query; + NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(query); + if (nameValueCollection.AllKeys.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + _ = nameValueCollection[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()]; + } + ?(query, context.Response); + } + else if (context.Request.HttpMethod == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + if (context.Request.ContentType.Equals(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), StringComparison.OrdinalIgnoreCase)) + { + using (StreamReader streamReader = new StreamReader(context.Request.InputStream, Encoding.UTF8)) + { + string text = streamReader.ReadToEnd(); + ?(text, context.Response); + return; + } + } + context.Response.StatusCode = 415; + } + else + { + context.Response.StatusCode = 405; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + /// + /// Wait for callback asynchronously. + /// + /// The token. + /// ]]> + public override Task WaitForCallbackAsync(CancellationToken token) + { + token.Register(base.CancelWaiting); + Task.Factory.StartNew(delegate + { + ?(); + }, token); + Task.Factory.StartNew(delegate + { + Task.Delay(TimeSpan.FromMinutes(30.0), token).Wait(token); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + taskSource.SetException(new TimeoutException()); + }, token); + return taskSource.Task; + } + + [CompilerGenerated] + private async Task? ?() + { + await Task.Delay(500); + ??.Stop(); + ??.Close(); + } + } + public sealed class LoopbackRedirects : LoopbackBase, IDisposable + { + [CompilerGenerated] + private sealed class ? + { + public CancellationToken ??; + + public LoopbackRedirects ??; + + internal void ?() + { + Task.Delay(TimeSpan.FromMinutes(30.0), ??).Wait(??); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + ??.taskSource.SetException(new TimeoutException()); + } + } + + private readonly IOAuthBrowserControl ??; + + public LoopbackRedirects(IOAuthBrowserControl browserControl) + { + ?? = browserControl; + ??.Navigated += ?; + } + + public override void Dispose() + { + if (?? != null) + { + ??.Navigated -= ?; + } + } + + private void ?(string P_0) + { + try + { + string query = new Uri(P_0).Query; + NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(query); + if (nameValueCollection.AllKeys.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + _ = nameValueCollection[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()]; + taskSource.TrySetResult(query); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public override Task WaitForCallbackAsync(CancellationToken token) + { + token.Register(base.CancelWaiting); + Task.Factory.StartNew(delegate + { + Task.Delay(TimeSpan.FromMinutes(30.0), token).Wait(token); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + taskSource.SetException(new TimeoutException()); + }, token); + return taskSource.Task; + } + } +} +namespace ? +{ + internal class ? : IdentityModel.OidcClient.Browser.IBrowser + { + [CompilerGenerated] + private sealed class ? + { + public LoopbackBase ??; + + internal void ?() + { + ???.CancelWaiting(); + } + } + + internal IOAuthBrowserCreator ??; + + private readonly int ??; + + private readonly bool ??; + + public ?(bool P_0, int? P_1 = null) + { + ?? = P_0; + if (!P_1.HasValue) + { + ?? = TcpIpHelper.GetRandomUnusedPort; + } + else + { + ?? = P_1.Value; + } + } + + public async Task InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default(CancellationToken)) + { + IOAuthBrowserControl iOAuthBrowserControl = ?(options.StartUrl); + LoopbackBase ?? = null; + if (options.EndUrl.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + ?? = new LoopbackHttpListenerWithoutKestrel(??); + } + else + { + ?? = new LoopbackRedirects(iOAuthBrowserControl); + } + if (iOAuthBrowserControl != null) + { + iOAuthBrowserControl.BrowserClosed += delegate + { + ???.CancelWaiting(); + }; + } + try + { + string text = await ??.WaitForCallbackAsync(cancellationToken); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + text, LoggingLevel.Verbose); + if (string.IsNullOrWhiteSpace(text)) + { + return new BrowserResult + { + ResultType = BrowserResultType.UnknownError, + Error = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + }; + } + return new BrowserResult + { + Response = text, + ResultType = BrowserResultType.Success + }; + } + catch (TimeoutException ex) + { + return new BrowserResult + { + ResultType = BrowserResultType.Timeout, + Error = ex.Message + }; + } + catch (TaskCanceledException ex2) + { + return new BrowserResult + { + ResultType = BrowserResultType.UserCancel, + Error = ex2.Message + }; + } + catch (Exception ex3) + { + return new BrowserResult + { + ResultType = BrowserResultType.UnknownError, + Error = ex3.Message + }; + } + finally + { + iOAuthBrowserControl?.CloseBrowser(); + ??.Dispose(); + } + } + + private IOAuthBrowserControl ?(string P_0) + { + if (?? == null) + { + ?(P_0); + return null; + } + IOAuthBrowserControl iOAuthBrowserControl = ??.CreateBrowser(!P_0.Contains(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())); + iOAuthBrowserControl.ShowBrowser(P_0, ??); + return iOAuthBrowserControl; + } + + private static void ?(string P_0) + { + try + { + Process.Start(P_0); + } + catch + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + P_0 = P_0.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + Process.Start(new ProcessStartInfo(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0) + { + CreateNoWindow = true + }); + return; + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0); + return; + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), P_0); + return; + } + throw; + } + } + } +} +namespace TradingPlatform.BusinessLayer.Licence +{ + public static class TcpIpHelper + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(TcpConnectionInformation P_0) + { + return P_0.State != TcpState.Closed; + } + + internal int ?(TcpConnectionInformation P_0) + { + return P_0.LocalEndPoint.Port; + } + + internal int ?(IPEndPoint P_0) + { + return P_0.Port; + } + + internal int ?(IPEndPoint P_0) + { + return P_0.Port; + } + } + + private static readonly Random ??; + + public static int GetRandomUnusedPort + { + get + { + IPGlobalProperties iPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); + IEnumerable first = from P_0 in iPGlobalProperties.GetActiveTcpConnections() + where P_0.State != TcpState.Closed + select P_0.LocalEndPoint.Port; + IPEndPoint[] activeTcpListeners = iPGlobalProperties.GetActiveTcpListeners(); + first = first.Union(activeTcpListeners.Select((IPEndPoint P_0) => P_0.Port)); + IPEndPoint[] activeUdpListeners = iPGlobalProperties.GetActiveUdpListeners(); + first = first.Union(activeUdpListeners.Select((IPEndPoint P_0) => P_0.Port)); + int num = 49152; + int num2 = 65535; + int[] array = Enumerable.Range(num, num2 - num + 1).Except(first).ToArray(); + if (!array.Any()) + { + throw new ApplicationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + int num3 = ??.Next(0, array.Length - 1); + return array[num3]; + } + } + + static TcpIpHelper() + { + ?? = new Random(); + } + } + public class UserInfo + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public string Email + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public string UserId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public UserInfo(IEnumerable claims) + { + foreach (Claim claim in claims) + { + if (claim.Type == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + UserId = claim.Value; + } + if (claim.Type == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Name = claim.Value; + } + if (claim.Type == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + Email = claim.Value; + } + } + } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding +{ + [AttributeUsage(AttributeTargets.Property)] + public class BindableAttribute : Attribute + { + [CompilerGenerated] + private readonly string ??; + + public string Alias + { + [CompilerGenerated] + get + { + return ??; + } + } + + public BindableAttribute(string alias) + { + ?? = alias; + } + } + public abstract class BindableEntity : IBindableEntity, INotifyPropertyChanged + { + [CompilerGenerated] + private sealed class ? + { + public BindableEntity ??; + + public string ??; + + internal void ?(object? _, NotifyCollectionChangedEventArgs P_1) + { + ??.?(??, P_1); + } + } + + public const string SYMBOL = "symbol"; + + public const string ACCOUNT = "account"; + + public const string ACCOUNTS = "accounts"; + + public const string ORDER_TYPE = "orderType"; + + public const string SIDE = "side"; + + public const string QUANTITY = "quantity"; + + public const string PRICE = "price"; + + public const string TRIGGER_PRICE = "triggerPrice"; + + public const string CONNECTION_ID = "connectionId"; + + public const string CONNECTIONS = "connections"; + + public const string CONNECTION = "connection"; + + public const string EXCHANGES = "exchanges"; + + public const string EXCHANGE = "exchange"; + + public const string CONTAINERS = "containers"; + + public const string CONTAINER = "container"; + + public const string VISIBLE = "visible"; + + public const string ENABLED = "enabled"; + + public const string CHECKED = "checked"; + + public const string HIDDEN = "hidden"; + + public const string ERROR = "error"; + + public const string WARNING = "warning"; + + public const string ORDER = "order"; + + public const string POSITION = "position"; + + public const string GROSS_PNL = "grossPnl"; + + public const string FEE = "fee"; + + public const string NET_PNL = "netPnl"; + + public const string STOP_LOSS = "stopLoss"; + + public const string TAKE_PROFIT = "takeProfit"; + + public const string BRACKET = "bracket"; + + public const string IS_TRAILING = "isTrailing"; + + public const string IS_TRAILING_ALLOWED = "isTrailingAllowed"; + + public const string TICKS = "ticks"; + + public const string PERIOD = "period"; + + public const string SELECTED_ITEM = "selectedItem"; + + public const string ITEMS = "items"; + + public const string SETTINGS = "settings"; + + public const string COMMAND = "command"; + + public const string CANCEL_COMMAND = "cancelCommand"; + + public const string CLOSE_COMMAND = "closeCommand"; + + public const string ADD_COMMAND = "addCommand"; + + public const string EDIT_COMMAND = "editCommand"; + + public const string DELETE_COMMAND = "deleteCommand"; + + public const string SELECT_COMMAND = "selectCommand"; + + public const string SAVE_COMMAND = "saveCommand"; + + public const string CLEAR_COMMAND = "clearAllCommand"; + + public const string APPLY_COMMAND = "applyCommand"; + + public const string DISCARD_COMMAND = "discardCommand"; + + public const string CHANGED_COMMAND = "changedCommand"; + + public const string VALUE = "value"; + + public const string TEXT = "text"; + + public const string LABEL = "label"; + + public const string TOOLTIP = "tooltip"; + + public const string MAXIMUM = "maximum"; + + public const string MINIMUM = "minimum"; + + public const string INCREMENT = "increment"; + + public const string DECIMAL_PLACES = "decimalPlaces"; + + public const string DIMENSION = "dimension"; + + public const string LINK_TEXT = "linkText"; + + public const string STEPS_COUNT = "stepsCount"; + + public const string CURRENT_STEP = "currentStep"; + + public const string WIDTH = "width"; + + public const string IS_SLIM_MODE_ENABLED = "isSlimModeEnabled"; + + public const string COLOR = "color"; + + public const string FOREGROUND_COLOR = "foregroundColor"; + + public const string BACKGROUND_COLOR = "backgroundColor"; + + public const string FORMAT = "format"; + + public const string INDEX = "index"; + + public const string SHOW = "show"; + + public const string SHOW_TOOLBAR = "showToolbar"; + + public const string IS_ACTIVE = "isActive"; + + public const string MULTIPLIER = "multiplier"; + + public const string NAME = "name"; + + public const string DESCRIPTION = "description"; + + public const string FROM = "from"; + + public const string TO = "to"; + + public const string TYPE = "type"; + + public const string START = "start"; + + public const string END = "end"; + + public const string DAY = "day"; + + public const string TIMEZONE = "timeZone"; + + public const string IS_VALID = "isValid"; + + public const string DATE = "date"; + + public const string DIRECTION = "direction"; + + public const string PROGRESS = "progress"; + + public const string COUNT = "count"; + + public const string IS_ALLOWED = "isAllowed"; + + public const string IS_LOADING = "isLoading"; + + public const string FILTRATION = "filtration"; + + public const string COLUMNS = "columns"; + + public const string ROWS = "rows"; + + private static readonly BusinessObjectEqualityComparer ?? = new BusinessObjectEqualityComparer(); + + private static readonly ListEqualityComparer ?? = new ListEqualityComparer(EqualityComparer.Default); + + private static readonly ListEqualityComparer ?? = new ListEqualityComparer(EqualityComparer.Default); + + private static readonly UniqueIdEqualityComparer ?? = new UniqueIdEqualityComparer(); + + private readonly Lazy> ?? = new Lazy>(); + + [CompilerGenerated] + private PropertyChangedEventHandler ??; + + public event PropertyChangedEventHandler PropertyChanged + { + [CompilerGenerated] + add + { + PropertyChangedEventHandler propertyChangedEventHandler = ??; + PropertyChangedEventHandler propertyChangedEventHandler2; + do + { + propertyChangedEventHandler2 = propertyChangedEventHandler; + PropertyChangedEventHandler value2 = (PropertyChangedEventHandler)Delegate.Combine(propertyChangedEventHandler2, value); + propertyChangedEventHandler = Interlocked.CompareExchange(ref ??, value2, propertyChangedEventHandler2); + } + while ((object)propertyChangedEventHandler != propertyChangedEventHandler2); + } + [CompilerGenerated] + remove + { + PropertyChangedEventHandler propertyChangedEventHandler = ??; + PropertyChangedEventHandler propertyChangedEventHandler2; + do + { + propertyChangedEventHandler2 = propertyChangedEventHandler; + PropertyChangedEventHandler value2 = (PropertyChangedEventHandler)Delegate.Remove(propertyChangedEventHandler2, value); + propertyChangedEventHandler = Interlocked.CompareExchange(ref ??, value2, propertyChangedEventHandler2); + } + while ((object)propertyChangedEventHandler != propertyChangedEventHandler2); + } + } + + protected bool SetValue(ref T storage, T value, IEqualityComparer comparer = null, [CallerMemberName] string propertyName = null) + { + if (IsValueEquals(storage, value, comparer)) + { + return false; + } + ?(storage, propertyName); + storage = value; + OnPropertyChanged(propertyName); + ?(storage, propertyName); + return true; + } + + protected bool IsValueEquals(T oldValue, T newValue, IEqualityComparer comparer = null) + { + if (comparer != null) + { + return comparer.Equals(oldValue, newValue); + } + T val = ((oldValue != null) ? oldValue : newValue); + return (val is Symbol) ? ??.Equals(oldValue as BusinessObject, newValue as BusinessObject) : ((val is IUniqueID) ? ??.Equals(oldValue as IUniqueID, newValue as IUniqueID) : ((val is IList) ? ??.Equals(oldValue as IList, newValue as IList) : ((!(val is IList)) ? EqualityComparer.Default.Equals(oldValue, newValue) : ??.Equals(oldValue as IList, newValue as IList)))); + } + + private void ?(? P_0, string P_1) + { + if (P_0 is INotifyCollectionChanged notifyCollectionChanged && P_1 != null && ??.Value.TryRemove(P_1, out var value)) + { + notifyCollectionChanged.CollectionChanged -= value; + } + } + + private void ?(? P_0, string P_1) + { + if (P_0 is INotifyCollectionChanged notifyCollectionChanged && P_1 != null) + { + NotifyCollectionChangedEventHandler value = delegate(object? _, NotifyCollectionChangedEventArgs e) + { + this.?(P_1, e); + }; + if (??.Value.TryAdd(P_1, value)) + { + notifyCollectionChanged.CollectionChanged += value; + } + } + } + + protected void OnPropertyChanged(string propertyName) + { + ?(new PropertyChangedEventArgs(propertyName)); + } + + private void ?(string P_0, NotifyCollectionChangedEventArgs P_1) + { + ?(new CollectionChangedEventArgs(P_0, P_1)); + } + + private void ?(PropertyChangedEventArgs P_0) + { + ???.InvokeSafely(this, P_0); + } + } + public class Binding : IDisposable + { + internal class ? + { + [CompilerGenerated] + private sealed class ? + { + public List ??; + + internal List ?(Type _) + { + return ??; + } + + internal List ?(Type _, List P_1) + { + return ??; + } + } + + [CompilerGenerated] + private readonly IBindableEntity ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly Type ??; + + private readonly PropertyInfo ??; + + private static readonly ConcurrentDictionary> ??; + + private static readonly PropertyInfoEqualityComparer ??; + + public IBindableEntity Entity + { + [CompilerGenerated] + get + { + return ??; + } + } + + public string PropertyName + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Type PropertyType + { + [CompilerGenerated] + get + { + return ??; + } + } + + static ?() + { + ?? = new ConcurrentDictionary>(); + ?? = new PropertyInfoEqualityComparer(); + } + + public ?(IBindableEntity P_0, string P_1) + { + ?? = P_0; + ?? = P_1; + foreach (PropertyInfo item in ?(Entity.GetType())) + { + if (!((item.GetCustomAttribute()?.Alias ?? item.Name) != P_1)) + { + ?? = item.Name; + ?? = item.PropertyType; + ?? = item; + break; + } + } + if (?? == null) + { + throw new BindingPropertyMissingException(P_1); + } + } + + public object ?() + { + try + { + if (?? == null || !??.CanRead) + { + return null; + } + return ???.GetValue(Entity); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return null; + } + + public void ?(object P_0) + { + try + { + if (!(?? == null) && ??.CanWrite) + { + ??.SetValue(Entity, P_0); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 2); + defaultInterpolatedStringHandler.AppendFormatted(PropertyName); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Entity.GetType()); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + private static List ?(Type P_0) + { + if (??.TryGetValue(P_0, out var value)) + { + return value; + } + List ?? = new List(); + Type type = P_0; + do + { + PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + ??.AddRange(properties); + type = type.BaseType; + } + while (type != null); + ?? = ??.Distinct(??).ToList(); + ??.AddOrUpdate(P_0, (Type _) => ??, (Type _, List list) => ??); + return ??; + } + } + + [StructLayout(LayoutKind.Auto)] + [CompilerGenerated] + private struct ? + { + public Binding ??; + + public IList ??; + + public NotifyCollectionChangedEventArgs ??; + } + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private readonly ? ??; + + [CompilerGenerated] + private Queue ??; + + [CompilerGenerated] + private Predicate ??; + + [CompilerGenerated] + private Func ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + [CompilerGenerated] + private Action ??; + + private bool ??; + + internal ? Accessor1 + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal ? Accessor2 + { + [CompilerGenerated] + get + { + return ??; + } + } + + internal Queue ConvertersQueue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = queue; + } + } + + internal Predicate Predicate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = predicate; + } + } + + internal Func ItemsFactory + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = func; + } + } + + internal Action RemoveItemCallback + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = action; + } + } + + internal Action ClearItemsCallback + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = action; + } + } + + internal Action ApplyCallback + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = action; + } + } + + public Binding(IBindableEntity entity1, string propertyName1, IBindableEntity entity2, string propertyName2) + { + if (entity1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (entity2 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + ?? = new ?(entity1, propertyName1); + ?? = new ?(entity2, propertyName2); + Accessor1.Entity.PropertyChanged += ?; + Accessor2.Entity.PropertyChanged += ?; + } + + private void ?(object P_0, PropertyChangedEventArgs P_1) + { + ? ? = ((P_0 == Accessor1.Entity) ? Accessor1 : Accessor2); + ? ?2 = ((P_0 == Accessor1.Entity) ? Accessor2 : Accessor1); + if (? == null || ?2 == null || P_1.PropertyName != ?.PropertyName || (Predicate != null && !Predicate(?.Entity))) + { + return; + } + try + { + if (!??) + { + ?? = true; + if (P_1 is CollectionChangedEventArgs e && ?2.?() is IList list) + { + this.?(?, list, e); + } + else + { + this.?(?, ?2); + } + } + } + finally + { + ?? = false; + } + } + + internal Binding ?(? P_0, ? P_1) + { + object obj = P_0.?(); + if (ConvertersQueue == null || !ConvertersQueue.Any()) + { + P_1.?(obj); + return this; + } + object convertedValue = obj; + foreach (IBindingValueConverter item in ConvertersQueue) + { + if (!item.TryConvert(convertedValue, P_0.PropertyType, P_0.Entity, out convertedValue)) + { + return this; + } + } + P_1.?(convertedValue); + ApplyCallback?.InvokeSafely(); + return this; + } + + private Binding ?(? P_0, IList P_1, CollectionChangedEventArgs P_2) + { + ? ? = default(?); + ?.?? = this; + ?.?? = P_1; + ?.?? = P_2.CollectionChangedArgs; + switch (?.??.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (object newItem in ?.??.NewItems) + { + ?(newItem, ref ?); + } + break; + case NotifyCollectionChangedAction.Move: + { + object value = ?.??[?.??.OldStartingIndex]; + ?.??.RemoveAt(?.??.OldStartingIndex); + ?.??.Insert(?.??.NewStartingIndex, value); + break; + } + case NotifyCollectionChangedAction.Remove: + ?(ref ?); + break; + case NotifyCollectionChangedAction.Replace: + ?(ref ?); + foreach (object newItem2 in ?.??.NewItems) + { + ?(newItem2, ref ?); + } + break; + case NotifyCollectionChangedAction.Reset: + ClearItemsCallback?.InvokeSafely(); + ?.??.Clear(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + return this; + } + + internal bool ?(object P_0) + { + if (Accessor1.Entity != P_0) + { + return Accessor2.Entity == P_0; + } + return true; + } + + public void Dispose() + { + Accessor1.Entity.PropertyChanged -= ?; + Accessor2.Entity.PropertyChanged -= ?; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(18, 3); + defaultInterpolatedStringHandler.AppendFormatted(Accessor1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Accessor2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ConvertersQueue?.Count); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + [CompilerGenerated] + private void ?(object P_0, ref ? P_1) + { + object value = ItemsFactory?.Invoke(P_0) ?? P_0; + P_1.??.Insert(P_1.??.NewStartingIndex, value); + } + + [CompilerGenerated] + private void ?(ref ? P_0) + { + object obj = P_0.??[P_0.??.OldStartingIndex]; + P_0.??.RemoveAt(P_0.??.OldStartingIndex); + RemoveItemCallback?.Invoke(obj); + } + } + public static class BindingExtensions + { + public static Binding WithConvertor(this Binding binding, IBindingValueConverter converter) + { + if (binding.ConvertersQueue == null) + { + Queue queue = (binding.ConvertersQueue = new Queue()); + } + binding.ConvertersQueue.Enqueue(converter); + return binding; + } + + public static Binding WithPredicate(this Binding binding, Predicate predicate) + { + binding.Predicate = predicate; + return binding; + } + + public static Binding WithItemsFactory(this Binding binding, Func itemsFactory) + { + binding.ItemsFactory = itemsFactory; + return binding; + } + + public static Binding WithRemoveItemCallback(this Binding binding, Action removeItemCallback) + { + binding.RemoveItemCallback = removeItemCallback; + return binding; + } + + public static Binding WithClearItemsCallback(this Binding binding, Action clearItemsCallback) + { + binding.ClearItemsCallback = clearItemsCallback; + return binding; + } + + public static Binding WithApplyCallback(this Binding binding, Action applyCallback) + { + binding.ApplyCallback = applyCallback; + return binding; + } + + public static Binding ApplyValue(this Binding binding) + { + return binding.?(binding.Accessor2, binding.Accessor1); + } + } + public class CollectionChangedEventArgs : PropertyChangedEventArgs + { + [CompilerGenerated] + private readonly NotifyCollectionChangedEventArgs ??; + + public NotifyCollectionChangedEventArgs CollectionChangedArgs + { + [CompilerGenerated] + get + { + return ??; + } + } + + public CollectionChangedEventArgs(string propertyName, NotifyCollectionChangedEventArgs collectionChangedArgs) + : base(propertyName) + { + ?? = collectionChangedArgs; + } + } +} +namespace ? +{ + internal class ? : IDisposable + { + [CompilerGenerated] + private sealed class ? + { + public IBindableEntity ??; + + internal bool ?(Binding P_0) + { + return P_0.?(??); + } + } + + private IBindableEntity ??; + + private readonly IList ??; + + public ?(IBindableEntity P_0) + { + ?? = P_0; + ?? = new List(); + } + + public Binding ?(IBindableEntity P_0, string P_1) + { + return ?(P_0, P_1, ??, P_1); + } + + public Binding ?(IBindableEntity P_0, string P_1, string P_2) + { + return ?(P_0, P_1, ??, P_2); + } + + public Binding ?(IBindableEntity P_0, string P_1, IBindableEntity P_2, string P_3) + { + try + { + Binding binding = new Binding(P_0, P_1, P_2, P_3); + ??.Add(binding); + return binding; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return null; + } + + public void ?(IBindableEntity P_0) + { + if (P_0 == null) + { + return; + } + try + { + foreach (Binding item in ??.Where((Binding binding) => binding.?(P_0)).ToList()) + { + ??.Remove(item); + item.Dispose(); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + + public void Dispose() + { + ?? = null; + foreach (Binding item in ??) + { + item.Dispose(); + } + } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding +{ + public interface IBindableEntity : INotifyPropertyChanged + { + } + public interface IBindingValueConverter + { + bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue); + } + public interface ICommandBindableEntity : IBindableEntity, INotifyPropertyChanged + { + ICommand Command { get; set; } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding.Mvvm +{ + public abstract class BindableView : BindableEntity, IBindableView, IDisposable + { + private IBindableEntity ??; + + private ? ??; + + public IBindableEntity BindingContext + { + get + { + return ??; + } + set + { + ?? = value; + ???.Dispose(); + if (?? == null) + { + return; + } + ?? = new ?(??); + try + { + BindContext(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + protected virtual void BindContext() + { + } + + public Binding Bind(string propertyName) + { + return ??.?(this, propertyName); + } + + public Binding Bind(string propertyName1, string propertyName2) + { + return ??.?(this, propertyName1, propertyName2); + } + + public Binding Bind(IBindableEntity entity1, string propertyName) + { + return ??.?(entity1, propertyName, propertyName); + } + + public Binding Bind(IBindableEntity entity1, string propertyName1, string propertyName2) + { + return ??.?(entity1, propertyName1, propertyName2); + } + + public Binding Bind(IBindableEntity entity1, string propertyName1, IBindableEntity entity2, string propertyName2) + { + return ??.?(entity1, propertyName1, entity2, propertyName2); + } + + public void Unbind(IBindableEntity entity) + { + ??.?(entity); + } + + public virtual void Dispose() + { + BindingContext = null; + } + } + public interface IBindableView : IDisposable + { + IBindableEntity BindingContext { get; set; } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding.Extensions +{ + public static class CommandBindableEntityExtensions + { + public static void TryExecuteCommand(this ICommandBindableEntity entity, object parameter = null) + { + entity.TryExecuteCommand(entity.Command, parameter); + } + + public static void TryExecuteCommand(this IBindableEntity entity, ICommand command, object parameter = null) + { + try + { + if (command != null) + { + if (parameter == null) + { + parameter = entity; + } + if (command.CanExecute(parameter)) + { + command.Execute(parameter); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding.Exceptions +{ + public class BindingException : Exception + { + protected BindingException(string message) + : base(message) + { + } + } + public class BindingPropertyMissingException : BindingException + { + public BindingPropertyMissingException(string propertyAlias) + : base(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + propertyAlias + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + { + } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding.Converters +{ + public class DateTimeTimeSpanConverter : IBindingValueConverter + { + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (value is DateTime dateTime) + { + convertedValue = dateTime.TimeOfDay; + return true; + } + if (value is TimeSpan value2) + { + convertedValue = default(DateTime).Add(value2); + return true; + } + return false; + } + } + public class DoubleDecimalConverter : IBindingValueConverter + { + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (value is double num) + { + if (!(num <= -7.922816251426434E+28)) + { + if (num >= 7.922816251426434E+28) + { + convertedValue = decimal.MaxValue; + return true; + } + convertedValue = (decimal)num; + return true; + } + convertedValue = decimal.MinValue; + return true; + } + if (value is decimal num2) + { + convertedValue = (double)num2; + return true; + } + return false; + } + } + public class IntDecimalConverter : IBindingValueConverter + { + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (!(value is int num)) + { + if (value is decimal val) + { + decimal val2 = Math.Max(val, -2147483648m); + val2 = Math.Min(val2, 2147483647m); + convertedValue = (int)val2; + return true; + } + return false; + } + convertedValue = (decimal)num; + return true; + } + } + public class LongDecimalConverter : IBindingValueConverter + { + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (!(value is long num)) + { + if (value is decimal val) + { + decimal val2 = Math.Max(val, -9223372036854775808m); + val2 = Math.Min(val2, 9223372036854775807m); + convertedValue = (long)val2; + return true; + } + return false; + } + convertedValue = (decimal)num; + return true; + } + } + public class SettingItemToStringConverter : IBindingValueConverter + { + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (!(source is SettingItem settingItem)) + { + return false; + } + convertedValue = settingItem.Value?.ToString() ?? settingItem.Text; + return true; + } + } + public class StringToLocalizedStringConverter : IBindingValueConverter + { + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (source is IBindableView) + { + return false; + } + if (!(value is string text)) + { + return false; + } + convertedValue = loc._(text, null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return true; + } + } + public class ValueConverter : IBindingValueConverter + { + private readonly Func ??; + + public ValueConverter(Func convertDelegate) + { + ?? = convertDelegate ?? throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + public bool TryConvert(object value, Type valueType, IBindableEntity source, out object convertedValue) + { + convertedValue = null; + if (valueType != typeof(TValue)) + { + return false; + } + if (value is TValue arg) + { + convertedValue = ??(arg); + } + else + { + convertedValue = ??(default(TValue)); + } + return true; + } + } +} +namespace TradingPlatform.BusinessLayer.DataBinding.Commands +{ + public class BindingCommand : ICommand + { + private readonly Action ??; + + private readonly Predicate ??; + + [CompilerGenerated] + private EventHandler ??; + + public event EventHandler CanExecuteChanged + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + public BindingCommand(Action action, Predicate canExecutePredicate = null) + { + ?? = action; + ?? = canExecutePredicate; + } + + public bool CanExecute(object parameter) + { + return ???.Invoke(parameter) ?? (?? != null); + } + + public void Execute(object parameter) + { + try + { + ???.Invoke(parameter); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } +} +namespace ? +{ + internal class ? + { + [CompilerGenerated] + private sealed class ? + { + public string ??; + + internal bool ?(? P_0) + { + return P_0.Regex.Match(??).Success; + } + } + + private static readonly IList ?? = new List + { + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()), + new ?(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }; + + public void ?(SettingItem P_0) + { + IList value = P_0.GetValue>(); + SettingItem itemByName = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + SettingItem itemByName2 = value.GetItemByName(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + string text = itemByName.Value.ToString(); + foreach (? item in ??) + { + if (item.Regex.Match(text).Success) + { + itemByName.Value = text.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + item.OldName, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + item.NewName); + itemByName2.Value = item.NewName; + break; + } + } + } + + public string ?(string P_0) + { + ? ?2 = ??.FirstOrDefault((? ?3) => ?3.Regex.Match(P_0).Success); + if (?2 == null) + { + return P_0; + } + return P_0.Replace(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ?2.OldName, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ?2.NewName); + } + } + internal class ? + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly Regex ??; + + public string OldName + { + [CompilerGenerated] + get + { + return ??; + } + } + + public string NewName + { + [CompilerGenerated] + get + { + return ??; + } + } + + public Regex Regex + { + [CompilerGenerated] + get + { + return ??; + } + } + + public ?(string P_0, string P_1) + { + ?? = P_0; + ?? = P_1; + ?? = new Regex(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + OldName + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } +} +namespace TradingPlatform.BusinessLayer.VolumeAnalysis.Storage +{ + public interface IVolumeAnalysisLocalStorage : ILocalStorage + { + void Save(VolumeAnalysisInterval volumeAnalysisInterval); + + VolumeAnalysisInterval Load(VolumeAnalysisDescription description, Interval interval); + + void Delete(VolumeAnalysisDescription description, Interval interval); + + VolumeAnalysisStorageInfo GetInfo(VolumeAnalysisDescription description); + } + public class VolumeAnalysisDescription + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Period? ??; + + [CompilerGenerated] + private bool ??; + + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Period? Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool IncludePriceLevels + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VolumeAnalysisDescription(string symbolId, Period? period, bool includePriceLevels) + { + SymbolId = symbolId; + Period = period; + IncludePriceLevels = includePriceLevels; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 3); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Period); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(IncludePriceLevels); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public class VolumeAnalysisInterval + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal int ?(VolumeAnalysisData P_0) + { + return P_0.PriceLevels.Count; + } + } + + [CompilerGenerated] + private VolumeAnalysisDescription ??; + + [CompilerGenerated] + private Interval ??; + + [CompilerGenerated] + private IList ??; + + public VolumeAnalysisDescription Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Interval Interval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList VolumeAnalysis + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(32, 4); + defaultInterpolatedStringHandler.AppendFormatted(Description); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Interval); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(VolumeAnalysis.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(VolumeAnalysis.Sum((VolumeAnalysisData P_0) => P_0.PriceLevels.Count)); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public class VolumeAnalysisStorage : DataStorage + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, bool> ??; + + internal bool ?(Interval P_0) + { + return !P_0.IsEmpty; + } + } + + [CompilerGenerated] + private sealed class ? + { + public Interval ??; + + public VolumeAnalysisByPeriodRequestParameters ??; + + internal VolumeAnalysisByPeriodRequestParameters ?(Interval P_0) + { + if (P_0 == ??) + { + return ??; + } + VolumeAnalysisByPeriodRequestParameters copy = ??.Copy; + copy.FromTime = P_0.From; + copy.ToTime = P_0.To; + return copy; + } + + internal Interval ?(Interval P_0) + { + return P_0.Intersect(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public VolumeAnalysisStorage ??; + + public VolumeAnalysisInterval ??; + + internal void ?() + { + ??.??.Save(??); + } + + internal void ?() + { + ??.??.Save(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public VolumeAnalysisStorage ??; + + public VolumeAnalysisDescription ??; + + public Interval ??; + + internal void ?() + { + ??.??.Delete(??, ??); + } + + internal void ?() + { + ??.??.Delete(??, ??); + } + } + + private readonly IVolumeAnalysisLocalStorage ??; + + private static readonly Type ??; + + public VolumeAnalysisStorage(IVolumeAnalysisLocalStorage storage, string localFilePath) + : base(storage, localFilePath) + { + ?? = storage; + } + + public IList Load(VolumeAnalysisByPeriodRequestParameters requestParameters, out List parametersForServerRequest) + { + CheckDisposed(); + List list = new List(); + parametersForServerRequest = new List(); + if (requestParameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + VolumeAnalysisDescription description = requestParameters.ToDescription(); + VolumeAnalysisStorageInfo info = ??.GetInfo(description); + if (info.StoredIntervals.Count == 0) + { + parametersForServerRequest.Add(requestParameters); + return list; + } + Interval ?? = requestParameters.Interval; + Interval[] source = ??.Subtract(info.StoredIntervals).ToArray(); + parametersForServerRequest.AddRange(source.Select(delegate(Interval P_0) + { + if (!(P_0 == ??)) + { + VolumeAnalysisByPeriodRequestParameters copy = requestParameters.Copy; + copy.FromTime = P_0.From; + copy.ToTime = P_0.To; + return copy; + } + return requestParameters; + })); + Interval[] array = (from P_0 in info.StoredIntervals + select P_0.Intersect(??) into P_0 + where !P_0.IsEmpty + select P_0).ToArray(); + foreach (Interval interval in array) + { + VolumeAnalysisInterval item = ??.Load(description, interval); + list.Add(item); + } + return list; + } + + public void Save(VolumeAnalysisInterval volumeAnalysisInterval, bool wait = false) + { + CheckDisposed(); + if (wait) + { + WaitForAction(delegate + { + ??.Save(volumeAnalysisInterval); + }); + } + else + { + PushAction(delegate + { + ??.Save(volumeAnalysisInterval); + }); + } + } + + public void Delete(VolumeAnalysisDescription description, Interval interval, bool wait = false) + { + CheckDisposed(); + if (wait) + { + WaitForAction(delegate + { + ??.Delete(description, interval); + }); + } + else + { + PushAction(delegate + { + ??.Delete(description, interval); + }); + } + } + + public VolumeAnalysisStorageInfo GetInfo(VolumeAnalysisDescription description) + { + CheckDisposed(); + return ??.GetInfo(description); + } + + static VolumeAnalysisStorage() + { + try + { + ?? = AssemblyLoader.LoadTypes(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), typeof(IVolumeAnalysisLocalStorage), null, SearchOption.AllDirectories)?.FirstOrDefault(); + } + catch + { + } + } + + public static VolumeAnalysisStorage Create(string connectionString) + { + if (?? == null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IVolumeAnalysisLocalStorage obj = Activator.CreateInstance(??) as IVolumeAnalysisLocalStorage; + if (obj == null) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + string directoryName = Path.GetDirectoryName(connectionString); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + return new VolumeAnalysisStorage(obj, connectionString); + } + } + public class VolumeAnalysisStorageInfo + { + [CompilerGenerated] + private List> ??; + + public List> StoredIntervals + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VolumeAnalysisStorageInfo() + { + StoredIntervals = new List>(); + } + } +} +namespace TradingPlatform.BusinessLayer.PowerTrades +{ + public interface IPowerTradesBaseSettings + { + double MinTradeVolume { get; } + + double MaxTradeVolume { get; } + + double TotalVolume { get; } + + double TimeInterval { get; } + + double BasisVolumeInterval { get; } + + int MaxZoneHeight { get; } + + int MinZoneHeight { get; } + + double DeltaFilter { get; } + + double BasisRatioFilter { get; } + } + public interface IPowerTradesHistoryItem : IHistoryItem, ICloneable + { + double Cumulative { get; } + + double Delta { get; } + + double DeltaPercent { get; } + + double MaxPrice { get; } + + double MinPrice { get; } + + double BasisRatioPercent { get; } + + DateTime LeftTime { get; } + + DateTime RightTime { get; } + } +} +namespace TradingPlatform.BusinessLayer.Media.Messengers +{ + public interface IMessenger : ICustomizable + { + string Name { get; } + + void SendMessage(MessengerMessage message, CancellationToken cancellationToken); + } + public static class Messenger + { + public const string TELEGRAM = "Telegram"; + + public const string EMAIL = "Email"; + } + public class MessengerMessage + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public string Title + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Text + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public class MessengersManager : ICustomizable, IDisposable + { + private readonly Dictionary ??; + + public IMessenger Telegram => this[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()]; + + public IMessenger Email => this[3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()]; + + public IMessenger[] All => ??.Values.ToArray(); + + public IMessenger this[string name] + { + get + { + if (!TryGetMessenger(name, out var messenger)) + { + return null; + } + return messenger; + } + } + + public IList Settings + { + get + { + List list = new List(); + IMessenger[] all = All; + foreach (IMessenger messenger in all) + { + list.Add(new SettingItemGroup(messenger.Name, messenger.Settings)); + } + return list; + } + set + { + foreach (SettingItem item in value) + { + if (item is SettingItemGroup { Value: IList value2 } settingItemGroup && TryGetMessenger(settingItemGroup.Name, out var messenger)) + { + messenger.Settings = value2; + } + } + } + } + + internal MessengersManager() + { + ?? = new Dictionary(); + } + + internal void ?() + { + try + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (TypeWrapper item in AssemblyLoader.LoadTypes(Const.MESSENGERS_PATH, typeof(IMessenger), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchOption.AllDirectories)) + { + Type type = item; + try + { + if (!type.IsAbstract) + { + if (!(Activator.CreateInstance(type) is IMessenger messenger)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + type.Name); + } + else if (??.ContainsKey(messenger.Name)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + messenger.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + else + { + ??.Add(messenger.Name, messenger); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(26, 2); + defaultInterpolatedStringHandler.AppendFormatted(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear()); + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + } + finally + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public bool TryGetMessenger(string messengerName, out IMessenger messenger) + { + return ??.TryGetValue(messengerName, out messenger); + } + + public void Dispose() + { + ??.Clear(); + } + } +} +namespace TradingPlatform.BusinessLayer.Serialization +{ + public interface IXElementSerialization + { + XElement ToXElement(); + + void FromXElement(XElement element, DeserializationInfo deserializationInfo); + } + /// + /// ??????? ??? ????????? + /// + [ProtoContract] + public class SnapshotData : IXElementSerialization + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(Account P_0) + { + return !(P_0 is CryptoAccount); + } + + internal MessageAccount ?(Account P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + + internal MessageCryptoAccount ?(CryptoAccount P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + + internal IEnumerable ?(CryptoAccount P_0) + { + return P_0.Balances; + } + + internal MessageCryptoAssetBalances ?(CryptoAssetBalances P_0) + { + return P_0.BuildMessage(); + } + + internal MessageAsset ?(Asset P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + + internal MessageExchange ?(Exchange P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + + internal MessageSymbol ?(Symbol P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + + internal DayBar ?(Symbol P_0) + { + return ((IMessageBuilder)P_0).BuildMessage(); + } + + internal MessageOpenOrder ?(Order P_0) + { + return P_0.BuildMessage(); + } + + internal MessageOpenPosition ?(Position P_0) + { + return P_0.BuildMessage(); + } + + internal MessageOpenDeliveredAsset ?(DeliveredAsset P_0) + { + return P_0.BuildMessage(); + } + + internal MessageSessionsContainer ?(SessionsContainer P_0) + { + return P_0.BuildMessage(); + } + } + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private IEnumerable ??; + + [ProtoMember(1)] + public IEnumerable AccountMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(2)] + public IEnumerable SymbolMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(3)] + public IEnumerable AssetsMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(4)] + public IEnumerable ExchangeMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(5)] + public IEnumerable DayBars + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(7)] + public IEnumerable AssetBalances + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(8)] + public IEnumerable CryptoAccounts + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(9)] + public IEnumerable PositionMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(10)] + public IEnumerable OpenOrdersMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(11)] + public IEnumerable OpenDeliveredAssetMessages + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(12)] + public IEnumerable OptionSeries + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + [ProtoMember(13)] + public IEnumerable SessionsContainers + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = enumerable; + } + } + + public SnapshotData() + { + AccountMessages = new List(); + OpenOrdersMessages = new List(); + PositionMessages = new List(); + OpenDeliveredAssetMessages = new List(); + CryptoAccounts = new List(); + AssetBalances = new List(); + OptionSeries = new List(); + SessionsContainers = new List(); + } + + public static SnapshotData Create(IEnumerable symbolItems, IEnumerable uniqueAssets, IEnumerable uniqueExchanges, IEnumerable dayBars, IEnumerable accounts, IEnumerable cryptoAccounts, IEnumerable assetBalances, IEnumerable messageOptionSeries, IEnumerable sessionsData, IDictionary idsMap, IDictionary idsMap1) + { + foreach (KeyValuePair item in idsMap) + { + item.Value.Id = item.Key; + } + foreach (KeyValuePair item2 in idsMap1) + { + item2.Value.SymbolId = item2.Key; + } + return Create(symbolItems, uniqueAssets, uniqueExchanges, dayBars, accounts, cryptoAccounts, assetBalances, messageOptionSeries, sessionsData); + } + + public static SnapshotData Create(IEnumerable symbolItems, IEnumerable uniqueAssets, IEnumerable uniqueExchanges, IEnumerable dayBars, IEnumerable accounts, IEnumerable cryptoAccounts, IEnumerable assetBalances, IEnumerable messageOptionSeries, IEnumerable sessionsData) + { + return new SnapshotData + { + SymbolMessages = symbolItems, + DayBars = dayBars, + AssetsMessages = uniqueAssets, + ExchangeMessages = uniqueExchanges, + AccountMessages = accounts, + CryptoAccounts = cryptoAccounts, + AssetBalances = assetBalances, + OptionSeries = messageOptionSeries, + SessionsContainers = sessionsData + }; + } + + public static SnapshotData Create(Connection connection) + { + return new SnapshotData + { + AccountMessages = (from P_0 in connection.BusinessObjects.Accounts + where !(P_0 is CryptoAccount) + select ((IMessageBuilder)P_0).BuildMessage()).ToArray(), + CryptoAccounts = (from P_0 in connection.BusinessObjects.Accounts.OfType() + select ((IMessageBuilder)P_0).BuildMessage()).ToArray(), + AssetBalances = (from P_0 in connection.BusinessObjects.Accounts.OfType().SelectMany((CryptoAccount P_0) => P_0.Balances) + select P_0.BuildMessage()).ToArray(), + AssetsMessages = connection.BusinessObjects.Assets.Select((Asset P_0) => ((IMessageBuilder)P_0).BuildMessage()).ToArray(), + ExchangeMessages = connection.BusinessObjects.Exchanges.Select((Exchange P_0) => ((IMessageBuilder)P_0).BuildMessage()).ToArray(), + SymbolMessages = connection.BusinessObjects.Symbols.Select((Symbol P_0) => ((IMessageBuilder)P_0).BuildMessage()).ToArray(), + DayBars = connection.BusinessObjects.Symbols.Select((Symbol P_0) => ((IMessageBuilder)P_0).BuildMessage()).ToArray(), + OpenOrdersMessages = connection.BusinessObjects.Orders.Select((Order P_0) => P_0.BuildMessage()).ToArray(), + PositionMessages = connection.BusinessObjects.Positions.Select((Position P_0) => P_0.BuildMessage()).ToArray(), + OpenDeliveredAssetMessages = connection.BusinessObjects.DeliveredAssets.Select((DeliveredAsset P_0) => P_0.BuildMessage()).ToArray(), + SessionsContainers = connection.??.TradingSessions.Values.Select((SessionsContainer P_0) => P_0.BuildMessage()).ToArray() + }; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + List list = new List(); + foreach (XElement item in xElement.Elements()) + { + MessageAsset messageAsset = new MessageAsset(); + messageAsset.FromXElement(item, deserializationInfo); + list.Add(messageAsset); + } + AssetsMessages = list; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + List list2 = new List(); + foreach (XElement item2 in xElement2.Elements()) + { + MessageExchange messageExchange = new MessageExchange(); + messageExchange.FromXElement(item2, deserializationInfo); + list2.Add(messageExchange); + } + ExchangeMessages = list2; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + List list3 = new List(); + foreach (XElement item3 in xElement3.Elements()) + { + MessageAccount messageAccount = new MessageAccount(); + messageAccount.FromXElement(item3, deserializationInfo); + list3.Add(messageAccount); + } + AccountMessages = list3; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + string name = typeof(MessageSymbol).Name; + List list4 = new List(); + foreach (XElement item4 in xElement4.Elements()) + { + try + { + MessageSymbol messageSymbol = new MessageSymbol(string.Empty); + if (item4.Name == name) + { + messageSymbol.FromXElement(item4, deserializationInfo); + } + else + { + XElement xElement5 = item4.Element(name); + if (xElement5 != null) + { + messageSymbol.FromXElement(xElement5, deserializationInfo); + } + } + list4.Add(messageSymbol); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + SymbolMessages = list4; + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + List list5 = new List(); + foreach (XElement item5 in xElement6.Elements()) + { + MessageOptionSerie messageOptionSerie = new MessageOptionSerie(); + messageOptionSerie.FromXElement(item5, deserializationInfo); + list5.Add(messageOptionSerie); + } + OptionSeries = list5; + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + List list6 = new List(); + foreach (XElement item6 in xElement7.Elements()) + { + DayBar dayBar = new DayBar(string.Empty, Core.Instance.TimeUtils.DateTimeUtcNow); + dayBar.FromXElement(item6, deserializationInfo); + list6.Add(dayBar); + } + DayBars = list6; + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + List list7 = new List(); + foreach (XElement item7 in xElement8.Elements()) + { + MessageCryptoAccount messageCryptoAccount = new MessageCryptoAccount(); + messageCryptoAccount.FromXElement(item7, deserializationInfo); + list7.Add(messageCryptoAccount); + } + CryptoAccounts = list7; + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + List list8 = new List(); + foreach (XElement item8 in xElement9.Elements()) + { + MessageCryptoAssetBalances messageCryptoAssetBalances = new MessageCryptoAssetBalances(); + messageCryptoAssetBalances.FromXElement(item8, deserializationInfo); + list8.Add(messageCryptoAssetBalances); + } + AssetBalances = list8; + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + List list9 = new List(); + foreach (XElement item9 in xElement10.Elements()) + { + MessageOpenOrder messageOpenOrder = new MessageOpenOrder(); + messageOpenOrder.FromXElement(item9, deserializationInfo); + list9.Add(messageOpenOrder); + } + OpenOrdersMessages = list9; + } + XElement xElement11 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + List list10 = new List(); + foreach (XElement item10 in xElement11.Elements()) + { + MessageOpenPosition messageOpenPosition = new MessageOpenPosition(); + messageOpenPosition.FromXElement(item10, deserializationInfo); + list10.Add(messageOpenPosition); + } + PositionMessages = list10; + } + XElement xElement12 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + List list11 = new List(); + foreach (XElement item11 in xElement12.Elements()) + { + MessageOpenDeliveredAsset messageOpenDeliveredAsset = new MessageOpenDeliveredAsset(); + messageOpenDeliveredAsset.FromXElement(item11, deserializationInfo); + list11.Add(messageOpenDeliveredAsset); + } + OpenDeliveredAssetMessages = list11; + } + XElement xElement13 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement13 == null) + { + return; + } + List list12 = new List(); + foreach (XElement item12 in xElement13.Elements()) + { + MessageSessionsContainer messageSessionsContainer = new MessageSessionsContainer(); + messageSessionsContainer.FromXElement(item12, deserializationInfo); + list12.Add(messageSessionsContainer); + } + SessionsContainers = list12; + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), typeof(SnapshotData).Name)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageAsset assetsMessage in AssetsMessages) + { + xElement2.Add(assetsMessage.ToXElement()); + } + xElement.Add(xElement2); + XElement xElement3 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageExchange exchangeMessage in ExchangeMessages) + { + xElement3.Add(exchangeMessage.ToXElement()); + } + xElement.Add(xElement3); + XElement xElement4 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + XElement xElement5 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageAccount accountMessage in AccountMessages) + { + if (accountMessage is MessageCryptoAccount) + { + xElement5.Add(accountMessage.ToXElement()); + } + else + { + xElement4.Add(accountMessage.ToXElement()); + } + } + xElement.Add(xElement4); + xElement.Add(xElement5); + XElement xElement6 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageSymbol symbolMessage in SymbolMessages) + { + xElement6.Add(symbolMessage.ToXElement()); + } + xElement.Add(xElement6); + XElement xElement7 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageOptionSerie item in OptionSeries) + { + xElement7.Add(item.ToXElement()); + } + xElement.Add(xElement7); + XElement xElement8 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (DayBar dayBar in DayBars) + { + xElement8.Add(dayBar.ToXElement()); + } + xElement.Add(xElement8); + XElement xElement9 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageCryptoAssetBalances assetBalance in AssetBalances) + { + xElement9.Add(assetBalance.ToXElement()); + } + xElement.Add(xElement9); + XElement xElement10 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageOpenOrder openOrdersMessage in OpenOrdersMessages) + { + xElement10.Add(openOrdersMessage.ToXElement()); + } + xElement.Add(xElement10); + XElement xElement11 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageOpenPosition positionMessage in PositionMessages) + { + xElement11.Add(positionMessage.ToXElement()); + } + xElement.Add(xElement11); + XElement xElement12 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageOpenDeliveredAsset openDeliveredAssetMessage in OpenDeliveredAssetMessages) + { + xElement12.Add(openDeliveredAssetMessage.ToXElement()); + } + xElement.Add(xElement12); + XElement xElement13 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (MessageSessionsContainer sessionsContainer in SessionsContainers) + { + xElement13.Add(sessionsContainer.ToXElement()); + } + xElement.Add(xElement13); + return xElement; + } + } + public class DeserializationInfo + { + [CompilerGenerated] + private double ??; + + private readonly Func ??; + + public double Version + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + private DeserializationInfo() + { + Version = 1.0; + } + + public DeserializationInfo(Func fabric) + : this() + { + ?? = fabric; + } + + public IXElementSerialization CreateObject(XElement node) + { + try + { + return ???.Invoke(node); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex.Message, LoggingLevel.Verbose); + return null; + } + } + } + public static class Serializer + { + private const double ?? = 1.3; + + /// + /// Version 1.1: ?????????? ????? ?????? ? ??????????: ????? ???????? ????????? ???????? + /// + public const double VERSION_NEW_CONNECTIONS_SCHEMA = 1.1; + + public const double VERSION_CHANGE_ENCRYPTION_KEY_SCHEMA = 1.2; + + public const double VERSION_CHANGE_DATE_TIME_SERIALIZATION_FORMAT = 1.3; + + public const double VERSION_CHANGE_HOTKEYS_SETTING_ITEM_CLASS_NAME = 1.4; + + public const string CORE_SERIALIZATION_NAMESPACE_NAME = "TradingPlatform"; + + public static bool SerializeXML(string filePath, List list) + { + try + { + XElement xElement = ?(list); + if (xElement != null) + { + xElement.Save(filePath); + return true; + } + return false; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + return false; + } + } + + public static bool SerializeXML(Stream stream, List list) + { + try + { + XElement xElement = ?(list); + if (xElement != null) + { + xElement.Save(stream); + return true; + } + return false; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + return false; + } + } + + public static List DeserializeXML(string filePath, out double version, Func fabric) + { + List result = new List(); + version = 1.3; + if (string.IsNullOrEmpty(filePath)) + { + return result; + } + if (!File.Exists(filePath)) + { + return result; + } + FileStream fileStream = null; + try + { + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + result = DeserializeXML(fileStream, out version, fabric); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + fileStream?.Close(); + } + return result; + } + + public static List DeserializeXML(Stream stream, out double version, Func fabric) + { + List list = new List(); + version = 1.3; + if (stream == null) + { + return list; + } + try + { + XElement xElement = XElement.Load(stream); + DeserializationInfo deserializationInfo = new DeserializationInfo(fabric); + if (double.TryParse(xElement.Attribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()).Value, NumberStyles.Float, CultureInfo.InvariantCulture, out version)) + { + deserializationInfo.Version = version; + } + foreach (XElement item in xElement.Nodes()) + { + IXElementSerialization iXElementSerialization = DeserializeNode(item, deserializationInfo); + if (iXElementSerialization != null) + { + list.Add(iXElementSerialization); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return list; + } + + public static IEnumerable DeserializeXML(XElement element, DeserializationInfo info) + { + foreach (XElement item in element.Nodes()) + { + IXElementSerialization iXElementSerialization = DeserializeNode(item, info); + if (iXElementSerialization != null) + { + yield return iXElementSerialization; + } + } + } + + public static IXElementSerialization DeserializeNode(XElement node, DeserializationInfo info) + { + try + { + IXElementSerialization iXElementSerialization = info.CreateObject(node); + iXElementSerialization?.FromXElement(node, info); + return iXElementSerialization; + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + return null; + } + + private static XElement ?(List P_0) + { + try + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), new XAttribute(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), 1.3)); + for (int i = 0; i < P_0.Count; i++) + { + try + { + xElement.Add(P_0[i].ToXElement()); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + return xElement; + } + catch (Exception ex2) + { + Core.Instance.Loggers.Log(ex2); + return null; + } + } + } + [ProtoContract] + public sealed class TypedObjectSurrogate : TypedObjectSurrogate + { + [CompilerGenerated] + private T ??; + + [ProtoIgnore] + public override object ObjectValue => Value; + + [ProtoMember(1)] + public T Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TypedObjectSurrogate() + { + } + + public TypedObjectSurrogate(T value) + { + Value = value; + } + } + [ProtoContract] + public abstract class TypedObjectSurrogate + { + [ProtoIgnore] + public abstract object ObjectValue { get; } + + public static object CreateSurrogate(T value) + { + if (value == null) + { + return new TypedObjectSurrogate(); + } + Type type = value.GetType(); + if (type == typeof(T)) + { + return new TypedObjectSurrogate(value); + } + return Activator.CreateInstance(typeof(TypedObjectSurrogate<>).MakeGenericType(type), value); + } + } +} +namespace TradingPlatform.BusinessLayer.Abstractions +{ + public interface IVwapHistoryItem : IHistoryItem, ICloneable + { + /// + /// + /// + int RangeIndex { get; } + + /// + /// + /// + new DateTime TimeLeft { get; } + + /// + /// Get VWAP value + /// + double Value { get; } + + /// + /// + /// + double STDCoefficient { get; } + + /// + /// + /// + double CumulativeVolume { get; } + + /// + /// + /// + double CumulativePriceMVolume { get; } + + /// + /// + /// + double MPDCoefficient { get; } + } +} +namespace TradingPlatform.BusinessLayer.Abstractions.Misc +{ + public interface ITaskSchedulerProvider + { + TaskScheduler TaskScheduler { get; } + } +} +namespace TradingPlatform.BusinessLayer.Integration +{ + public interface IBrowser + { + string BrowserTitle { get; set; } + + Size BrowerSize { get; set; } + + event BrowserEventHandler Navigated; + + event BrowserEventHandler Closed; + + void Show(); + + void Close(); + + void Navigate(string address); + } + public delegate void BrowserEventHandler(IBrowser browser, BrowserEventArgs e); + public interface IBrowserFactory + { + IBrowser CreateBrowser(string url = null); + } + public interface IHistoryVendor : IVendor + { + HistoryMetadata GetHistoryMetadata(CancellationToken cancelationToken); + + IList LoadHistory(HistoryRequestParameters requestParameters); + } + public interface IMessageBuilder where TMessage : Message + { + TMessage BuildMessage(); + } + public interface INeedSymbolToPocess + { + string SymbolId { get; } + } + public interface IQuoteVendor : IVendor + { + void SubscribeSymbol(SubscribeQuotesParameters parameters); + + void UnSubscribeSymbol(SubscribeQuotesParameters parameters); + } + public interface ISymbolVendor : IVendor + { + bool AllowNonFixedList { get; } + + IList GetSessions(CancellationToken token); + + IList GetExchanges(CancellationToken token); + + IList GetAssets(CancellationToken token); + + IList GetSymbols(CancellationToken token); + + MessageSymbolTypes GetSymbolTypes(CancellationToken token); + + IList GetSymbolGroups(CancellationToken token); + + MessageSymbol GetNonFixedSymbol(GetSymbolRequestParameters requestParameters); + + IList SearchSymbols(SearchSymbolsRequestParameters requestParameters); + + IList GetFutureContracts(GetFutureContractsRequestParameters requestParameters); + + IList GetOptionSeries(GetOptionSeriesRequestParameters requestParameters); + + IList GetStrikes(GetStrikesRequestParameters requestParameters); + } + public interface ITradingVendor : IVendor + { + LimitationMetadata GetLimitationMetadata(); + + IList GetAccounts(CancellationToken token); + + IList GetCryptoAssetBalances(CancellationToken token); + + IList GetRules(CancellationToken token); + + IList GetAccountOperations(CancellationToken token); + + IList GetAllowedOrderTypes(CancellationToken token); + + IList GetPendingOrders(CancellationToken token); + + IList GetPositions(CancellationToken token); + + TradesHistoryMetadata GetTradesMetadata(); + + IList GetTrades(TradesHistoryRequestParameters parameters); + + void GetTrades(TradesHistoryRequestParameters parameters, AccountTradesLoadingCallback callback); + + IList GetOrdersHistory(OrdersHistoryRequestParameters parameters); + + PnL CalculatePnL(PnLRequestParameters parameters); + + TradingOperationResult PlaceOrder(PlaceOrderRequestParameters parameters); + + TradingOperationResult PlaceMultiOrder(PlaceMultiOrderOrderRequestParameters parameters); + + TradingOperationResult ModifyOrder(ModifyOrderRequestParameters parameters); + + TradingOperationResult CancelOrder(CancelOrderRequestParameters parameters); + + TradingOperationResult ClosePosition(ClosePositionRequestParameters parameters); + + MarginInfo GetMarginInfo(OrderRequestParameters orderRequestParameters); + + IList GetReportsMetaData(CancellationToken token); + + Report GenerateReport(ReportRequestParameters reportRequestParameters); + } + public interface IVendor + { + string Key { get; set; } + + event EventHandler NewMessage; + + ConnectionResult Connect(ConnectRequestParameters connectRequestParameters); + + void Disconnect(); + + void OnConnected(CancellationToken token); + + PingResult Ping(); + + void PushMessage(Message msg); + + void SendCustomRequest(RequestParameters parameters); + } + public interface IVolumeAnalysisVendor : IVendor + { + VolumeAnalysisMetadata GetVolumeAnalysisMetadata(); + + VendorVolumeAnalysisByPeriodResponse LoadVolumeAnalysis(VolumeAnalysisByPeriodRequestParameters requestParameters); + } + public class BrowserEventArgs : EventArgs + { + [CompilerGenerated] + private string ??; + + public string Url + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public BrowserEventArgs(string url = null) + { + Url = url; + } + } + public class ConnectionLogger + { + private readonly ILogger ??; + + public ConnectionLogger(string vendorName, string connectionId) + { + string outputFolderPath = Path.Combine(Const.LOGS_FOLDER_PATH, vendorName, connectionId); + ?? = Core.Instance.Loggers.GetLogger(new LoggerConfig + { + LoggerName = connectionId, + OutputFolderPath = outputFolderPath, + Scope = LoggerScope.General + }); + } + + public void Log(string message) + { + ???.Log(message, Core.Instance.TimeUtils.DateTimeUtcNow, LoggingLevel.Verbose); + } + + public void Dispose() + { + ???.Dispose(); + } + } + /// + /// Vendor connection respond bundle + /// + [ProtoContract] + public sealed class ConnectionResult : ICloneable + { + [CompilerGenerated] + private ConnectionState ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private IList ??; + + /// + /// The connection status + /// + [ProtoMember(1)] + public ConnectionState State + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// The respond message + /// + [ProtoMember(2)] + public string Message + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public bool Cancelled + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList UpdatedSettings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public static ConnectionResult CreateFail(string message, IList updatedSettings = null) + { + return new ConnectionResult + { + State = ConnectionState.Fail, + Message = message, + UpdatedSettings = updatedSettings + }; + } + + public static ConnectionResult CreateSuccess(string message = "", IList updatedSettings = null) + { + return new ConnectionResult + { + State = ConnectionState.Connected, + Message = message, + UpdatedSettings = updatedSettings + }; + } + + public static ConnectionResult CreateCancelled(string message = "") + { + return new ConnectionResult + { + State = ConnectionState.Fail, + Message = message, + Cancelled = true + }; + } + + public object Clone() + { + return new ConnectionResult + { + State = State, + Message = Message, + Cancelled = Cancelled + }; + } + } + [ProtoContract] + public sealed class ConnectRequestParameters : RequestParameters + { + [CompilerGenerated] + private IList ??; + + [CompilerGenerated] + private IBrowserFactory ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IProgress ??; + + public override RequestType Type => RequestType.Connect; + + [ProtoMember(1)] + public IList ConnectionSettings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = list; + } + } + + public IBrowserFactory BrowserFactory + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = browserFactory; + } + } + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public IProgress ConnectingProgress + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = progress; + } + } + + public ConnectRequestParameters() + { + } + + public ConnectRequestParameters(IList connectionSettings) + { + ConnectionSettings = connectionSettings; + } + } +} +namespace ? +{ + internal class ? : BufferedProcessor + { + public int ??; + + private readonly Dictionary ??; + + public Action ??; + + public Func> ??; + + public ?() + { + ?? = new Dictionary(); + } + + public void ?() + { + ProcessTreadsCount = ??; + } + + protected override void Process(DayBarMessageGenerationParameters subject) + { + try + { + CancellationToken token; + lock (??) + { + if (??.TryGetValue(subject.SymbolId, out var value)) + { + value.Cancel(); + } + value = new CancellationTokenSource(); + ??[subject.SymbolId] = value; + token = value.Token; + } + if (!token.IsCancellationRequested) + { + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + HistoryRequestParameters arg = new HistoryRequestParameters + { + SymbolId = subject.SymbolId, + FromTime = dateTimeUtcNow.Date.AddDays(0L - (long)subject.DayToLoadCount).AddMilliseconds(-1.0), + ToTime = dateTimeUtcNow, + Aggregation = new HistoryAggregationTime(new Period(BasePeriod.Day, 1), subject.UpdateHistoryType), + CancellationToken = token + }; + IList list = ???.Invoke(arg); + if (list != null && list.Count != 0 && !token.IsCancellationRequested) + { + ? ?2 = new ?(subject.SymbolId) + { + UpdateHistoryType = subject.UpdateHistoryType + }; + ?2.?(token, subject.SymbolId, list); + ???.Invoke(?2); + ??.Remove(subject.SymbolId); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + subject?.Callback?.Invoke(); + } + } + + protected internal override void Clear() + { + foreach (CancellationTokenSource value in ??.Values) + { + value.Cancel(); + } + base.Clear(); + } + } +} +namespace TradingPlatform.BusinessLayer.Integration +{ + public abstract class DayBarMessageCreator : IDayBarUpdate, IDisposable + { + public Action PushMessage; + + private protected ConcurrentDictionary ??; + + private bool ??; + + public virtual void Initialize() + { + ?? = new ConcurrentDictionary(); + } + + public void TryCreateEmptyDb(string symbol, HistoryType updateType) + { + if (!??.TryGetValue(symbol, out var value)) + { + value = new ?(symbol) + { + UpdateHistoryType = updateType + }; + ??[symbol] = value; + } + PushMessage?.Invoke(value.LastDayBar); + } + + public DayBar ProcessQuote(Quote quote1) + { + if (!??.TryGetValue(quote1.SymbolId, out var value)) + { + return null; + } + return value.ProcessQuote(quote1); + } + + public DayBar ProcessLast(Last last) + { + if (!??.TryGetValue(last.SymbolId, out var value)) + { + return null; + } + return value.ProcessLast(last); + } + + public DayBar ProcessMark(Mark mark) + { + if (!??.TryGetValue(mark.SymbolId, out var value)) + { + return null; + } + return value.ProcessMark(mark); + } + + public abstract void CreateDbFromHistory(string symbol, HistoryType updateType, Action callback = null); + + public void CheckIfNeedUpdate() + { + if (??) + { + return; + } + ?? = true; + try + { + foreach (KeyValuePair item in new Dictionary(??)) + { + string key = item.Key; + ? value = item.Value; + if ((Core.Instance.TimeUtils.DateTimeUtcNow - value.LastDayBarCreationTime).TotalDays > 1.0) + { + CreateDbFromHistory(key, value.UpdateHistoryType); + } + } + } + finally + { + ?? = false; + } + } + + public virtual void Dispose() + { + ???.Clear(); + } + } +} +namespace ? +{ + internal class ? : IDayBarUpdate + { + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private HistoryType ??; + + [CompilerGenerated] + private DayBar ??; + + public DateTime LastDayBarCreationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dateTime; + } + } + + public HistoryType UpdateHistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = historyType; + } + } + + internal string SymbolId => LastDayBar?.SymbolId; + + internal DayBar LastDayBar + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dayBar; + } + } + + internal ?(string P_0) + { + LastDayBar = new DayBar(P_0, Core.Instance.TimeUtils.DateTimeUtcNow); + } + + internal void ?(CancellationToken P_0, string P_1, IList P_2) + { + DayBar dayBar = null; + try + { + if (P_0.IsCancellationRequested || P_2 == null || !P_2.Any()) + { + return; + } + IHistoryItem historyItem = P_2[P_2.Count - 1]; + if (historyItem == null) + { + return; + } + TimeSpan timeSpan = Core.Instance.TimeUtils.DateTimeUtcNow - historyItem.TimeLeft; + LastDayBarCreationTime = historyItem.TimeLeft.AddDays((int)timeSpan.TotalDays); + dayBar = new DayBar(P_1, Core.Instance.TimeUtils.DateTimeUtcNow) + { + Open = historyItem[PriceType.Open], + High = historyItem[PriceType.High], + Low = historyItem[PriceType.Low], + Volume = historyItem[PriceType.Volume], + QuoteAssetVolume = historyItem[PriceType.QuoteAssetVolume] + }; + if (UpdateHistoryType == HistoryType.Last) + { + dayBar.Trades = (long)historyItem[PriceType.Ticks]; + } + else + { + dayBar.Ticks = (long)historyItem[PriceType.Ticks]; + } + if (P_2.Count > 1) + { + dayBar.PreviousClose = P_2[P_2.Count - 2][PriceType.Close]; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + LastDayBar = dayBar; + } + + public DayBar ProcessQuote(Quote quote1) + { + DayBar lastDayBar = LastDayBar; + if (lastDayBar == null) + { + return null; + } + if (UpdateHistoryType switch + { + HistoryType.Ask => ?(lastDayBar, quote1.Ask) ? 1 : 0, + HistoryType.Bid => ?(lastDayBar, quote1.Bid) ? 1 : 0, + HistoryType.Midpoint => ?(lastDayBar, (quote1.Ask + quote1.Bid) / 2.0) ? 1 : 0, + _ => 0, + } == 0) + { + return null; + } + return lastDayBar; + } + + public DayBar ProcessLast(Last last) + { + bool flag = false; + DayBar lastDayBar = LastDayBar; + if (lastDayBar == null) + { + return null; + } + if (UpdateHistoryType == HistoryType.Last) + { + flag = ?(lastDayBar, last.Price); + } + if (!flag) + { + return null; + } + return lastDayBar; + } + + public DayBar ProcessMark(Mark mark) + { + bool flag = false; + DayBar lastDayBar = LastDayBar; + if (lastDayBar == null) + { + return null; + } + if (UpdateHistoryType == HistoryType.Mark) + { + flag = ?(lastDayBar, mark.Price); + } + if (!flag) + { + return null; + } + return lastDayBar; + } + + private static bool ?(DayBar P_0, double P_1) + { + bool result = false; + if (double.IsNaN(P_0.High) || P_0.High < P_1) + { + P_0.High = P_1; + result = true; + } + if (double.IsNaN(P_0.Low) || P_0.Low > P_1) + { + P_0.Low = P_1; + result = true; + } + return result; + } + } +} +namespace TradingPlatform.BusinessLayer.Integration +{ + public class DayBarMessageFromHistoryCreator : DayBarMessageCreator + { + private const int ?? = 5; + + public Func> LoadHistory; + + [CompilerGenerated] + private Action ??; + + public int GenerationThreadsCount; + + private readonly ? ??; + + public Action CorrectDayBar + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DayBarMessageFromHistoryCreator() + { + ?? = new ?(); + GenerationThreadsCount = 3; + } + + public override void Initialize() + { + base.Initialize(); + ??.?? = LoadHistory; + ??.?? = GenerationThreadsCount; + ??.?? = ?; + ??.?(); + ??.Start(); + } + + public override void CreateDbFromHistory(string symbol, HistoryType updateType, Action callback = null) + { + DayBarMessageGenerationParameters subject = new DayBarMessageGenerationParameters + { + SymbolId = symbol, + UpdateHistoryType = updateType, + DayToLoadCount = 5u, + Callback = callback + }; + ??.Push(subject); + } + + private void ?(? P_0) + { + DayBar lastDayBar = P_0.LastDayBar; + CorrectDayBar?.Invoke(lastDayBar); + ??[P_0.SymbolId] = P_0; + PushMessage?.Invoke(lastDayBar); + } + + public override void Dispose() + { + ???.Stop(); + base.Dispose(); + } + } + public class DayBarMessageGenerationParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private HistoryType ??; + + [CompilerGenerated] + private uint ??; + + [CompilerGenerated] + private Action ??; + + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryType UpdateHistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public uint DayToLoadCount + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Action Callback + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public interface IDayBarUpdate + { + DayBar ProcessQuote(Quote quote1); + + DayBar ProcessLast(Last last); + + DayBar ProcessMark(Mark mark); + } + /// + /// Ping state dictum + /// + public enum PingEnum + { + /// + /// Ping signals connected + /// + Connected, + /// + /// Ping signals disconnected + /// + Disconnected + } + public enum VolumeAnalysisAvailability + { + NotAvailable, + Available + } + /// + /// The asset formatting description. + /// + public class AssetFormattingDescription : FormattingDescription + { + private readonly string ??; + + private readonly bool ??; + + /// + /// Initializes a new instance of the class. + /// + /// The asset id. + /// The value. + /// If true, add currency name. + public AssetFormattingDescription(string assetId, double value, bool addCurrencyName = true) + : base(value) + { + ?? = assetId; + ?? = addCurrencyName; + } + + protected override bool IsValueValid(double value) + { + if (!double.IsNaN(value)) + { + return base.IsValueValid(value); + } + return false; + } + + protected override string FormatValue(double value) + { + Asset asset = Core.Instance.Connections[base.ConnectionId]?.BusinessObjects?.Assets.FirstOrDefault((Asset P_0) => P_0.Id == ??); + if (asset == null) + { + return value.Format(); + } + if (!??) + { + return asset.FormatPrice(value); + } + return asset.FormatPriceWithCurrency(value); + } + + [CompilerGenerated] + private bool ?(Asset P_0) + { + return P_0.Id == ??; + } + } + public class DateTimeFormattingDescription : FormattingDescription + { + public DateTimeFormattingDescription(DateTime dateTime) + : base(dateTime) + { + } + + protected override string FormatValue(DateTime value) + { + return Core.Instance.TimeUtils.ConvertFromUTCToSelectedTimeZone(value).ToString(Core.Instance.TimeUtils.CultureInfo); + } + } + public abstract class FormattingDescription : IFormattingDescription + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private readonly bool ??; + + private readonly TValue ??; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AllowFormatDefaultValue + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + protected virtual TValue DefaultValue => default(TValue); + + protected FormattingDescription(TValue value) + { + ?? = value; + } + + public string GetFormattedData() + { + if (!IsValueValid(??)) + { + return string.Empty; + } + return FormatValue(??); + } + + protected virtual bool IsValueValid(TValue value) + { + if (!AllowFormatDefaultValue) + { + return !object.Equals(DefaultValue, ??); + } + return true; + } + + protected abstract string FormatValue(TValue value); + } + public interface IFormattingDescription + { + string ConnectionId { get; set; } + + string GetFormattedData(); + } + public class OffsetFormattingDescription : FormattingDescription + { + private readonly string ??; + + public OffsetFormattingDescription(double offset, string symbolId) + : base(offset) + { + ?? = symbolId; + } + + protected override bool IsValueValid(double value) + { + if (!double.IsNaN(value)) + { + return base.IsValueValid(value); + } + return false; + } + + protected override string FormatValue(double value) + { + Symbol symbol = Core.Instance.Connections[base.ConnectionId]?.BusinessObjects?.Symbols?.FirstOrDefault((Symbol P_0) => P_0.Id == ??); + if (symbol == null) + { + return value.ToString(CultureInfo.InvariantCulture); + } + return symbol.FormatOffset(value, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + [CompilerGenerated] + private bool ?(Symbol P_0) + { + return P_0.Id == ??; + } + } + public class OrderTypeNameFormattingDescription : FormattingDescription + { + public OrderTypeNameFormattingDescription(string orderTypeId) + : base(orderTypeId) + { + } + + protected override string FormatValue(string value) + { + return Core.Instance.GetOrderType(value, base.ConnectionId)?.Name ?? value; + } + } + public class PriceFormattingDescription : FormattingDescription + { + private readonly string ??; + + public PriceFormattingDescription(double price, string symbolId) + : base(price) + { + ?? = symbolId; + } + + protected override bool IsValueValid(double value) + { + if (!double.IsNaN(value)) + { + return base.IsValueValid(value); + } + return false; + } + + protected override string FormatValue(double value) + { + Symbol symbol = Core.Instance.Connections[base.ConnectionId]?.BusinessObjects?.Symbols?.FirstOrDefault((Symbol P_0) => P_0.Id == ??); + if (symbol != null) + { + return symbol.FormatPrice(value); + } + return value.ToString(CultureInfo.InvariantCulture); + } + + [CompilerGenerated] + private bool ?(Symbol P_0) + { + return P_0.Id == ??; + } + } + public class SlTpHolderFormattingDescription : FormattingDescription + { + private readonly string ??; + + public SlTpHolderFormattingDescription(SlTpHolder slTpHolder, string symbolId) + : base(slTpHolder) + { + ?? = symbolId; + } + + protected override string FormatValue(SlTpHolder value) + { + Symbol symbol = Core.Instance.Connections[base.ConnectionId]?.BusinessObjects?.Symbols?.FirstOrDefault((Symbol P_0) => P_0.Id == ??); + return value.Format(symbol); + } + + [CompilerGenerated] + private bool ?(Symbol P_0) + { + return P_0.Id == ??; + } + } + public class SymbolNameFormattingDescription : FormattingDescription + { + public SymbolNameFormattingDescription(string symbolId) + : base(symbolId) + { + } + + protected override string FormatValue(string value) + { + return Core.Instance.GetSymbol(new GetSymbolRequestParameters + { + SymbolId = value + }, base.ConnectionId, NonFixedListDownload.IgnoreDownload)?.Name ?? value; + } + } + public class VolumeFormattingDescription : FormattingDescription + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + private readonly string ??; + + public bool DisplayQuantityInLots + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AbbreviateVolumes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VolumeFormattingDescription(double volume, string symbolId) + : base(volume) + { + ?? = symbolId; + } + + protected override bool IsValueValid(double value) + { + if (!double.IsNaN(value)) + { + return base.IsValueValid(value); + } + return false; + } + + protected override string FormatValue(double value) + { + Symbol symbol = Core.Instance.Connections[base.ConnectionId]?.?(new GetSymbolRequestParameters + { + SymbolId = ?? + }, NonFixedListDownload.IgnoreDownload); + if (symbol != null) + { + return symbol.FormatQuantity(value, DisplayQuantityInLots, AbbreviateVolumes); + } + return value.ToString(CultureInfo.InvariantCulture); + } + } + /// + /// Mediates a history meta data with available data types and intervals on vendor side + /// + [ProtoContract] + public sealed class HistoryMetadata + { + [CompilerGenerated] + private string[] ??; + + [CompilerGenerated] + private Period[] ??; + + [CompilerGenerated] + private BasePeriod[] ??; + + [CompilerGenerated] + private HistoryType[] ??; + + [CompilerGenerated] + private HistoryType[] ??; + + [CompilerGenerated] + private Period[] ??; + + [CompilerGenerated] + private BasePeriod[] ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [ProtoMember(1)] + public string[] AllowedAggregations + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public Period[] AllowedPeriodsHistoryAggregationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public BasePeriod[] AllowedBasePeriodsHistoryAggregationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + public HistoryType[] AllowedHistoryTypesHistoryAggregationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public HistoryType[] AllowedHistoryTypesHistoryAggregationTick + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(6)] + public Period[] AllowedPeriodsHistoryAggregationTimeStatistics + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(7)] + public BasePeriod[] AllowedBasePeriodsHistoryAggregationTimeStatistics + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(8)] + public TimeSpan DownloadingStep_Tick + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(9)] + public TimeSpan DownloadingStep_Second + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(10)] + public TimeSpan DownloadingStep_Minute + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(11)] + public TimeSpan DownloadingStep_Day + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(12)] + public int DegreeOfParallelism + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(13, IsRequired = true)] + public bool UseHistoryLocalCache + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(14)] + public bool BuildUncompletedBars + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(15)] + public bool ServerSideTickDirectionAvailable + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + internal HistoryMetadata Copy => new HistoryMetadata(this); + + public HistoryMetadata() + { + AllowedAggregations = Array.Empty(); + AllowedPeriodsHistoryAggregationTime = Array.Empty(); + AllowedHistoryTypesHistoryAggregationTime = Array.Empty(); + AllowedHistoryTypesHistoryAggregationTick = Array.Empty(); + AllowedBasePeriodsHistoryAggregationTime = Array.Empty(); + AllowedPeriodsHistoryAggregationTimeStatistics = Array.Empty(); + AllowedBasePeriodsHistoryAggregationTimeStatistics = Array.Empty(); + DownloadingStep_Tick = TimeSpan.FromDays(10.0); + DownloadingStep_Second = TimeSpan.FromDays(10.0); + DownloadingStep_Minute = TimeSpan.FromDays(1000.0); + DownloadingStep_Day = TimeSpan.FromDays(10000.0); + DegreeOfParallelism = Environment.ProcessorCount; + UseHistoryLocalCache = true; + BuildUncompletedBars = false; + ServerSideTickDirectionAvailable = false; + } + + public HistoryMetadata(HistoryMetadata historyMetadata) + { + AllowedAggregations = new string[historyMetadata.AllowedAggregations.Length]; + Array.Copy(historyMetadata.AllowedAggregations, AllowedAggregations, historyMetadata.AllowedAggregations.Length); + AllowedPeriodsHistoryAggregationTime = new Period[historyMetadata.AllowedPeriodsHistoryAggregationTime.Length]; + Array.Copy(historyMetadata.AllowedPeriodsHistoryAggregationTime, AllowedPeriodsHistoryAggregationTime, AllowedPeriodsHistoryAggregationTime.Length); + AllowedBasePeriodsHistoryAggregationTime = new BasePeriod[historyMetadata.AllowedBasePeriodsHistoryAggregationTime.Length]; + Array.Copy(historyMetadata.AllowedBasePeriodsHistoryAggregationTime, AllowedBasePeriodsHistoryAggregationTime, historyMetadata.AllowedBasePeriodsHistoryAggregationTime.Length); + AllowedHistoryTypesHistoryAggregationTime = new HistoryType[historyMetadata.AllowedHistoryTypesHistoryAggregationTime.Length]; + Array.Copy(historyMetadata.AllowedHistoryTypesHistoryAggregationTime, AllowedHistoryTypesHistoryAggregationTime, historyMetadata.AllowedHistoryTypesHistoryAggregationTime.Length); + AllowedHistoryTypesHistoryAggregationTick = new HistoryType[historyMetadata.AllowedHistoryTypesHistoryAggregationTick.Length]; + Array.Copy(historyMetadata.AllowedHistoryTypesHistoryAggregationTick, AllowedHistoryTypesHistoryAggregationTick, historyMetadata.AllowedHistoryTypesHistoryAggregationTick.Length); + AllowedPeriodsHistoryAggregationTimeStatistics = new Period[historyMetadata.AllowedPeriodsHistoryAggregationTimeStatistics.Length]; + Array.Copy(historyMetadata.AllowedPeriodsHistoryAggregationTimeStatistics, AllowedPeriodsHistoryAggregationTimeStatistics, AllowedPeriodsHistoryAggregationTimeStatistics.Length); + AllowedBasePeriodsHistoryAggregationTimeStatistics = new BasePeriod[historyMetadata.AllowedBasePeriodsHistoryAggregationTimeStatistics.Length]; + Array.Copy(historyMetadata.AllowedBasePeriodsHistoryAggregationTimeStatistics, AllowedBasePeriodsHistoryAggregationTimeStatistics, historyMetadata.AllowedBasePeriodsHistoryAggregationTimeStatistics.Length); + DownloadingStep_Tick = historyMetadata.DownloadingStep_Tick; + DownloadingStep_Second = historyMetadata.DownloadingStep_Second; + DownloadingStep_Minute = historyMetadata.DownloadingStep_Minute; + DownloadingStep_Day = historyMetadata.DownloadingStep_Day; + DegreeOfParallelism = historyMetadata.DegreeOfParallelism; + UseHistoryLocalCache = historyMetadata.UseHistoryLocalCache; + BuildUncompletedBars = historyMetadata.BuildUncompletedBars; + ServerSideTickDirectionAvailable = historyMetadata.ServerSideTickDirectionAvailable; + } + + internal TimeSpan ?(HistoryAggregation P_0) + { + Period getPeriod = P_0.GetPeriod; + int basePeriod = (int)getPeriod.BasePeriod; + TimeSpan timeSpan; + long val; + if (basePeriod >= 4) + { + timeSpan = DownloadingStep_Day; + val = getPeriod.Ticks / Period.DAY1.Ticks; + } + else if (basePeriod >= 2) + { + timeSpan = DownloadingStep_Minute; + val = getPeriod.Ticks / Period.MIN1.Ticks; + } + else + { + if (basePeriod < 1) + { + if (getPeriod.BasePeriod == BasePeriod.Tick && getPeriod.PeriodMultiplier != 1) + { + return TimeSpan.Zero; + } + return DownloadingStep_Tick; + } + timeSpan = DownloadingStep_Second; + val = getPeriod.Ticks / Period.SECOND1.Ticks; + } + return TimeSpan.FromTicks(Math.Min(timeSpan.Ticks * Math.Max(val, 1L), 31536000000000000L)); + } + } + public static class SymbolDefaultDescriptions + { + public static string GetDefaultDescription(string symbolName) + { + switch (?.?(symbolName)) + { + case 1620419802u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1350845065u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 68008159u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2335563927u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3889859125u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2018644614u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3962463764u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4116658238u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1624907770u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1887691111u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2942542223u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2151569089u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1839836162u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1078471552u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2087596954u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1637628082u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3233654154u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2238471692u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3649218711u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2360299262u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 24114034u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1615521271u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 429890879u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1265226235u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 191367025u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1679457057u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2483540628u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3039026436u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3661938870u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2516370071u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2850936713u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 659044693u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4232868562u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1045659265u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3789443832u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 641760120u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 988355861u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4281617233u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 80800563u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 350375300u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 839191917u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1999194261u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4244775404u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4014714260u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2928008062u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1825504590u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2037013095u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1280195859u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1328771369u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3606328198u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2515488773u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 957338138u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3685275323u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 173045139u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1934807510u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 124375746u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2429247009u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3501247908u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3298783647u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4058670711u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3554264809u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2716707914u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3352170512u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 457013197u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 320108201u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1750896523u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2305573784u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2228121868u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3638868887u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1208142671u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3002305103u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2349949438u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 13764210u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 419541055u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2636366975u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1254876411u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1814557834u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 181017201u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2585813309u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1669107233u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2473190804u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3651589046u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2506020247u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2840586889u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 94341894u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 648694869u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4222518738u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 714960562u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1035309441u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 978006037u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2357959268u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2496842966u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3711978256u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2491396094u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3371260840u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2634575795u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3652951536u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3030116563u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3436039563u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3021718053u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 284478568u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2411620006u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3350668061u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2073801205u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1905909567u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2441366352u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4221599727u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2436215740u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1801439256u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2518774546u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2500097719u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3342045897u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3519432546u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2416749392u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3552124516u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2003830314u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2238933702u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 612031836u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2823409836u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 408419246u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3233745107u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2336395862u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1006372052u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 804040855u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 347237120u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3799182549u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1932694036u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2852934106u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 984865474u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1255225665u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3213535021u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1838176045u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2687288967u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3602322474u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3517448641u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 287284361u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3471409855u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1306488298u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3509434492u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2952591452u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4217526264u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 422909761u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2371299268u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 168257872u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 394422474u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1343306773u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1926913222u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3775114597u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2016932178u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1069676081u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3499941520u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4011922870u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3346963607u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3498891434u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 698744176u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 44668826u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3991148999u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3661345779u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1183670000u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2497369850u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3183129029u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 18060235u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2213786847u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3985953508u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4169618513u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3517981331u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3921296083u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2246776758u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1307284877u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1724953394u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1471925664u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1427930923u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 701623346u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4194627902u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3296676779u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4130881864u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2291264053u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2637100485u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 420402725u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2268114475u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2739153357u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 510157801u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1229808796u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2526228103u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 206975631u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3884664239u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2392630576u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3379624205u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 850190540u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3436469264u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 637122682u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 468120478u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1508096022u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1651264960u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2633683452u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 1648225525u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2706260476u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 401975857u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 78441955u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 2746663082u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 4007212653u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 628962940u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3134998797u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + case 3513957278u: + if (!(symbolName == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??())) + { + break; + } + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + return string.Empty; + } + } + public class MarginInfo + { + [CompilerGenerated] + private readonly SettingItem[] ??; + + public SettingItem[] Parameters + { + [CompilerGenerated] + get + { + return ??; + } + } + + public MarginInfo(SettingItem[] parameters) + { + ?? = parameters; + } + } + [ProtoContract] + public abstract class CustomMessage : Message, IBufferedProcessorValue, IConnectionBindedObject + { + [CompilerGenerated] + private string ??; + + public string ConnectionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + public abstract int MessageId { get; } + + public override MessageType Type => MessageType.Custom; + + public int Key => MessageId; + } + public enum MessageType + { + Account, + Symbol, + OpenOrder, + CloseOrder, + OpenPosition, + ClosePosition, + Trade, + Quote, + Level2, + Last, + DayBar, + Asset, + Custom, + DOM, + Exchange, + ReportMetadata, + SymbolTypes, + OrderHistory, + Rule, + DealTicket, + SymbolGroup, + CryptoAssetBalances, + CryptoAccount, + OptionSerie, + SymbolInfo, + Session, + OpenDeliveredAsset, + CloseDeliveredAsset, + CorporateAction, + AccountOperation, + ClosedPosition, + Mark, + NewsHeadline, + TradingSignal, + RemoveTradingSignal + } + public enum QuotePriceType + { + Bid, + Ask + } + public sealed class LicenceMessageRule : MessageRule + { + public override MessageType Type => MessageType.Rule; + + public LicenceMessageRule() + { + if (!?.?(Assembly.GetCallingAssembly().Location)) + { + throw new Exception(); + } + } + } + [Serializable] + [DataContract(Name = "Message", Namespace = "TradingPlatform")] + [KnownType(typeof(CustomMessage))] + [KnownType(typeof(MessageAccount))] + [KnownType(typeof(MessageAsset))] + [KnownType(typeof(MessageCloseOrder))] + [KnownType(typeof(MessageClosePosition))] + [KnownType(typeof(MessageExchange))] + [KnownType(typeof(MessageSymbol))] + [KnownType(typeof(MessageSymbolTypes))] + [KnownType(typeof(MessageOpenOrder))] + [KnownType(typeof(MessageOpenPosition))] + [KnownType(typeof(MessageReportType))] + [KnownType(typeof(MessageTrade))] + [KnownType(typeof(MessageQuote))] + [KnownType(typeof(MessageDealTicket))] + [KnownType(typeof(MessageRule))] + [KnownType(typeof(MessageOrderHistory))] + [ProtoContract] + [ProtoInclude(1, typeof(MessageAsset))] + [ProtoInclude(2, typeof(MessageAccount))] + [ProtoInclude(3, typeof(MessageSymbolInfo))] + [ProtoInclude(4, typeof(MessageSymbolTypes))] + [ProtoInclude(5, typeof(MessageExchange))] + [ProtoInclude(6, typeof(MessageQuote))] + [ProtoInclude(7, typeof(MessageOpenOrder))] + [ProtoInclude(8, typeof(MessageCloseOrder))] + [ProtoInclude(9, typeof(MessageOpenPosition))] + [ProtoInclude(10, typeof(MessageClosePosition))] + [ProtoInclude(11, typeof(MessageTrade))] + [ProtoInclude(12, typeof(MessageSessionsContainer))] + [ProtoInclude(13, typeof(MessageOptionSerie))] + [ProtoInclude(14, typeof(MessageCryptoAssetBalances))] + [ProtoInclude(15, typeof(MessageOpenDeliveredAsset))] + [ProtoInclude(16, typeof(CustomMessage))] + public abstract class Message + { + public abstract MessageType Type { get; } + + public override string ToString() + { + return Type.ToString(); + } + } + [DataContract(Name = "Account", Namespace = "TradingPlatform")] + [ProtoContract] + [ProtoInclude(1000, typeof(MessageCryptoAccount))] + public class MessageAccount : Message, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private NettingType ??; + + [CompilerGenerated] + private List ??; + + public override MessageType Type => MessageType.Account; + + [DataMember(Name = "ID")] + [ProtoMember(1)] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Name")] + [ProtoMember(2)] + public string AccountName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AssetId")] + [ProtoMember(3)] + public string AssetId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Balance")] + [ProtoMember(4)] + public double Balance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public NettingType NettingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(6)] + public List AccountAdditionalInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MessageAccount() + { + NettingType = NettingType.Undefined; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(25, 4); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(AccountId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(AccountName); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Balance); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AccountId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AccountName)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AssetId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Balance)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)NettingType)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (AccountAdditionalInfo != null) + { + foreach (AdditionalInfoItem item in AccountAdditionalInfo) + { + xElement2.Add(item.ToXElement()); + } + } + xElement.Add(xElement2); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + AccountId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + AccountName = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + AssetId = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + Balance = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + NettingType = (NettingType)xElement5.ToInt(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 == null) + { + return; + } + AccountAdditionalInfo = new List(); + foreach (XElement item in xElement6.Elements()) + { + AdditionalInfoItem additionalInfoItem = new AdditionalInfoItem(); + additionalInfoItem.FromXElement(item, deserializationInfo); + AccountAdditionalInfo.Add(additionalInfoItem); + } + } + } + public sealed class MessageAccountOperation : Message + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IList ??; + + [CompilerGenerated] + private AccountOperationUpdateHandler ??; + + [CompilerGenerated] + private AccountOperationConfirmationHandler ??; + + [CompilerGenerated] + private AccountOperationExecuteHandler ??; + + public override MessageType Type => MessageType.AccountOperation; + + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ButtonText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public AccountOperationUpdateHandler UpdateHandler + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public AccountOperationConfirmationHandler BuildConfirmationHandler + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public AccountOperationExecuteHandler ExecuteHandler + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MessageAccountOperation() + { + Settings = new List(); + } + + public override string ToString() + { + return Name ?? 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + } + [DataContract(Name = "Asset", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageAsset : Message, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + private string ??; + + public override MessageType Type => MessageType.Asset; + + /// + /// Asset id bearer + /// + [DataMember(Name = "Id")] + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Asset name bearer + /// + [DataMember(Name = "Name")] + [ProtoMember(2)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Asset description + /// + [DataMember(Name = "Description")] + [ProtoMember(3)] + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "MinimumChange")] + [ProtoMember(4)] + public double MinimumChange + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "ISO")] + [ProtoMember(5)] + public string IsoCode + { + get + { + return ?? ?? Name; + } + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Description)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MinimumChange)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), IsoCode)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Name = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + Description = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + MinimumChange = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + IsoCode = xElement5.Value; + } + } + } + [DataContract(Name = "MessageCloseDeliveredAsset", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageCloseDeliveredAsset : Message + { + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.CloseDeliveredAsset; + + [DataMember(Name = "Id")] + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 2); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public class MessageClosedPosition : MessageOpenPosition + { + [CompilerGenerated] + private double ??; + + public override MessageType Type => MessageType.ClosedPosition; + + public double LastTradedPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MessageClosedPosition(string symbolId) + : base(symbolId) + { + } + } + [DataContract(Name = "CloseOrder", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageCloseOrder : Message + { + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.CloseOrder; + + [DataMember(Name = "OrderId")] + [ProtoMember(1)] + public string OrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 2); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [DataContract(Name = "ClosePosition", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageClosePosition : Message + { + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.ClosePosition; + + [DataMember(Name = "PositionId")] + [ProtoMember(1)] + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 2); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PositionId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [DataContract(Name = "CorporateAction", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageCorporateAction : Message, INeedSymbolToPocess + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private CorporateActionType ??; + + public override MessageType Type => MessageType.CorporateAction; + + [DataMember(Name = "CorporateActionId")] + [ProtoMember(1)] + public string CorporateActionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "DateTime")] + [ProtoMember(2)] + public DateTime DateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "InstrumentSymbol")] + [ProtoMember(3)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Details")] + [ProtoMember(4)] + public string Details + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public CorporateActionType CorporateActionType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + [DataContract(Name = "CryptoAccount", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageCryptoAccount : MessageAccount + { + public override MessageType Type => MessageType.CryptoAccount; + } + [DataContract(Name = "CryptoAssetBalances", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageCryptoAssetBalances : Message, IXElementSerialization, IEquatable + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private GetAvailableBalanceHandler ??; + + public override MessageType Type => MessageType.CryptoAssetBalances; + + [DataMember(Name = "AccountId")] + [ProtoMember(1)] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Asset id bearer + /// + [DataMember(Name = "AssetId")] + [ProtoMember(2)] + public string AssetId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TotalBalance")] + [ProtoMember(3)] + public double TotalBalance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AvailableBalance")] + [ProtoMember(4)] + public double AvailableBalance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "ReservedBalance")] + [ProtoMember(5)] + public double ReservedBalance + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TotalInUSD")] + [ProtoMember(6)] + public double TotalInUSD + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TotalInBTC")] + [ProtoMember(7)] + public double TotalInBTC + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Debt")] + [ProtoMember(8)] + public double Debt + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Equity")] + [ProtoMember(9)] + public double Equity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "EquityInBTC")] + [ProtoMember(10)] + public double EquityInBTC + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public GetAvailableBalanceHandler AvailableBalanceHandler + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AccountId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AssetId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TotalBalance)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AvailableBalance)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ReservedBalance)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TotalInUSD)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TotalInBTC)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Debt)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Equity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), EquityInBTC)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + AccountId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + AssetId = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + TotalBalance = xElement3.ToDouble(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + AvailableBalance = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + ReservedBalance = xElement5.ToDouble(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + TotalInUSD = xElement6.ToDouble(); + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + TotalInBTC = xElement7.ToDouble(); + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + Debt = xElement8.ToDouble(); + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + Equity = xElement9.ToDouble(); + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + EquityInBTC = xElement10.ToDouble(); + } + } + + public bool Equals(MessageCryptoAssetBalances other) + { + if (other == null) + { + return false; + } + if (this == other) + { + return true; + } + if (AccountId == other.AccountId && AssetId == other.AssetId && TotalBalance.Equals(other.TotalBalance) && AvailableBalance.Equals(other.AvailableBalance) && ReservedBalance.Equals(other.ReservedBalance) && TotalInUSD.Equals(other.TotalInUSD) && TotalInBTC.Equals(other.TotalInBTC) && Debt.Equals(other.Debt) && Equity.Equals(other.Equity) && EquityInBTC.Equals(other.EquityInBTC)) + { + return object.Equals(AvailableBalanceHandler, other.AvailableBalanceHandler); + } + return false; + } + + public override bool Equals(object obj) + { + if (this != obj) + { + if (obj is MessageCryptoAssetBalances other) + { + return Equals(other); + } + return false; + } + return true; + } + + public override int GetHashCode() + { + HashCode hashCode = default(HashCode); + hashCode.Add(AccountId); + hashCode.Add(AssetId); + hashCode.Add(TotalBalance); + hashCode.Add(AvailableBalance); + hashCode.Add(ReservedBalance); + hashCode.Add(TotalInUSD); + hashCode.Add(TotalInBTC); + hashCode.Add(Debt); + hashCode.Add(Equity); + hashCode.Add(EquityInBTC); + hashCode.Add(AvailableBalanceHandler); + return hashCode.ToHashCode(); + } + } + public delegate bool GetAvailableBalanceHandler(string assetId, OrderRequestParameters requestParameters, out double availableBalance); + [DataContract(Name = "DealTicket", Namespace = "TradingPlatform")] + public sealed class MessageDealTicket : Message + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DealTicketType ??; + + public override MessageType Type => MessageType.DealTicket; + + [DataMember(Name = "Header")] + public string Header + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + [DataMember(Name = "Description")] + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + [DataMember(Name = "DealTicketType")] + public DealTicketType DealTicketType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = dealTicketType; + } + } + + public MessageDealTicket(string header, string description = "", DealTicketType dealTicketType = DealTicketType.Info) + { + Header = header; + Description = description; + DealTicketType = dealTicketType; + } + + public static MessageDealTicket CreateInfoDealTicket(string header, string text) + { + return new MessageDealTicket(header, text); + } + + public static MessageDealTicket CreateRefuseDealTicket(string refuse) + { + return CreateRefuseDealTicket(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), refuse); + } + + public static MessageDealTicket CreateRefuseDealTicket(string header, string refuse) + { + return new MessageDealTicket(header, refuse, DealTicketType.Refuse); + } + } + [DataContract(Name = "Exchange", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageExchange : Message, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.Exchange; + + [DataMember(Name = "ExchangeId")] + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "ExchangeName")] + [ProtoMember(2)] + public string ExchangeName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "SortIndex")] + [ProtoMember(3)] + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string SessionsContainerId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 3); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ExchangeName); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExchangeName)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SortIndex)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SessionsContainerId)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + ExchangeName = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + SortIndex = xElement3.ToInt(); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + SessionsContainerId = xElement4.Value; + } + } + } + public class MessageNewsHeadline : Message + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private IEnumerable ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.NewsHeadline; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime CreationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Title + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IEnumerable SymbolsIds + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Category + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string SourceLink + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string SubscribeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + [DataContract(Name = "MessageOpenDeliveredAsset", Namespace = "TradingPlatform")] + [ProtoContract] + public class MessageOpenDeliveredAsset : Message, INeedSymbolToPocess, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private List ??; + + public override MessageType Type => MessageType.OpenDeliveredAsset; + + [DataMember(Name = "Id")] + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AccountId")] + [ProtoMember(2)] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "SymbolId")] + [ProtoMember(3)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Quantity")] + [ProtoMember(4)] + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Status")] + [ProtoMember(5)] + public string Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "CreationTime")] + [ProtoMember(6)] + public DateTime CreationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(7)] + public List AdditionalInfoItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AccountId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SymbolId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Status)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CreationTime)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + AccountId = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + SymbolId = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + Quantity = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + Status = xElement5.Value; + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + CreationTime = xElement6.ToDateTime(toUTC: true); + } + } + } + [DataContract(Name = "OpenOrder", Namespace = "TradingPlatform")] + [ProtoContract] + [ProtoInclude(23, typeof(MessageOrderHistory))] + public class MessageOpenOrder : Message, INeedSymbolToPocess, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private TimeInForce ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private OrderStatus ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private readonly List ??; + + [CompilerGenerated] + private readonly List ??; + + [CompilerGenerated] + private List ??; + + public override MessageType Type => MessageType.OpenOrder; + + [DataMember(Name = "OrderId")] + [ProtoMember(1)] + public string OrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "GroupId")] + [ProtoMember(2)] + public string GroupId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "PositionId")] + [ProtoMember(3)] + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AccountId")] + [ProtoMember(4)] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TotalQuantity")] + [ProtoMember(5)] + public double TotalQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "FilledQuantity")] + [ProtoMember(6)] + public double FilledQuantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Side")] + [ProtoMember(7)] + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Comment")] + [ProtoMember(8)] + public string Comment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "LastUpdateTime")] + [ProtoMember(9)] + public DateTime LastUpdateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "InstrumentSymbol")] + [ProtoMember(10)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + [DataMember(Name = "OrderTypeId")] + [ProtoMember(11)] + public string OrderTypeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Tif")] + [ProtoMember(12)] + public TimeInForce TimeInForce + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "ExpirationTime")] + [ProtoMember(13)] + public DateTime ExpirationTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Price")] + [ProtoMember(14)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TriggerPrice")] + [ProtoMember(15)] + public double TriggerPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "TrailOffset")] + [ProtoMember(16)] + public double TrailOffset + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Status")] + [ProtoMember(17)] + public OrderStatus Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "OriginalStatus")] + [ProtoMember(18)] + public string OriginalStatus + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AverageFillPrice")] + [ProtoMember(19)] + public double AverageFillPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public SlTpHolder StopLoss + { + get + { + return StopLossItems.FirstOrDefault(); + } + set + { + if (value == null) + { + StopLossItems.Clear(); + } + else if (StopLossItems.Any()) + { + StopLossItems[0] = value; + } + else + { + StopLossItems.Add(value); + } + } + } + + public SlTpHolder TakeProfit + { + get + { + return TakeProfitItems.FirstOrDefault(); + } + set + { + if (value == null) + { + TakeProfitItems.Clear(); + } + else if (TakeProfitItems.Any()) + { + TakeProfitItems[0] = value; + } + else + { + TakeProfitItems.Add(value); + } + } + } + + [ProtoMember(20)] + public List StopLossItems + { + [CompilerGenerated] + get + { + return ??; + } + } + + [ProtoMember(21)] + public List TakeProfitItems + { + [CompilerGenerated] + get + { + return ??; + } + } + + [ProtoMember(22)] + public List AdditionalInfoItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + internal MessageOpenOrder() + { + Price = double.NaN; + TriggerPrice = double.NaN; + TrailOffset = double.NaN; + AverageFillPrice = double.NaN; + ?? = new List(); + ?? = new List(); + } + + public MessageOpenOrder(string symbolId) + : this() + { + SymbolId = symbolId; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(41, 6); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Price); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderTypeId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public string Format() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 8); + defaultInterpolatedStringHandler.AppendFormatted(OrderId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(AccountId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderTypeId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(FilledQuantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(TotalQuantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Status); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OrderId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), GroupId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PositionId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AccountId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TotalQuantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), FilledQuantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Side)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Comment)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LastUpdateTime)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SymbolId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OrderTypeId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)TimeInForce)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationTime)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Price)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TriggerPrice)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TrailOffset)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)Status)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OriginalStatus)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + foreach (AdditionalInfoItem additionalInfoItem in AdditionalInfoItems) + { + xElement2.Add(additionalInfoItem.ToXElement()); + } + xElement.Add(xElement2); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + OrderId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + GroupId = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + PositionId = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + AccountId = xElement4.Value; + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + TotalQuantity = xElement5.ToDouble(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + FilledQuantity = xElement6.ToDouble(); + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + Side = (Side)xElement7.ToInt(); + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + Comment = xElement8.Value; + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + LastUpdateTime = xElement9.ToDateTime(toUTC: true); + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + SymbolId = xElement10.Value; + } + XElement xElement11 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + OrderTypeId = xElement11.Value; + } + XElement xElement12 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + TimeInForce = (TimeInForce)xElement12.ToInt(); + } + XElement xElement13 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement13 != null) + { + ExpirationTime = xElement13.ToDateTime(toUTC: true); + } + XElement xElement14 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement14 != null) + { + Price = xElement14.ToDouble(); + } + XElement xElement15 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement15 != null) + { + TriggerPrice = xElement15.ToDouble(); + } + XElement xElement16 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement16 != null) + { + TrailOffset = xElement16.ToDouble(); + } + XElement xElement17 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement17 != null) + { + Status = (OrderStatus)xElement17.ToInt(); + } + XElement xElement18 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement18 != null) + { + OriginalStatus = xElement18.Value; + } + XElement xElement19 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement19 == null) + { + return; + } + List list = new List(); + foreach (XElement item in xElement19.Elements()) + { + AdditionalInfoItem additionalInfoItem = new AdditionalInfoItem(); + additionalInfoItem.FromXElement(item, deserializationInfo); + list.Add(additionalInfoItem); + } + AdditionalInfoItems = list; + } + } + [DataContract(Name = "OpenPosition", Namespace = "TradingPlatform")] + [ProtoContract] + public class MessageOpenPosition : Message, INeedSymbolToPocess, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private List ??; + + public override MessageType Type => MessageType.OpenPosition; + + [DataMember(Name = "PositionId")] + [ProtoMember(1)] + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "OpenPrice")] + [ProtoMember(2)] + public double OpenPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "OpenTime")] + [ProtoMember(3)] + public DateTime OpenTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Quantity")] + [ProtoMember(4)] + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Side")] + [ProtoMember(5)] + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Comment")] + [ProtoMember(6)] + public string Comment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AccountId")] + [ProtoMember(7)] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "InstrumentSymbol")] + [ProtoMember(8)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + [DataMember(Name = "OpenOrderId")] + [ProtoMember(9)] + public string OpenOrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "LiquidationPrice")] + [ProtoMember(10)] + public double LiquidationPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public List AdditionalInfoItems + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + internal MessageOpenPosition() + { + LiquidationPrice = double.NaN; + } + + public MessageOpenPosition(string symbolId) + : this() + { + SymbolId = symbolId; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 4); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(PositionId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OpenPrice); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), PositionId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OpenPrice)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OpenTime)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Quantity)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Side)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Comment)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AccountId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SymbolId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OpenOrderId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LiquidationPrice)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + PositionId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + OpenPrice = xElement2.ToDouble(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + OpenTime = xElement3.ToDateTime(toUTC: true); + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + Quantity = xElement4.ToDouble(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + Side = (Side)xElement5.ToInt(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + Comment = xElement6.Value; + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + AccountId = xElement7.Value; + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + SymbolId = xElement8.Value; + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + OpenOrderId = xElement9.Value; + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + LiquidationPrice = xElement10.ToDouble(); + } + } + } + [DataContract(Name = "OptionSerie", Namespace = "TradingPlatform")] + [ProtoContract] + public class MessageOptionSerie : Message, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private OptionSerieType ??; + + public override MessageType Type => MessageType.OptionSerie; + + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public DateTime ExpirationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public string ExchangeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(6)] + public OptionSerieType SerieType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(25, 3); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(UnderlierId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(ExpirationDate.ToShortDateString()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationDate)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), UnderlierId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)SerieType)); + return xElement; + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.ToString(); + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + ExpirationDate = xElement2.ToDateTime(); + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + Name = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + UnderlierId = xElement4.Value; + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + SerieType = (OptionSerieType)xElement5.ToInt(); + } + } + } + [DataContract(Name = "OrderHistory", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageOrderHistory : MessageOpenOrder + { + public override MessageType Type => MessageType.OrderHistory; + + private MessageOrderHistory() + { + base.AverageFillPrice = double.NaN; + } + + public MessageOrderHistory(string symbolId) + : base(symbolId) + { + base.AverageFillPrice = double.NaN; + } + + public MessageOrderHistory(MessageOpenOrder order) + : base(order.SymbolId) + { + base.OrderId = order.OrderId; + base.AccountId = order.AccountId; + base.OrderTypeId = order.OrderTypeId; + base.Price = order.Price; + base.TriggerPrice = order.TriggerPrice; + base.TrailOffset = order.TrailOffset; + base.FilledQuantity = order.FilledQuantity; + base.TotalQuantity = order.TotalQuantity; + base.Side = order.Side; + base.TimeInForce = order.TimeInForce; + base.ExpirationTime = order.ExpirationTime; + base.PositionId = order.PositionId; + base.GroupId = order.GroupId; + base.Comment = order.Comment; + base.LastUpdateTime = order.LastUpdateTime; + base.StopLoss = order.StopLoss; + base.TakeProfit = order.TakeProfit; + base.Status = order.Status; + base.OriginalStatus = order.OriginalStatus; + base.AverageFillPrice = order.AverageFillPrice; + } + } + public class MessageRemoveTradingSignal : Message + { + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.RemoveTradingSignal; + + public string TradingSignalId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MessageRemoveTradingSignal(string tradingSignalId) + { + TradingSignalId = tradingSignalId; + } + } + [DataContract(Name = "MessageReportType", Namespace = "TradingPlatform")] + public sealed class MessageReportType : Message + { + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private List ??; + + [DataMember(Name = "Id")] + public int Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Name")] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Parameters")] + public List Parameters + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override MessageType Type => MessageType.ReportMetadata; + + public MessageReportType() + { + Parameters = new List(); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(14, 3); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [DataContract(Name = "Rule", Namespace = "TradingPlatform")] + public class MessageRule : Message + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private readonly object ??; + + public override MessageType Type => MessageType.Rule; + + [DataMember(Name = "Name")] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + [DataMember(Name = "AccountId")] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + [DataMember(Name = "InstrumentId")] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + [DataMember(Name = "OrderTypeId")] + public string OrderTypeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + [DataMember(Name = "Value")] + public object Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public MessageRule() + { + Name = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + AccountId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + SymbolId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + OrderTypeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(); + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(15, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Name); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Value); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [ProtoContract] + public class MessageSessionsContainer : Message, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private HolidayInfo[] ??; + + [CompilerGenerated] + private SessionsSet[] ??; + + public override MessageType Type => MessageType.Session; + + [ProtoMember(1)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(2)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(3)] + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(4)] + public HolidayInfo[] Holidays + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(5)] + public SessionsSet[] SessionsSets + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Name = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + Description = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + List list = new List(); + foreach (XElement item in xElement4.Elements()) + { + HolidayInfo holidayInfo = new HolidayInfo(); + holidayInfo.FromXElement(item, deserializationInfo); + list.Add(holidayInfo); + } + Holidays = list.ToArray(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 == null) + { + return; + } + List list2 = new List(); + foreach (XElement item2 in xElement5.Elements()) + { + SessionsSet sessionsSet = new SessionsSet(); + sessionsSet.FromXElement(item2, deserializationInfo); + list2.Add(sessionsSet); + } + SessionsSets = list2.ToArray(); + } + + public XElement ToXElement() + { + XElement xElement = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Description)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (Holidays != null) + { + HolidayInfo[] holidays = Holidays; + foreach (HolidayInfo holidayInfo in holidays) + { + xElement2.Add(holidayInfo.ToXElement()); + } + } + xElement.Add(xElement2); + XElement xElement3 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + SessionsSet[] sessionsSets = SessionsSets; + foreach (SessionsSet sessionsSet in sessionsSets) + { + xElement3.Add(sessionsSet.ToXElement()); + } + xElement.Add(xElement3); + return xElement; + } + } + [DataContract(Name = "Instrument", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageSymbol : MessageSymbolInfo, IXElementSerialization, INeedSymbolToPocess + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal AdditionalInfoItem ?(AdditionalInfoItem P_0) + { + return (AdditionalInfoItem)P_0.Clone(); + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private TimeSpan ??; + + [CompilerGenerated] + private SymbolQuotingType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private List ??; + + [CompilerGenerated] + private NettingType ??; + + [CompilerGenerated] + private SymbolVolumeType ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DeltaCalculationType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private HistoryMetadata ??; + + [CompilerGenerated] + private VolumeAnalysisMetadata ??; + + public override MessageType Type => MessageType.Symbol; + + [DataMember(Name = "productID")] + [ProtoMember(100)] + public string ProductAssetId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "quotingCurrencyID")] + [ProtoMember(105)] + public string QuotingCurrencyAssetID + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "quoteDelay")] + [ProtoMember(110)] + public TimeSpan QuoteDelay + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "quotingType")] + [ProtoMember(115)] + public SymbolQuotingType QuotingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "lotSize")] + [ProtoMember(120)] + public double LotSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "instrumentAdditionalInfo")] + [ProtoMember(130)] + public List SymbolAdditionalInfo + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "nettingType")] + [ProtoMember(135)] + public NettingType NettingType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "VolumeType")] + [ProtoMember(145)] + public SymbolVolumeType VolumeType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "allowCalculateRealtimeTicks")] + [ProtoMember(150)] + public bool AllowCalculateRealtimeTicks + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "allowCalculateRealtimeTrades")] + [ProtoMember(155)] + public bool AllowCalculateRealtimeTrades + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "allowCalculateRealtimeVolume")] + [ProtoMember(160)] + public bool AllowCalculateRealtimeVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "allowCalculateRealtimeChange")] + [ProtoMember(165)] + public bool AllowCalculateRealtimeChange + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "allowAbbreviatePriceByTickSize")] + [ProtoMember(170)] + public bool AllowAbbreviatePriceByTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "notionalValueStep")] + [ProtoMember(175)] + public double NotionalValueStep + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "deltaCalculationType")] + [ProtoMember(180)] + public DeltaCalculationType DeltaCalculationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "minVolumeAnalysisTickSize")] + [ProtoMember(183)] + public double MinVolumeAnalysisTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(185)] + public DateTime MaturityDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + string INeedSymbolToPocess.SymbolId => base.UnderlierId; + + [DataMember(Name = "SessionsContainerId")] + [ProtoMember(186)] + public string SessionsContainerId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "HistoryMetadata")] + [ProtoMember(187)] + public HistoryMetadata HistoryMetadata + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(188)] + public VolumeAnalysisMetadata VolumeAnalysisMetadata + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + private MessageSymbol() + { + } + + public MessageSymbol(string symbolId) + : base(symbolId) + { + } + + public MessageSymbol(MessageSymbol origin) + : base(origin) + { + ProductAssetId = origin.ProductAssetId; + QuotingCurrencyAssetID = origin.QuotingCurrencyAssetID; + QuoteDelay = origin.QuoteDelay; + QuotingType = origin.QuotingType; + LotSize = origin.LotSize; + SymbolAdditionalInfo = ((origin.SymbolAdditionalInfo != null) ? new List(origin.SymbolAdditionalInfo.Select((AdditionalInfoItem P_0) => (AdditionalInfoItem)P_0.Clone())) : null); + NettingType = origin.NettingType; + base.GroupId = origin.GroupId; + VolumeType = origin.VolumeType; + AllowCalculateRealtimeTicks = origin.AllowCalculateRealtimeTicks; + AllowCalculateRealtimeTrades = origin.AllowCalculateRealtimeTrades; + AllowCalculateRealtimeVolume = origin.AllowCalculateRealtimeVolume; + AllowCalculateRealtimeChange = origin.AllowCalculateRealtimeChange; + AllowAbbreviatePriceByTickSize = origin.AllowAbbreviatePriceByTickSize; + NotionalValueStep = origin.NotionalValueStep; + DeltaCalculationType = origin.DeltaCalculationType; + MinVolumeAnalysisTickSize = origin.MinVolumeAnalysisTickSize; + MaturityDate = origin.MaturityDate; + SessionsContainerId = origin.SessionsContainerId; + HistoryMetadata = origin.HistoryMetadata; + VolumeAnalysisMetadata = origin.VolumeAnalysisMetadata; + } + + protected override void InitialState() + { + base.InitialState(); + NettingType = NettingType.Undefined; + AllowCalculateRealtimeTicks = true; + AllowCalculateRealtimeTrades = true; + AllowCalculateRealtimeVolume = true; + AllowCalculateRealtimeChange = true; + AllowAbbreviatePriceByTickSize = false; + LotSize = 1.0; + NotionalValueStep = 1.0; + MinVolumeAnalysisTickSize = double.NaN; + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(16, 3); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(base.Name); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + + public override XElement ToXElement() + { + XElement xElement = base.ToXElement(); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ProductAssetId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuotingCurrencyAssetID)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), QuoteDelay.ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)QuotingType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LotSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), NotionalValueStep)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)NettingType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)base.HistoryType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)VolumeType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)DeltaCalculationType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MinVolumeAnalysisTickSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowCalculateRealtimeTicks)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowCalculateRealtimeTrades)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowCalculateRealtimeVolume)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowCalculateRealtimeChange)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), AllowAbbreviatePriceByTickSize)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MaturityDate)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SessionsContainerId)); + if (base.FutureContractType.HasValue) + { + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)base.FutureContractType.Value).ToString())); + } + return xElement; + } + + public override void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + base.FromXElement(element, deserializationInfo); + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + ProductAssetId = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + QuotingCurrencyAssetID = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + QuoteDelay = xElement3.ToTimeSpan(); + } + element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + NettingType = (NettingType)xElement4.ToInt(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + QuotingType = (SymbolQuotingType)xElement5.ToInt(); + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + LotSize = xElement6.ToDouble(); + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + NotionalValueStep = xElement7.ToDouble(); + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + base.HistoryType = (HistoryType)xElement8.ToInt(); + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + VolumeType = (SymbolVolumeType)xElement9.ToInt(); + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + DeltaCalculationType = (DeltaCalculationType)xElement10.ToInt(); + } + XElement xElement11 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + MinVolumeAnalysisTickSize = xElement11.ToDouble(); + } + XElement xElement12 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + AllowCalculateRealtimeTicks = xElement12.ToBool(); + } + XElement xElement13 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement13 != null) + { + AllowCalculateRealtimeTrades = xElement13.ToBool(); + } + XElement xElement14 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement14 != null) + { + AllowCalculateRealtimeVolume = xElement14.ToBool(); + } + XElement xElement15 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement15 != null) + { + AllowCalculateRealtimeChange = xElement15.ToBool(); + } + XElement xElement16 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement16 != null) + { + AllowAbbreviatePriceByTickSize = xElement16.ToBool(); + } + XElement xElement17 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement17 != null) + { + MaturityDate = xElement17.ToDateTime(); + } + XElement xElement18 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement18 != null) + { + SessionsContainerId = xElement18.Value; + } + XElement xElement19 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement19 != null) + { + base.FutureContractType = (FutureContractType)xElement19.ToInt(); + } + } + } + public class MessageSymbolGroup : Message + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + public override MessageType Type => MessageType.SymbolGroup; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string GroupName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int SortIndex + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 3); + defaultInterpolatedStringHandler.AppendFormatted(Type); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Id); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(GroupName); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + [DataContract(Name = "Instrument", Namespace = "TradingPlatform")] + [ProtoContract] + [ProtoInclude(1000, typeof(MessageSymbol))] + public class MessageSymbolInfo : Message, IXElementSerialization + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private SymbolType ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private OptionType ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private HistoryType ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private AvailableDerivatives ??; + + [CompilerGenerated] + private AvailableDerivatives ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private FutureContractType? ??; + + [CompilerGenerated] + private string[] ??; + + [CompilerGenerated] + private List ??; + + public override MessageType Type => MessageType.SymbolInfo; + + [DataMember(Name = "id")] + [ProtoMember(5)] + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + internal set + { + ?? = text; + } + } + + [DataMember(Name = "name")] + [ProtoMember(10)] + public string Name + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "description")] + [ProtoMember(15)] + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "type")] + [ProtoMember(20)] + public SymbolType SymbolType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "ExchangeId")] + [ProtoMember(25)] + public string ExchangeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "lotStep")] + [ProtoMember(30)] + public double LotStep + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "minLot")] + [ProtoMember(35)] + public double MinLot + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "maxLot")] + [ProtoMember(40)] + public double MaxLot + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "underlierName")] + [ProtoMember(45)] + public string Root + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "optionType")] + [ProtoMember(50)] + public OptionType OptionType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "strikePrice")] + [ProtoMember(55)] + public double StrikePrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "expirationDate")] + [ProtoMember(60)] + public DateTime ExpirationDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "HistoryType")] + [ProtoMember(70)] + public HistoryType HistoryType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "lastTradingDate")] + [ProtoMember(80)] + public DateTime LastTradingDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AvailableFutures")] + [ProtoMember(85)] + public AvailableDerivatives AvailableFutures + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AvailableOptions")] + [ProtoMember(86)] + public AvailableDerivatives AvailableOptions + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "underlierId")] + [ProtoMember(90)] + public string UnderlierId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "optionSerieId")] + [ProtoMember(95)] + public string OptionSerieId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(96)] + public string GroupId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(97)] + public FutureContractType? FutureContractType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(98)] + public string[] AvailableOptionsExchanges + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "variableTickList")] + [ProtoMember(125)] + public List VariableTickList + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + protected MessageSymbolInfo() + { + InitialState(); + } + + public MessageSymbolInfo(string symbolId) + : this() + { + Id = symbolId; + } + + public MessageSymbolInfo(MessageSymbolInfo origin) + : this() + { + Fill(origin); + } + + protected virtual void InitialState() + { + ExchangeId = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + AvailableFutures = AvailableDerivatives.None; + AvailableOptions = AvailableDerivatives.None; + MinLot = 1.0; + MaxLot = 2147483647.0; + LotStep = 1.0; + } + + public void Fill(MessageSymbolInfo messageSymbolInfo) + { + Id = messageSymbolInfo.Id; + Name = messageSymbolInfo.Name; + Description = messageSymbolInfo.Description; + SymbolType = messageSymbolInfo.SymbolType; + ExchangeId = messageSymbolInfo.ExchangeId; + LotStep = messageSymbolInfo.LotStep; + MinLot = messageSymbolInfo.MinLot; + MaxLot = messageSymbolInfo.MaxLot; + Root = messageSymbolInfo.Root; + OptionType = messageSymbolInfo.OptionType; + StrikePrice = messageSymbolInfo.StrikePrice; + ExpirationDate = messageSymbolInfo.ExpirationDate; + HistoryType = messageSymbolInfo.HistoryType; + LastTradingDate = messageSymbolInfo.LastTradingDate; + AvailableFutures = messageSymbolInfo.AvailableFutures; + AvailableOptions = messageSymbolInfo.AvailableOptions; + UnderlierId = messageSymbolInfo.UnderlierId; + OptionSerieId = messageSymbolInfo.OptionSerieId; + FutureContractType = messageSymbolInfo.FutureContractType; + VariableTickList = ((messageSymbolInfo.VariableTickList != null) ? new List(messageSymbolInfo.VariableTickList) : null); + } + + public virtual XElement ToXElement() + { + XElement xElement = new XElement(GetType().Name); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Id)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Name)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Description)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)SymbolType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExchangeId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LotStep)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MinLot)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MaxLot)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Root)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)AvailableFutures).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)AvailableOptions).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), UnderlierId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), OptionSerieId)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ((int)OptionType).ToString())); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), StrikePrice)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), ExpirationDate)); + xElement.Add(new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LastTradingDate)); + XElement xElement2 = new XElement(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (VariableTickList != null && VariableTickList.Count > 0) + { + for (int i = 0; i < VariableTickList.Count; i++) + { + xElement2.Add(VariableTickList[i].ToXElement()); + } + } + xElement.Add(xElement2); + return xElement; + } + + public virtual void FromXElement(XElement element, DeserializationInfo deserializationInfo) + { + XElement xElement = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement != null) + { + Id = xElement.Value; + } + XElement xElement2 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement2 != null) + { + Name = xElement2.Value; + } + XElement xElement3 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement3 != null) + { + Description = xElement3.Value; + } + XElement xElement4 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement4 != null) + { + SymbolType = (SymbolType)xElement4.ToInt(); + } + XElement xElement5 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement5 != null) + { + ExchangeId = xElement5.Value; + } + XElement xElement6 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement6 != null) + { + LotStep = xElement6.ToDouble(); + } + XElement xElement7 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement7 != null) + { + MaxLot = xElement7.ToDouble(); + } + XElement xElement8 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement8 != null) + { + MinLot = xElement8.ToDouble(); + } + XElement xElement9 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement9 != null) + { + Root = xElement9.Value; + } + XElement xElement10 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement10 != null) + { + AvailableFutures = (AvailableDerivatives)xElement10.ToInt(); + } + XElement xElement11 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement11 != null) + { + AvailableOptions = (AvailableDerivatives)xElement11.ToInt(); + } + XElement xElement12 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement12 != null) + { + UnderlierId = xElement12.Value; + } + XElement xElement13 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement13 != null) + { + OptionSerieId = xElement13.Value; + } + XElement xElement14 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement14 != null) + { + OptionType = (OptionType)xElement14.ToInt(); + } + XElement xElement15 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement15 != null) + { + StrikePrice = xElement15.ToDouble(); + } + XElement xElement16 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement16 != null) + { + ExpirationDate = xElement16.ToDateTime(); + } + XElement xElement17 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement17 != null) + { + LastTradingDate = xElement17.ToDateTime(); + } + XElement xElement18 = element.Element(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (xElement18 == null) + { + return; + } + List list = new List(); + foreach (XElement item in xElement18.Elements()) + { + VariableTick variableTick = new VariableTick(); + variableTick.FromXElement(item, deserializationInfo); + list.Add(variableTick); + } + VariableTickList = list; + } + } + [DataContract(Name = "InstrumentTypes", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageSymbolTypes : Message + { + [CompilerGenerated] + private IList ??; + + public override MessageType Type => MessageType.SymbolTypes; + + [ProtoMember(1)] + public IList SymbolTypes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + [DataContract(Name = "Trade", Namespace = "TradingPlatform")] + [ProtoContract] + public sealed class MessageTrade : Message, INeedSymbolToPocess + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private PnLItem ??; + + [CompilerGenerated] + private PnLItem ??; + + [CompilerGenerated] + private PnLItem ??; + + [CompilerGenerated] + private PositionImpactType ??; + + public override MessageType Type => MessageType.Trade; + + [DataMember(Name = "TradeId")] + [ProtoMember(1)] + public string TradeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "OrderId")] + [ProtoMember(2)] + public string OrderId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "PositionId")] + [ProtoMember(3)] + public string PositionId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Price")] + [ProtoMember(4)] + public double Price + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Quantity")] + [ProtoMember(5)] + public double Quantity + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Side")] + [ProtoMember(6)] + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "AccountId")] + [ProtoMember(7)] + public string AccountId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "InstrumentSymbol")] + [ProtoMember(8)] + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "DateTime")] + [ProtoMember(9)] + public DateTime DateTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Comment")] + [ProtoMember(10)] + public string Comment + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "OrderType")] + [ProtoMember(11)] + public string OrderTypeId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "GrossPnl")] + [ProtoMember(12)] + public PnLItem GrossPnl + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "NetPnl")] + [ProtoMember(13)] + public PnLItem NetPnl + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [DataMember(Name = "Fee")] + [ProtoMember(14)] + public PnLItem Fee + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + [ProtoMember(15)] + public PositionImpactType PositionImpactType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public override string ToString() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(28, 4); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(SymbolId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Side); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(Quantity); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(OrderId); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } + } + public class MessageTradingSignal : Message + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Side ??; + + [CompilerGenerated] + private OrderTypeBehavior ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + public override MessageType Type => MessageType.TradingSignal; + + public string Id + { + [CompilerGenerated] + get + { + return ??; + } + } + + public string Ticker + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Root + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string VendorName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Side Side + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public OrderTypeBehavior OrderTypeBehavior + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double EntryPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TargetPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double StopPrice + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double Confidence + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime Published + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime Updated + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime ExpiresAt + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Duration + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Status + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Details + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string Source + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public MessageTradingSignal(string id) + { + ?? = id; + } + + public override string ToString() + { + return 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + Side.ToString().ToUpperInvariant() + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + (Ticker ?? Root); + } + } + public abstract class MultiVendor : Vendor + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func> ??; + + public static Func, IEnumerable> ??; + + public static Func, IEnumerable> ??; + + public static Func, IEnumerable> ??; + + public static Func, IEnumerable> ??; + + public static Func, TimeSpan> ??; + + public static Func, TimeSpan> ??; + + public static Func, TimeSpan> ??; + + public static Func, bool> ??; + + public static Func, bool> ??; + + public static Func ??; + + public static Func ??; + + public static Func ??; + + internal bool ?(IVendor P_0) + { + return P_0 is Vendor; + } + + internal bool ?(ISymbolVendor P_0) + { + return P_0.AllowNonFixedList; + } + + internal IEnumerable ?(MessageSymbolTypes P_0) + { + return P_0.SymbolTypes; + } + + internal IEnumerable ?(KeyValuePair P_0) + { + return P_0.Value.AllowedAggregations; + } + + internal IEnumerable ?(KeyValuePair P_0) + { + return P_0.Value.AllowedPeriodsHistoryAggregationTime; + } + + internal IEnumerable ?(KeyValuePair P_0) + { + return P_0.Value.AllowedHistoryTypesHistoryAggregationTime; + } + + internal IEnumerable ?(KeyValuePair P_0) + { + return P_0.Value.AllowedHistoryTypesHistoryAggregationTick; + } + + internal TimeSpan ?(KeyValuePair P_0) + { + return P_0.Value.DownloadingStep_Day; + } + + internal TimeSpan ?(KeyValuePair P_0) + { + return P_0.Value.DownloadingStep_Minute; + } + + internal TimeSpan ?(KeyValuePair P_0) + { + return P_0.Value.DownloadingStep_Tick; + } + + internal bool ?(KeyValuePair P_0) + { + return P_0.Value.BuildUncompletedBars; + } + + internal bool ?(KeyValuePair P_0) + { + return P_0.Value.IsVolumeAnalysisAvailable; + } + + internal bool ?(VolumeAnalysisMetadata P_0) + { + return P_0.BuildUncompletedBars; + } + + internal TimeSpan ?(VolumeAnalysisMetadata P_0) + { + return P_0.MaxTicksLoadingPeriod; + } + + internal bool ?(AdditionalInfoItem P_0) + { + return P_0.Id == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + } + } + + [CompilerGenerated] + private sealed class ? + { + public CancellationToken ??; + + internal MessageSymbolTypes ?(ISymbolVendor P_0) + { + return P_0.GetSymbolTypes(??); + } + } + + [CompilerGenerated] + private ITradingVendor ??; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + protected readonly List AllVendors; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + private readonly Dictionary ??; + + private readonly Dictionary> ??; + + private readonly Dictionary> ??; + + private readonly Dictionary> ??; + + private readonly Dictionary> ??; + + private readonly Dictionary ??; + + private readonly Dictionary> ??; + + private readonly Dictionary ??; + + private readonly Dictionary> ??; + + private readonly Dictionary ??; + + private readonly Dictionary> ??; + + protected ITradingVendor TradingVendor + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = tradingVendor; + } + } + + /// + /// Confirms allowed nonfixed list by vendor + /// + public override bool AllowNonFixedList + { + get + { + if (??.Count == 0) + { + return base.AllowNonFixedList; + } + return ??.Values.Any((ISymbolVendor P_0) => P_0.AllowNonFixedList); + } + } + + protected MultiVendor() + { + ?? = new Dictionary(); + ?? = new Dictionary(); + ?? = new Dictionary(); + ?? = new Dictionary(); + AllVendors = new List(); + ?? = new Dictionary(); + ?? = new Dictionary(); + ?? = new Dictionary(); + ?? = new Dictionary(); + ?? = new Dictionary>(); + ?? = new Dictionary>(); + ?? = new Dictionary>(); + ?? = new Dictionary>(); + ?? = new Dictionary(); + ?? = new Dictionary>(); + ?? = new Dictionary(); + ?? = new Dictionary>(); + ?? = new Dictionary(); + ?? = new Dictionary>(); + } + + /// + /// Performs a binding with broker or data provider + /// + public override ConnectionResult Connect(ConnectRequestParameters connectRequestParameters) + { + if (AllVendors.Count == 0) + { + return ConnectionResult.CreateFail(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + foreach (IVendor allVendor in AllVendors) + { + try + { + ConnectionResult connectionResult = allVendor.Connect(connectRequestParameters); + if (connectionResult.State == ConnectionState.Fail) + { + return connectionResult; + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex.InnerException ?? ex); + return ConnectionResult.CreateFail(ex.GetMessageRecursive()); + } + } + return ConnectionResult.CreateSuccess(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?()); + } + + /// + /// Specifies any operation before breaking a connection with broker or data provider + /// + public override void Disconnect() + { + foreach (IVendor allVendor in AllVendors) + { + try + { + allVendor.Disconnect(); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + /// + /// Called when platform finished retreiving all required informations from vendor during connecting + /// + public override void OnConnected(CancellationToken token) + { + foreach (IVendor allVendor in AllVendors) + { + try + { + allVendor.OnConnected(token); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + /// + /// Ping processing before its visualization in the terminal + /// + public override PingResult Ping() + { + PingResult pingResult = new PingResult + { + State = PingEnum.Disconnected + }; + double num = 0.0; + double num2 = 0.0; + foreach (IVendor allVendor in AllVendors) + { + PingResult pingResult2 = allVendor.Ping(); + if (pingResult2.State != PingEnum.Connected) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + allVendor.Key + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + return pingResult2; + } + if (pingResult2.PingTime.HasValue) + { + num = Math.Max(num, pingResult2.PingTime.Value.TotalMilliseconds); + } + if (pingResult2.RoundTripTime.HasValue) + { + num2 = Math.Max(num2, pingResult2.RoundTripTime.Value.TotalMilliseconds); + } + } + pingResult.State = PingEnum.Connected; + pingResult.PingTime = TimeSpan.FromMilliseconds(num); + pingResult.RoundTripTime = TimeSpan.FromMilliseconds(num2); + return pingResult; + } + + public override LimitationMetadata GetLimitationMetadata() + { + if (TradingVendor == null) + { + return base.GetLimitationMetadata(); + } + return TradingVendor.GetLimitationMetadata(); + } + + /// + /// Retrieves an information about available accounts. Yon need to specify at least one account + /// + public override IList GetAccounts(CancellationToken token) + { + return TradingVendor?.GetAccounts(token) ?? base.GetAccounts(token); + } + + public override IList GetRules(CancellationToken token) + { + if (TradingVendor != null) + { + return TradingVendor.GetRules(token); + } + if (AllVendors.Where((IVendor P_0) => P_0 is Vendor).FirstOrDefault() is Vendor vendor) + { + return vendor.GetRules(token); + } + return base.GetRules(token); + } + + public override IList GetCryptoAssetBalances(CancellationToken token) + { + return TradingVendor?.GetCryptoAssetBalances(token) ?? base.GetCryptoAssetBalances(token); + } + + public override IList GetAccountOperations(CancellationToken token) + { + return TradingVendor?.GetAccountOperations(token) ?? base.GetAccountOperations(token); + } + + public override IList GetSessions(CancellationToken token) + { + List list = new List(); + foreach (KeyValuePair item2 in ??) + { + ISymbolVendor value = item2.Value; + foreach (MessageSessionsContainer session in value.GetSessions(token)) + { + MessageSessionsContainer item = ?(value.Key, session); + list.Add(item); + } + } + return list; + } + + /// + /// Retrieves a collection of available exchange markets from vendor + /// + public override IList GetExchanges(CancellationToken token) + { + List list = new List(); + foreach (KeyValuePair item2 in ??) + { + ISymbolVendor value = item2.Value; + foreach (MessageExchange exchange in value.GetExchanges(token)) + { + MessageExchange item = ?(value.Key, exchange); + list.Add(item); + } + } + return list; + } + + /// + /// Retrieves information about available assets. + /// + public override IList GetAssets(CancellationToken token) + { + if (??.Count == 0) + { + return base.GetAssets(token); + } + List list = new List(); + foreach (KeyValuePair item2 in ??) + { + ISymbolVendor value = item2.Value; + foreach (MessageAsset asset in value.GetAssets(token)) + { + MessageAsset item = ?(value.Key, asset); + list.Add(item); + } + } + return list; + } + + /// + /// Retrieves information about available symbols. + /// + public override IList GetSymbols(CancellationToken token) + { + if (??.Count == 0) + { + return base.GetSymbols(token); + } + List list = new List(); + foreach (KeyValuePair item2 in ??) + { + ISymbolVendor value = item2.Value; + foreach (MessageSymbol symbol in value.GetSymbols(token)) + { + MessageSymbol item = ?(value.Key, symbol); + list.Add(item); + } + } + return list; + } + + /// + /// Gets an available symbols types from vendor + /// + public override MessageSymbolTypes GetSymbolTypes(CancellationToken token) + { + if (??.Count == 0) + { + return base.GetSymbolTypes(token); + } + List symbolTypes = ??.Values.Select((ISymbolVendor P_0) => P_0.GetSymbolTypes(token)).SelectMany((MessageSymbolTypes P_0) => P_0.SymbolTypes).Distinct() + .ToList(); + return new MessageSymbolTypes + { + SymbolTypes = symbolTypes + }; + } + + public override IList GetSymbolGroups(CancellationToken token) + { + List list = new List(); + foreach (KeyValuePair item2 in ??) + { + ISymbolVendor value = item2.Value; + foreach (MessageSymbolGroup symbolGroup in value.GetSymbolGroups(token)) + { + MessageSymbolGroup item = ?(value.Key, symbolGroup); + list.Add(item); + } + } + return list; + } + + /// + /// Derives a non fixed symbol from vendor + /// + public override MessageSymbol GetNonFixedSymbol(GetSymbolRequestParameters requestParameters) + { + if (!?(requestParameters.SymbolId, out string text, out ISymbolVendor symbolVendor)) + { + return base.GetNonFixedSymbol(requestParameters); + } + if (!?(text, requestParameters.SymbolId, out var symbolId)) + { + return base.GetNonFixedSymbol(requestParameters); + } + requestParameters.SymbolId = symbolId; + MessageSymbol nonFixedSymbol = symbolVendor.GetNonFixedSymbol(requestParameters); + return ?(text, nonFixedSymbol); + } + + /// + /// Derives a non-fixed list of symbols from vendor + /// + public override IList SearchSymbols(SearchSymbolsRequestParameters requestParameters) + { + if (??.Count == 0) + { + return base.SearchSymbols(requestParameters); + } + List list = new List(); + foreach (KeyValuePair item2 in ??) + { + string key = item2.Key; + ISymbolVendor value = item2.Value; + SearchSymbolsRequestParameters requestParameters2 = requestParameters; + IList exchangeIds = requestParameters.ExchangeIds; + if (exchangeIds != null && exchangeIds.Count > 0) + { + List list2 = new List(); + Map map = ??[key]; + foreach (string exchangeId in requestParameters.ExchangeIds) + { + if (map.TryGetDirect(exchangeId, out var value2)) + { + list2.Add(value2); + } + else + { + list2.Add(exchangeId); + } + } + requestParameters2 = new SearchSymbolsRequestParameters(requestParameters) + { + ExchangeIds = list2 + }; + } + foreach (MessageSymbolInfo item3 in value.SearchSymbols(requestParameters2)) + { + MessageSymbolInfo item = ?(key, item3); + list.Add(item); + } + } + return list; + } + + public override IList GetFutureContracts(GetFutureContractsRequestParameters requestParameters) + { + List list = new List(); + string exchangeId = requestParameters.ExchangeId; + HashSet value2; + if (!string.IsNullOrEmpty(requestParameters.UnderlierId)) + { + string underlierId = requestParameters.UnderlierId; + if (?(underlierId, out string text, out ISymbolVendor symbolVendor) && ?(text, underlierId, out var underlierId2) && ??[text].TryGetDirect(exchangeId, out var value)) + { + requestParameters.ExchangeId = value; + requestParameters.UnderlierId = underlierId2; + foreach (MessageSymbolInfo futureContract in symbolVendor.GetFutureContracts(requestParameters)) + { + MessageSymbolInfo item = ?(text, futureContract); + list.Add(item); + } + } + } + else if (!string.IsNullOrEmpty(requestParameters.Root) && ??.TryGetValue(requestParameters.Root, out value2)) + { + foreach (string item3 in value2) + { + if (!??[item3].TryGetDirect(exchangeId, out var value3)) + { + continue; + } + requestParameters.ExchangeId = value3; + foreach (MessageSymbolInfo futureContract2 in ??[item3].GetFutureContracts(requestParameters)) + { + MessageSymbolInfo item2 = ?(item3, futureContract2); + list.Add(item2); + } + } + } + return list; + } + + public override IList GetOptionSeries(GetOptionSeriesRequestParameters requestParameters) + { + if (!?(requestParameters.UnderlierId, out string text, out ISymbolVendor symbolVendor)) + { + return base.GetOptionSeries(requestParameters); + } + if (!?(text, requestParameters.UnderlierId, out var underlierId)) + { + return base.GetOptionSeries(requestParameters); + } + requestParameters.UnderlierId = underlierId; + if (??[text].TryGetDirect(requestParameters.ExchangeId, out var value)) + { + requestParameters.ExchangeId = value; + } + IList optionSeries = symbolVendor.GetOptionSeries(requestParameters); + List list = new List(); + foreach (MessageOptionSerie item2 in optionSeries) + { + MessageOptionSerie item = ?(text, item2); + list.Add(item); + } + return list; + } + + public override IList GetStrikes(GetStrikesRequestParameters requestParameters) + { + if (!?(requestParameters.UnderlierId, out string text, out ISymbolVendor symbolVendor)) + { + return base.GetStrikes(requestParameters); + } + if (!?(text, requestParameters.UnderlierId, out var underlierId)) + { + return base.GetStrikes(requestParameters); + } + requestParameters.UnderlierId = underlierId; + requestParameters.SerieId = ParseLocalId(text, requestParameters.SerieId); + IList strikes = symbolVendor.GetStrikes(requestParameters); + List list = new List(); + foreach (MessageSymbolInfo item2 in strikes) + { + MessageSymbolInfo item = ?(text, item2); + list.Add(item); + } + return list; + } + + /// + /// Retrieves allowed/supported order types + /// + public override IList GetAllowedOrderTypes(CancellationToken token) + { + return TradingVendor?.GetAllowedOrderTypes(token) ?? base.GetAllowedOrderTypes(token); + } + + /// + /// Retrieves an information about opened orders at the time of connection. + /// + public override IList GetPendingOrders(CancellationToken token) + { + return TradingVendor?.GetPendingOrders(token) ?? base.GetPendingOrders(token); + } + + /// + /// Retrieves an information about positions at the time of connection + /// + public override IList GetPositions(CancellationToken token) + { + return TradingVendor?.GetPositions(token) ?? base.GetPositions(token); + } + + public override TradesHistoryMetadata GetTradesMetadata() + { + return TradingVendor?.GetTradesMetadata() ?? base.GetTradesMetadata(); + } + + /// + /// Gets trades history from server for requested time range + /// + public override IList GetTrades(TradesHistoryRequestParameters parameters) + { + return TradingVendor?.GetTrades(parameters) ?? base.GetTrades(parameters); + } + + public override void GetTrades(TradesHistoryRequestParameters parameters, AccountTradesLoadingCallback callback) + { + if (TradingVendor != null) + { + TradingVendor.GetTrades(parameters, callback); + } + else + { + base.GetTrades(parameters, callback); + } + } + + public override IList GetOrdersHistory(OrdersHistoryRequestParameters parameters) + { + return TradingVendor?.GetOrdersHistory(parameters) ?? base.GetOrdersHistory(parameters); + } + + public override PnL CalculatePnL(PnLRequestParameters parameters) + { + return TradingVendor?.CalculatePnL(parameters) ?? base.CalculatePnL(parameters); + } + + /// + /// Subscribing to quote data: Level1/Level2/Trade + /// + public override void SubscribeSymbol(SubscribeQuotesParameters parameters) + { + if (?(parameters.SymbolId, out string text, out IQuoteVendor quoteVendor) && ?(text, parameters.SymbolId, out var symbolId)) + { + quoteVendor.SubscribeSymbol(new SubscribeQuotesParameters(symbolId, parameters.SubscribeType) + { + CancellationToken = parameters.CancellationToken + }); + } + } + + /// + /// Unsubscribing from quote data: Level1/Level2/Trade + /// + public override void UnSubscribeSymbol(SubscribeQuotesParameters parameters) + { + if (?(parameters.SymbolId, out string text, out IQuoteVendor quoteVendor) && ?(text, parameters.SymbolId, out var symbolId)) + { + quoteVendor.UnSubscribeSymbol(new SubscribeQuotesParameters(symbolId, parameters.SubscribeType) + { + CancellationToken = parameters.CancellationToken + }); + } + } + + /// + /// Gets a list of supported historical intervals and data types by vendor + /// + public override HistoryMetadata GetHistoryMetadata(CancellationToken cancelationToken) + { + Dictionary dictionary = new Dictionary(); + foreach (KeyValuePair item in ??) + { + try + { + HistoryMetadata historyMetadata = item.Value.GetHistoryMetadata(cancelationToken); + dictionary.Add(item.Key, historyMetadata); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex.InnerException ?? ex); + } + } + return new HistoryMetadata + { + AllowedAggregations = dictionary.SelectMany((KeyValuePair P_0) => P_0.Value.AllowedAggregations).Distinct().ToArray(), + AllowedPeriodsHistoryAggregationTime = dictionary.SelectMany((KeyValuePair P_0) => P_0.Value.AllowedPeriodsHistoryAggregationTime).Distinct().ToArray(), + AllowedHistoryTypesHistoryAggregationTime = dictionary.SelectMany((KeyValuePair P_0) => P_0.Value.AllowedHistoryTypesHistoryAggregationTime).Distinct().ToArray(), + AllowedHistoryTypesHistoryAggregationTick = dictionary.SelectMany((KeyValuePair P_0) => P_0.Value.AllowedHistoryTypesHistoryAggregationTick).Distinct().ToArray(), + DownloadingStep_Day = dictionary.Min((KeyValuePair P_0) => P_0.Value.DownloadingStep_Day), + DownloadingStep_Minute = dictionary.Min((KeyValuePair P_0) => P_0.Value.DownloadingStep_Minute), + DownloadingStep_Tick = dictionary.Min((KeyValuePair P_0) => P_0.Value.DownloadingStep_Tick), + BuildUncompletedBars = dictionary.Any((KeyValuePair P_0) => P_0.Value.BuildUncompletedBars) + }; + } + + public override IList LoadHistory(HistoryRequestParameters requestParameters) + { + List result = new List(); + if (!?(requestParameters.SymbolId, out string text, out IHistoryVendor historyVendor)) + { + return result; + } + if (!?(text, requestParameters.SymbolId, out var symbolId)) + { + return result; + } + return historyVendor.LoadHistory(new HistoryRequestParameters(requestParameters) + { + SymbolId = symbolId + }); + } + + public override VolumeAnalysisMetadata GetVolumeAnalysisMetadata() + { + if (??.Count == 0) + { + return base.GetVolumeAnalysisMetadata(); + } + foreach (KeyValuePair item in ??) + { + try + { + VolumeAnalysisMetadata volumeAnalysisMetadata = item.Value.GetVolumeAnalysisMetadata(); + ??.Add(item.Key, volumeAnalysisMetadata); + } + catch (Exception exception) + { + Core.Instance.Loggers.Log(exception.GetMessageRecursive()); + } + } + VolumeAnalysisAvailability volumeAnalysisAvailability = (??.Any((KeyValuePair P_0) => P_0.Value.IsVolumeAnalysisAvailable) ? VolumeAnalysisAvailability.Available : VolumeAnalysisAvailability.NotAvailable); + bool buildUncompletedBars = ??.Values.Any((VolumeAnalysisMetadata P_0) => P_0.BuildUncompletedBars); + TimeSpan maxTicksLoadingPeriod = ??.Values.Max((VolumeAnalysisMetadata P_0) => P_0.MaxTicksLoadingPeriod); + Dictionary dictionary = new Dictionary(); + Dictionary dictionary2 = new Dictionary(); + if (volumeAnalysisAvailability == VolumeAnalysisAvailability.Available) + { + foreach (VolumeAnalysisMetadata value in ??.Values) + { + ?(value.GetDownloadingStepByPeriod(includePriceLevels: false), dictionary); + ?(value.GetDownloadingStepByPeriod(includePriceLevels: true), dictionary2); + } + } + return new VolumeAnalysisMetadata + { + VolumeAnalysisAvailability = volumeAnalysisAvailability, + BuildUncompletedBars = buildUncompletedBars, + MaxTicksLoadingPeriod = maxTicksLoadingPeriod, + DownloadingStepByPeriod = dictionary, + DownloadingLevelsStepByPeriod = dictionary2 + }; + } + + public override VendorVolumeAnalysisByPeriodResponse LoadVolumeAnalysis(VolumeAnalysisByPeriodRequestParameters requestParameters) + { + if (!?(requestParameters.SymbolId, out string text, out IVolumeAnalysisVendor volumeAnalysisVendor)) + { + return null; + } + if (!??.TryGetValue(text, out var value)) + { + return null; + } + if (!value.GetAllowedPeriods(requestParameters.CalculatePriceLevels).Contains(requestParameters.Period)) + { + return null; + } + if (!?(text, requestParameters.SymbolId, out var symbolId)) + { + return null; + } + VolumeAnalysisByPeriodRequestParameters copy = requestParameters.Copy; + copy.SymbolId = symbolId; + return volumeAnalysisVendor.LoadVolumeAnalysis(copy); + } + + /// + /// Prepare and sending order placing request to broker + /// + public override TradingOperationResult PlaceOrder(PlaceOrderRequestParameters parameters) + { + return TradingVendor?.PlaceOrder(parameters) ?? base.PlaceOrder(parameters); + } + + public override TradingOperationResult PlaceMultiOrder(PlaceMultiOrderOrderRequestParameters parameters) + { + return TradingVendor?.PlaceMultiOrder(parameters) ?? base.PlaceMultiOrder(parameters); + } + + /// + /// Sending order modification request to broker + /// + public override TradingOperationResult ModifyOrder(ModifyOrderRequestParameters parameters) + { + return TradingVendor?.ModifyOrder(parameters) ?? base.ModifyOrder(parameters); + } + + /// + /// Sending order cancellation request to broker + /// + public override TradingOperationResult CancelOrder(CancelOrderRequestParameters parameters) + { + return TradingVendor?.CancelOrder(parameters) ?? base.CancelOrder(parameters); + } + + /// + /// Sending position closing request to broker + /// + public override TradingOperationResult ClosePosition(ClosePositionRequestParameters parameters) + { + return TradingVendor?.ClosePosition(parameters) ?? base.ClosePosition(parameters); + } + + public override MarginInfo GetMarginInfo(OrderRequestParameters orderRequestParameters) + { + return TradingVendor?.GetMarginInfo(orderRequestParameters) ?? base.GetMarginInfo(orderRequestParameters); + } + + /// + /// Gets information about available reports from vendor + /// + public override IList GetReportsMetaData(CancellationToken token) + { + return TradingVendor?.GetReportsMetaData(token) ?? base.GetReportsMetaData(token); + } + + /// + /// Called when platform need to generate particular report + /// + public override Report GenerateReport(ReportRequestParameters reportRequestParameters) + { + return TradingVendor?.GenerateReport(reportRequestParameters) ?? base.GenerateReport(reportRequestParameters); + } + + private MessageSessionsContainer ?(string P_0, MessageSessionsContainer P_1) + { + P_1.Id = CreateGlobalId(P_0, P_1.Id); + return P_1; + } + + private MessageExchange ?(string P_0, MessageExchange P_1) + { + if (!??.TryGetValue(P_1.ExchangeName, out var value)) + { + value = new MessageExchange + { + Id = ??.Count.ToString(), + ExchangeName = P_1.ExchangeName + }; + ??.Add(value.ExchangeName, value); + } + if (!string.IsNullOrEmpty(P_1.SessionsContainerId)) + { + value.SessionsContainerId = CreateGlobalId(P_0, P_1.SessionsContainerId); + } + if (!??.TryGetValue(P_0, out var value2)) + { + ??.Add(P_0, value2 = new Map()); + } + if (!value2.ContainsDirect(value.Id)) + { + value2.Add(value.Id, P_1.Id); + } + return value; + } + + private MessageSymbolGroup ?(string P_0, MessageSymbolGroup P_1) + { + if (!??.TryGetValue(P_1.GroupName, out var value)) + { + ??.Add(P_1.GroupName, value = P_1); + } + if (!??.TryGetValue(P_0, out var value2)) + { + ??.Add(P_0, value2 = new Map()); + } + if (!value2.ContainsDirect(value.Id)) + { + value2.Add(value.Id, P_1.Id); + } + return value; + } + + private MessageSymbolInfo ?(string P_0, MessageSymbolInfo P_1) + { + if (!??.TryGetValue(P_0, out var value)) + { + return null; + } + if (!value.TryGetReverse(P_1.ExchangeId, out var value2)) + { + return null; + } + MessageSymbolInfo messageSymbolInfo = new MessageSymbolInfo(P_1) + { + Id = CreateGlobalId(P_0, P_1.Id), + ExchangeId = value2 + }; + if (!string.IsNullOrEmpty(messageSymbolInfo.Root)) + { + if (!??.TryGetValue(messageSymbolInfo.Root, out var value3)) + { + ??.Add(messageSymbolInfo.Root, value3 = new HashSet()); + } + value3.Add(P_0); + } + if (!string.IsNullOrEmpty(messageSymbolInfo.UnderlierId)) + { + messageSymbolInfo.UnderlierId = CreateGlobalId(P_0, P_1.UnderlierId); + } + return messageSymbolInfo; + } + + private MessageSymbol ?(string P_0, MessageSymbol P_1) + { + MessageSymbolInfo messageSymbolInfo = ?(P_0, (MessageSymbolInfo)P_1); + MessageSymbol messageSymbol = new MessageSymbol(P_1); + messageSymbol.Fill(messageSymbolInfo); + if (!string.IsNullOrEmpty(messageSymbol.ProductAssetId)) + { + messageSymbol.ProductAssetId = CreateGlobalId(P_0, messageSymbol.ProductAssetId); + } + if (!string.IsNullOrEmpty(messageSymbol.QuotingCurrencyAssetID)) + { + messageSymbol.QuotingCurrencyAssetID = CreateGlobalId(P_0, messageSymbol.QuotingCurrencyAssetID); + } + if (!string.IsNullOrEmpty(messageSymbol.SessionsContainerId)) + { + messageSymbol.SessionsContainerId = CreateGlobalId(P_0, messageSymbol.SessionsContainerId); + } + if (!string.IsNullOrEmpty(messageSymbol.GroupId)) + { + if (!??.TryGetValue(P_0, out var value)) + { + return null; + } + if (!value.TryGetReverse(messageSymbol.GroupId, out var value2)) + { + return null; + } + messageSymbol.GroupId = value2; + } + if (messageSymbol.SymbolAdditionalInfo != null) + { + AdditionalInfoItem additionalInfoItem = messageSymbol.SymbolAdditionalInfo.FirstOrDefault((AdditionalInfoItem additionalInfoItem2) => additionalInfoItem2.Id == 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (additionalInfoItem != null && additionalInfoItem.Value != null) + { + additionalInfoItem.Value = CreateGlobalId(P_0, additionalInfoItem.Value.ToString()); + } + } + return messageSymbol; + } + + private MessageAsset ?(string P_0, MessageAsset P_1) + { + P_1.Id = CreateGlobalId(P_0, P_1.Id); + return P_1; + } + + private MessageOptionSerie ?(string P_0, MessageOptionSerie P_1) + { + if (!??.TryGetValue(P_0, out var value)) + { + return null; + } + if (!value.TryGetReverse(P_1.ExchangeId, out var value2)) + { + return null; + } + P_1.Id = CreateGlobalId(P_0, P_1.Id); + P_1.UnderlierId = CreateGlobalId(P_0, P_1.UnderlierId); + P_1.ExchangeId = value2; + return P_1; + } + + private MessageQuote ?(string P_0, MessageQuote P_1) + { + if (!??.TryGetValue(P_0, out var value)) + { + return null; + } + if (!value.TryGetReverse(P_1.SymbolId, out var value2)) + { + return null; + } + P_1.SymbolId = value2; + return P_1; + } + + public override void SendCustomRequest(RequestParameters parameters) + { + foreach (IVendor allVendor in AllVendors) + { + try + { + allVendor.SendCustomRequest(parameters); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + } + + protected void RegisterTradingVendor(ITradingVendor tradingVendor) + { + if (TradingVendor != null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + TradingVendor = tradingVendor ?? throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + ?(tradingVendor); + } + + protected void RegisterSymbolVendor(ISymbolVendor symbolVendor) + { + ?(symbolVendor.Key, symbolVendor, ??, ??); + } + + protected void RegisterQuoteVendor(IQuoteVendor quoteVendor) + { + ?(quoteVendor.Key, quoteVendor, ??, ??); + } + + protected void RegisterHistoryVendor(IHistoryVendor historyVendor) + { + ?(historyVendor.Key, historyVendor, ??, ??); + } + + protected void RegisterVolumeAnalysisVendor(IVolumeAnalysisVendor volumeAnalysisVendor) + { + ?(volumeAnalysisVendor.Key, volumeAnalysisVendor, ??, ??); + } + + private void ?(string P_0, ? P_1, Dictionary P_2, Dictionary> P_3) where ? : IVendor + { + if (P_1 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + P_2.Add(P_0, P_1); + P_3.Add(P_0, new Map()); + this.?(P_1); + } + + private void ?(? P_0) where ? : IVendor + { + if (P_0 == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + if (!AllVendors.Contains(P_0)) + { + P_0.NewMessage += this.?; + AllVendors.Add(P_0); + } + } + + private void ?(object P_0, VendorEventArgs P_1) + { + if (P_1.Message == null) + { + return; + } + Message message = null; + Message message2 = P_1.Message; + if (!(message2 is MessageExchange messageExchange)) + { + if (!(message2 is MessageSymbolGroup messageSymbolGroup)) + { + if (!(message2 is MessageSymbol messageSymbol)) + { + if (!(message2 is MessageSymbolInfo messageSymbolInfo)) + { + if (!(message2 is MessageAsset messageAsset)) + { + if (!(message2 is MessageOptionSerie messageOptionSerie)) + { + if (message2 is MessageQuote messageQuote) + { + message = ?(P_1.VendorKey, messageQuote); + } + else + { + PushMessage(P_1.Message); + } + } + else + { + message = ?(P_1.VendorKey, messageOptionSerie); + } + } + else + { + message = ?(P_1.VendorKey, messageAsset); + } + } + else + { + message = ?(P_1.VendorKey, messageSymbolInfo); + } + } + else + { + message = ?(P_1.VendorKey, messageSymbol); + } + } + else + { + message = ?(P_1.VendorKey, messageSymbolGroup); + } + } + else + { + message = ?(P_1.VendorKey, messageExchange); + } + if (message != null) + { + PushMessage(message); + } + } + + protected virtual string GetSymbolVendorKey(string globalSymbolId) + { + return ParseVendorKey(globalSymbolId); + } + + protected virtual string GetQuoteVendorKey(string globalSymbolId) + { + return ParseVendorKey(globalSymbolId); + } + + protected virtual string GetHistoryVendorKey(string globalSymbolId) + { + return ParseVendorKey(globalSymbolId); + } + + protected virtual string GetVolumeAnalysisVendorKey(string globalSymbolId) + { + return ParseVendorKey(globalSymbolId); + } + + protected virtual string GetSymbolVendorSymbolId(string vendorKey, string globalSymbolId) + { + return ParseLocalId(vendorKey, globalSymbolId); + } + + protected virtual string GetQuoteVendorSymbolId(string vendorKey, string globalSymbolId) + { + return ParseLocalId(vendorKey, globalSymbolId); + } + + protected virtual string GetHistoryVendorSymbolId(string vendorKey, string globalSymbolId) + { + return ParseLocalId(vendorKey, globalSymbolId); + } + + protected virtual string GetVolumeAnalysisVendorSymbolId(string vendorKey, string globalSymbolId) + { + return ParseLocalId(vendorKey, globalSymbolId); + } + + private bool ?(string P_0, out string P_1, out ISymbolVendor P_2) + { + return ?(P_0, ??, ??, GetSymbolVendorKey, out P_1, out P_2); + } + + private bool ?(string P_0, out string P_1, out IQuoteVendor P_2) + { + return ?(P_0, ??, ??, GetQuoteVendorKey, out P_1, out P_2); + } + + private bool ?(string P_0, out string P_1, out IHistoryVendor P_2) + { + return ?(P_0, ??, ??, GetHistoryVendorKey, out P_1, out P_2); + } + + private bool ?(string P_0, out string P_1, out IVolumeAnalysisVendor P_2) + { + return ?(P_0, ??, ??, GetVolumeAnalysisVendorKey, out P_1, out P_2); + } + + private static bool ?(string P_0, Dictionary P_1, Dictionary P_2, Func P_3, out string P_4, out ? P_5) where ? : IVendor + { + P_4 = null; + P_5 = default(?); + if (P_1.Count == 0) + { + return false; + } + if (P_1.Count == 1) + { + P_4 = P_1.First().Key; + P_5 = P_1.First().Value; + return true; + } + if (!P_2.TryGetValue(P_0, out P_4)) + { + P_4 = P_3(P_0); + if (string.IsNullOrEmpty(P_4)) + { + return false; + } + P_2.Add(P_0, P_4); + } + return P_1.TryGetValue(P_4, out P_5); + } + + private bool ?(string P_0, string P_1, out string P_2) + { + return ?(P_0, P_1, ??[P_0], GetSymbolVendorSymbolId, out P_2); + } + + private bool ?(string P_0, string P_1, out string P_2) + { + return ?(P_0, P_1, ??[P_0], GetQuoteVendorSymbolId, out P_2); + } + + private bool ?(string P_0, string P_1, out string P_2) + { + return ?(P_0, P_1, ??[P_0], GetHistoryVendorSymbolId, out P_2); + } + + private bool ?(string P_0, string P_1, out string P_2) + { + return ?(P_0, P_1, ??[P_0], GetVolumeAnalysisVendorSymbolId, out P_2); + } + + private static bool ?(string P_0, string P_1, Map P_2, Func P_3, out string P_4) + { + if (P_2.TryGetDirect(P_1, out P_4)) + { + return true; + } + P_4 = P_3(P_0, P_1); + if (string.IsNullOrEmpty(P_4)) + { + return false; + } + P_2.Add(P_1, P_4); + return true; + } + + protected virtual string CreateGlobalId(string vendorKey, string localId) + { + return localId + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + vendorKey; + } + + public static string ParseLocalId(string vendorKey, string globalId) + { + string empty = string.Empty; + int num = globalId.IndexOf(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + vendorKey); + if (num == -1) + { + return globalId; + } + return globalId.Substring(0, num); + } + + public static string ParseVendorKey(string globalId) + { + string[] array = globalId.Split(new string[1] { 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() }, StringSplitOptions.RemoveEmptyEntries); + if (array.Length != 2) + { + return string.Empty; + } + return array[1]; + } + + [CompilerGenerated] + internal static void ?(IDictionary P_0, IDictionary P_1) + { + foreach (KeyValuePair item in P_0) + { + if (P_1.ContainsKey(item.Key)) + { + if (item.Value < P_1[item.Key]) + { + P_1[item.Key] = item.Value; + } + } + else + { + P_1[item.Key] = item.Value; + } + } + } + } + public sealed class NewsRealtimeByTimerUpdater : IDisposable + { + private bool ??; + + private readonly Timer ??; + + private readonly ConcurrentDictionary ??; + + private readonly Action ??; + + private readonly Func> ??; + + public NewsRealtimeByTimerUpdater(Action pushMessage, Func> getNews, TimeSpan updatePeriod) + { + ?? = pushMessage; + ?? = getNews; + ?? = new ConcurrentDictionary(); + ?? = new Timer(?, null, updatePeriod, updatePeriod); + } + + public void Dispose() + { + ??.Dispose(); + } + + public void SubscribeNewsUpdates(SubscribeNewsRequestParameters parameters) + { + ??[parameters.SubscribeId] = new ?(parameters.AdditionalParameters) + { + lastRealTimeNewsRequestTime = Core.Instance.TimeUtils.DateTimeUtcNow + }; + } + + public void UnsubscribeNewsUpdates(SubscribeNewsRequestParameters parameters) + { + ??.TryRemove(parameters.SubscribeId, out var _); + } + + private void ?(object P_0) + { + if (??) + { + return; + } + try + { + ?? = true; + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + foreach (KeyValuePair item in ??) + { + IEnumerable enumerable = ??(new GetNewsRequestParameters + { + AdditionalParameters = item.Value.??, + From = item.Value.lastRealTimeNewsRequestTime, + To = dateTimeUtcNow + }); + item.Value.lastRealTimeNewsRequestTime = dateTimeUtcNow; + foreach (MessageNewsHeadline item2 in enumerable) + { + item2.SubscribeId = item.Key; + ??(item2); + } + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + ?? = false; + } + } + } +} +namespace ? +{ + internal sealed class ? + { + public readonly IEnumerable ??; + + [CompilerGenerated] + private DateTime ??; + + public DateTime lastRealTimeNewsRequestTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = dateTime; + } + } + + public ?(IEnumerable P_0) + { + ?? = P_0; + } + } +} +namespace TradingPlatform.BusinessLayer.Integration +{ + public class PingMeter + { + private readonly string ??; + + private readonly Ping ??; + + private readonly Uri ??; + + public PingMeter(string ownerName, string endpoint) + { + ?? = ownerName; + ?? = new Ping(); + ?? = new Uri(endpoint); + } + + public TimeSpan? MeasurePing() + { + try + { + PingReply pingReply = ??.Send(??.Host); + if (pingReply != null && pingReply.Status == IPStatus.Success) + { + return TimeSpan.FromMilliseconds(pingReply.RoundtripTime); + } + Core.Instance.Loggers.Log(?? + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + ??.Host); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + return null; + } + } + /// + /// Ping respond bundle + /// + public class PingResult + { + [CompilerGenerated] + private TimeSpan? ??; + + [CompilerGenerated] + private TimeSpan? ??; + + [CompilerGenerated] + private PingEnum ??; + + [CompilerGenerated] + private bool ??; + + /// + /// Ping time + /// + public TimeSpan? PingTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Time spent for single request + /// + public TimeSpan? RoundTripTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Ping state + /// + public PingEnum State + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + /// + /// Disable auto reconnecting + /// + public bool StopReconnecting + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public static PingResult Disconnected() + { + return new PingResult + { + State = PingEnum.Disconnected + }; + } + } + public class ResponseWaiterBase + { + public readonly long RequestId; + + public bool isFinish; + + [CompilerGenerated] + private TimeSpan ??; + + public TimeSpan Elapsed + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = timeSpan; + } + } + + public ResponseWaiterBase(long requestId) + { + RequestId = requestId; + } + + public bool WaitForResponse(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken)) + { + Elapsed = TimeSpan.Zero; + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + while (!isFinish) + { + if (cancellationToken.IsCancellationRequested) + { + return false; + } + Elapsed = stopwatch.Elapsed; + if (timeout < stopwatch.Elapsed) + { + return false; + } + Thread.Sleep(20); + } + return true; + } + } + public class ResponseWaiter : ResponseWaiterBase + { + public T Response; + + public ResponseWaiter(long requestId) + : base(requestId) + { + } + } + public class TradesHistoryMetadata + { + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ?? = true; + + [CompilerGenerated] + private bool ??; + + public bool AllowLocalStorage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AllowSingleSymbolLoading + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool AllowReloadFromServer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool LoadTradesFromCurrentTradingDate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TradesHistoryMetadata() + { + } + + public TradesHistoryMetadata(TradesHistoryMetadata origin) + : this() + { + AllowLocalStorage = origin.AllowLocalStorage; + AllowSingleSymbolLoading = origin.AllowSingleSymbolLoading; + AllowReloadFromServer = origin.AllowReloadFromServer; + LoadTradesFromCurrentTradingDate = origin.LoadTradesFromCurrentTradingDate; + } + } + public abstract class Vendor : ITradingVendor, IVendor, ISymbolVendor, IQuoteVendor, IHistoryVendor, IVolumeAnalysisVendor + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + internal bool ?(Period P_0) + { + return P_0.BasePeriod == BasePeriod.Tick; + } + + internal int ?(Period P_0) + { + return P_0.PeriodMultiplier; + } + } + + public static readonly string LOGIN_PARAMETER_USER = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public static readonly string LOGIN_PARAMETER_PASSWORD = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public const string LOGIN_PARAMETER_GROUP = "ConnectionGroup"; + + public const string ADDITIONAL_PARAMETER_GROUP = "AdditionalParametersGroup"; + + public const string REPORT_TYPE_PARAMETER_ACCOUNT = "Account"; + + public const string REPORT_TYPE_PARAMETER_SYMBOL = "Symbol"; + + public const string REPORT_TYPE_PARAMETER_DATETIME_FROM = "From"; + + public const string REPORT_TYPE_PARAMETER_DATETIME_TO = "To"; + + public static readonly string CONNECTION = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(); + + public static readonly string CONNECTION_DEMO = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public static readonly string CONNECTION_REAL = loc.key(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + + public const string EMULATOR = "Emulator"; + + public const string MARKET_REPLAY = "Market Replay"; + + public const string TRADING_SIMULATOR = "Trading Simulator"; + + [CompilerGenerated] + private EventHandler ??; + + private string ??; + + /// + /// Confirms allowed non fixed list by vendor + /// + public virtual bool AllowNonFixedList => false; + + public virtual DateTime? ServerTime => null; + + string IVendor.Key + { + get + { + return ??; + } + set + { + ?? = text; + } + } + + public event EventHandler NewMessage + { + [CompilerGenerated] + add + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + [CompilerGenerated] + remove + { + EventHandler eventHandler = ??; + EventHandler eventHandler2; + do + { + eventHandler2 = eventHandler; + EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value); + eventHandler = Interlocked.CompareExchange(ref ??, value2, eventHandler2); + } + while ((object)eventHandler != eventHandler2); + } + } + + [SpecialName] + private void ?(EventHandler P_0) + { + NewMessage += P_0; + } + + void IVendor.add_NewMessage(EventHandler P_0) + { + //ILSpy generated this explicit interface implementation from .override directive in ? + this.?(P_0); + } + + [SpecialName] + private void ?(EventHandler P_0) + { + NewMessage -= P_0; + } + + void IVendor.remove_NewMessage(EventHandler P_0) + { + //ILSpy generated this explicit interface implementation from .override directive in ? + this.?(P_0); + } + + /// + /// Performs a binding with broker or data provider + /// + public virtual ConnectionResult Connect(ConnectRequestParameters connectRequestParameters) + { + return new ConnectionResult + { + State = ConnectionState.Fail + }; + } + + /// + /// Specifies any operation before breaking a connection with broker or data provider + /// + public virtual void Disconnect() + { + } + + /// + /// Called when platform finished retreiving all required informations from vendor during connecting + /// + public virtual void OnConnected(CancellationToken token) + { + } + + /// + /// Ping processing before its visualization in the terminal + /// + public virtual PingResult Ping() + { + return new PingResult(); + } + + public virtual LimitationMetadata GetLimitationMetadata() + { + return new LimitationMetadata(); + } + + /// + /// Retrieves an information about available accounts. Yon need to specify at least one account + /// + public virtual IList GetAccounts(CancellationToken token) + { + return new List(); + } + + public virtual IList GetRules(CancellationToken token) + { + return new List(); + } + + public virtual IList GetCryptoAssetBalances(CancellationToken token) + { + return new List(); + } + + public virtual IList GetAccountOperations(CancellationToken token) + { + return new List(); + } + + public virtual IList GetSessions(CancellationToken token) + { + return new List(); + } + + /// + /// Retrieves a collection of available exchange markets from vendor + /// + public virtual IList GetExchanges(CancellationToken token) + { + return new List + { + new MessageExchange + { + Id = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + ExchangeName = 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), + SortIndex = -1 + } + }; + } + + /// + /// Retrieves information about available assets. + /// + public virtual IList GetAssets(CancellationToken token) + { + return new List(); + } + + public virtual IList GetSymbols(CancellationToken token) + { + return new List(); + } + + /// + /// Retrieves information about available symbols. + /// + public virtual IList GetAllOptionSeries(CancellationToken token) + { + return new List(); + } + + /// + /// Gets an available symbols types from vendor + /// + public virtual MessageSymbolTypes GetSymbolTypes(CancellationToken token) + { + return new MessageSymbolTypes + { + SymbolTypes = new List((SymbolType[])Enum.GetValues(typeof(SymbolType))) + }; + } + + public virtual IList GetSymbolGroups(CancellationToken token) + { + return new List(); + } + + /// + /// Derives a non fixed symbol from vendor + /// + public virtual MessageSymbol GetNonFixedSymbol(GetSymbolRequestParameters requestParameters) + { + return null; + } + + /// + /// Derives a non-fixed list of symbols from vendor + /// + public virtual IList SearchSymbols(SearchSymbolsRequestParameters requestParameters) + { + return new List(); + } + + public virtual IList GetFutureContracts(GetFutureContractsRequestParameters requestParameters) + { + return new List(); + } + + public virtual IList GetOptionSeries(GetOptionSeriesRequestParameters requestParameters) + { + return new List(); + } + + public virtual IList GetStrikes(GetStrikesRequestParameters requestParameters) + { + return new List(); + } + + /// + /// Retrieves an information about opened orders at the time of connection. + /// + public virtual IList GetPendingOrders(CancellationToken token) + { + return new List(); + } + + /// + /// Retrieves an information about positions at the time of connection + /// + public virtual IList GetPositions(CancellationToken token) + { + return new List(); + } + + /// + /// Retrieves an information about closed positions at the time of connection + /// + public virtual IList GetClosedPositions(CancellationToken token) + { + return new List(); + } + + /// + /// Subscribing to quote data: Level1/Level2/Trade + /// + public virtual void SubscribeSymbol(SubscribeQuotesParameters parameters) + { + } + + /// + /// Unsubscribing from quote data: Level1/Level2/Trade + /// + public virtual void UnSubscribeSymbol(SubscribeQuotesParameters parameters) + { + } + + public virtual IList LoadHistory(HistoryRequestParameters requestParameters) + { + return new List(); + } + + /// + /// Gets a list of supported historical intervals and data types by vendor + /// + public virtual HistoryMetadata GetHistoryMetadata(CancellationToken cancellationToken) + { + return new HistoryMetadata(); + } + + public virtual VendorVolumeAnalysisByPeriodResponse LoadVolumeAnalysis(VolumeAnalysisByPeriodRequestParameters requestParameters) + { + return VendorVolumeAnalysisByPeriodResponse.CreateDefault(); + } + + public virtual VolumeAnalysisMetadata GetVolumeAnalysisMetadata() + { + return new VolumeAnalysisMetadata(); + } + + /// + /// Prepare and sending order placing request to broker + /// + public virtual TradingOperationResult PlaceOrder(PlaceOrderRequestParameters parameters) + { + return TradingOperationResult.CreateError(parameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + public virtual TradingOperationResult PlaceMultiOrder(PlaceMultiOrderOrderRequestParameters parameters) + { + return TradingOperationResult.CreateError(parameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + /// + /// Sending order modification request to broker + /// + public virtual TradingOperationResult ModifyOrder(ModifyOrderRequestParameters parameters) + { + return TradingOperationResult.CreateError(parameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + /// + /// Sending order cancellation request to broker + /// + public virtual TradingOperationResult CancelOrder(CancelOrderRequestParameters parameters) + { + return TradingOperationResult.CreateError(parameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + /// + /// Sending position closing request to broker + /// + public virtual TradingOperationResult ClosePosition(ClosePositionRequestParameters parameters) + { + return TradingOperationResult.CreateError(parameters.RequestId, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + + public virtual MarginInfo GetMarginInfo(OrderRequestParameters orderRequestParameters) + { + return null; + } + + /// + /// Gets information about available reports from vendor + /// + public virtual IList GetReportsMetaData(CancellationToken token) + { + return new List(); + } + + /// + /// Called when platform need to generate particular report + /// + public virtual Report GenerateReport(ReportRequestParameters reportRequestParameters) + { + return new Report(); + } + + public virtual IEnumerable GetNewsProviderSettings(CancellationToken cancellationToken) + { + return Array.Empty(); + } + + public virtual IEnumerable GetNews(GetNewsRequestParameters requestParameters) + { + return Array.Empty(); + } + + public virtual void SubscribeNewsUpdates(SubscribeNewsRequestParameters subscribeNewsRequestParameters) + { + } + + public virtual void UnsubscribeNewsUpdates(SubscribeNewsRequestParameters subscribeNewsRequestParameters) + { + } + + public virtual string GetNewsArticleContent(GetNewsArticleContentRequestParameters requestParameters) + { + return string.Empty; + } + + public virtual IEnumerable GetTradingSignals(CancellationToken cancellationToken) + { + return Array.Empty(); + } + + public virtual TradesHistoryMetadata GetTradesMetadata() + { + return new TradesHistoryMetadata(); + } + + public virtual IList GetTrades(TradesHistoryRequestParameters parameters) + { + return Array.Empty(); + } + + public virtual void GetTrades(TradesHistoryRequestParameters parameters, AccountTradesLoadingCallback callback) + { + callback?.Invoke(GetTrades(parameters), isFinished: true); + } + + public virtual IList GetOrdersHistory(OrdersHistoryRequestParameters parameters) + { + return Array.Empty(); + } + + /// + /// Retrieves allowed/supported order types + /// + public virtual IList GetAllowedOrderTypes(CancellationToken token) + { + return new List(); + } + + public void PushMessage(Message msg) + { + ???.Invoke(this, new VendorEventArgs(??, msg)); + } + + public virtual PnL CalculatePnL(PnLRequestParameters parameters) + { + return null; + } + + public virtual void SendCustomRequest(RequestParameters parameters) + { + } + + protected static ConnectionInfo CreateDefaultConnectionInfo(string name, string vendorName, string logoPath = null, string group = null, bool allowCreateCustomConnections = true, ConnectionState connectionState = ConnectionState.Disconnected, IList settings = null, List links = null, string copyrights = null) + { + return new ConnectionInfo(name, group, vendorName) + { + ConnectionLogoPath = logoPath, + AllowCreateCustomConnections = allowCreateCustomConnections, + ConnectionState = connectionState, + ConnectionSettings = settings, + Links = links, + Copyrights = copyrights + }; + } + + [Conditional("quantower_licences")] + [Conditional("quantower_in_licences")] + [Conditional("quantower_br_licences")] + [Conditional("capfinex_licences")] + [Conditional("roemaker_licences")] + [Conditional("coincidence_licences")] + [Conditional("alpha_trader_licenses")] + [Conditional("vt_terminal_licences")] + [Conditional("quantower_de_licences")] + [Conditional("flowtrade_licences")] + [Conditional("spy_money_licences")] + [Conditional("total_trading_terminal_licences")] + protected void CheckLicenceMultiAssetVendor() + { + if ((Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) ?? Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?())) == null && Core.Instance.Licences.GetLicenceRuleItem(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) != null) + { + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + } + + public static bool TryCorrectPeriodForDirectDownload(Period[] allowedPeriods, Period currentPeriod, out Period allowedPeriod) + { + allowedPeriod = currentPeriod; + if (allowedPeriods == null) + { + allowedPeriods = Array.Empty(); + } + if (allowedPeriods.Contains(currentPeriod)) + { + return true; + } + if (currentPeriod.BasePeriod == BasePeriod.Tick) + { + Period[] array = (from P_0 in allowedPeriods + where P_0.BasePeriod == BasePeriod.Tick + orderby P_0.PeriodMultiplier descending + select P_0).ToArray(); + for (int num = 0; num < array.Length; num++) + { + Period period = array[num]; + if (currentPeriod.PeriodMultiplier % period.PeriodMultiplier == 0) + { + allowedPeriod = period; + return true; + } + } + } + else + { + Period[] array = allowedPeriods; + for (int num = 0; num < array.Length; num++) + { + Period period2 = array[num]; + if (currentPeriod.Ticks % period2.Ticks == 0L) + { + allowedPeriod = period2; + return true; + } + } + } + return false; + } + } + public delegate void AccountTradesLoadingCallback(IList messages, bool isFinished); + public class VendorEventArgs : EventArgs + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private Message ??; + + public string VendorKey + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = text; + } + } + + public Message Message + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = message; + } + } + + public VendorEventArgs(string vendorKey, Message message) + { + VendorKey = vendorKey; + Message = message; + } + } + public class VendorInfo + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal SettingItem ?(SettingItem P_0) + { + return P_0.GetCopy(); + } + } + + [CompilerGenerated] + private VendorMetaData ??; + + private readonly IList ??; + + [CompilerGenerated] + private ConnectionInfo[] ??; + + private readonly Type ??; + + private readonly SemaphoreSlim ??; + + public VendorMetaData MetaData + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = vendorMetaData; + } + } + + public SettingItem[] ConnectionParameters => ??.Select((SettingItem P_0) => P_0.GetCopy()).ToArray(); + + public ConnectionInfo[] DefaultConnections + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = array; + } + } + + internal VendorInfo(VendorMetaData P_0, Type P_1) + { + MetaData = P_0; + ?? = P_0.GetConnectionParameters(); + DefaultConnections = P_0.GetDefaultConnections().ToArray(); + ConnectionInfo[] defaultConnections = DefaultConnections; + for (int i = 0; i < defaultConnections.Length; i++) + { + defaultConnections[i].VendorInfo = this; + } + ?? = P_1; + if (P_0.SimultaneousConnectingProcessLimit > 0) + { + ?? = new SemaphoreSlim(P_0.SimultaneousConnectingProcessLimit); + } + } + + internal Vendor ?() + { + return Activator.CreateInstance(??) as Vendor; + } + + internal void ?() + { + ???.Wait(); + } + + internal void ?() + { + ???.Release(); + } + + public override string ToString() + { + return MetaData?.VendorName; + } + } + public class VendorManager + { + private readonly Dictionary ??; + + public VendorInfo[] Vendors => ??.Values.ToArray(); + + public VendorInfo this[string vendorName] + { + get + { + ??.TryGetValue(vendorName, out var value); + return value; + } + } + + internal VendorManager() + { + ?? = new Dictionary(); + } + + internal void ?() + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + if (!Directory.Exists(Const.CUSTOM_VENDORS_PATH)) + { + Directory.CreateDirectory(Const.CUSTOM_VENDORS_PATH); + } + List list = AssemblyLoader.LoadTypes(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), typeof(Vendor), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchOption.AllDirectories); + list.AddRange(AssemblyLoader.LoadTypes(Const.CUSTOM_VENDORS_PATH, typeof(Vendor), 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), SearchOption.AllDirectories)); + if (!list.Any()) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + return; + } + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(38, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + foreach (TypeWrapper item in list) + { + Type type = item; + try + { + if (type.IsAbstract) + { + continue; + } + MethodInfo method = type.GetMethod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BindingFlags.Static | BindingFlags.Public); + if (!(method != null)) + { + continue; + } + if (method.Invoke(null, null) is VendorMetaData vendorMetaData) + { + if (vendorMetaData == null || string.IsNullOrEmpty(vendorMetaData.VendorName)) + { + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(type); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Verbose); + } + else if (??.ContainsKey(vendorMetaData.VendorName)) + { + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + vendorMetaData.VendorName, LoggingLevel.Verbose); + } + else + { + ??.Add(vendorMetaData.VendorName, new VendorInfo(vendorMetaData, type)); + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + vendorMetaData.VendorName + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + } + else + { + Core.Instance.Loggers.Log(type.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + } + Core.Instance.Loggers.Log(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), LoggingLevel.Verbose); + } + + internal void ?() + { + ???.Clear(); + } + } + public class VendorMetaData + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func> ??; + + public static Func> ??; + + internal IList ?() + { + return new List(); + } + + internal IList ?() + { + return new List(); + } + } + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + public Func> GetDefaultConnections; + + /// + /// Gets a settings list from a vendor selection of the setup window + /// + public Func> GetConnectionParameters; + + public string VendorName + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string VendorDescription + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int SimultaneousConnectingProcessLimit + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VendorMetaData() + { + GetDefaultConnections = () => new List(); + GetConnectionParameters = () => new List(); + } + } + public class VendorHistoryResponse : VendorIntervalResponse> + { + public VendorHistoryResponse(IList data) + : base(data) + { + } + + public VendorHistoryResponse(string errorText) + : base(errorText) + { + } + + public static VendorHistoryResponse CreateSuccess(IList data) + { + return new VendorHistoryResponse(data); + } + + public static VendorHistoryResponse CreateError(string errorText) + { + return new VendorHistoryResponse(errorText); + } + + public static VendorHistoryResponse CreateError(Exception exception) + { + return new VendorHistoryResponse(exception.GetMessageRecursive()); + } + } + public class VendorIntervalResponse : VendorResponse + { + [CompilerGenerated] + private Interval ??; + + public Interval ActualDataInterval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VendorIntervalResponse(TData data) + : base(data) + { + } + + public VendorIntervalResponse(string errorText) + : base(errorText) + { + } + } + public class VendorResponse + { + [CompilerGenerated] + private TData ??; + + [CompilerGenerated] + private string ??; + + public TData Data + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public string ErrorText + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VendorResponse(TData data) + { + Data = data; + } + + public VendorResponse(string errorText) + { + ErrorText = errorText; + } + } + public class VendorVolumeAnalysisByPeriodResponse : VendorIntervalResponse> + { + private VendorVolumeAnalysisByPeriodResponse(IList P_0) + : base(P_0) + { + } + + private VendorVolumeAnalysisByPeriodResponse(string P_0) + : base(P_0) + { + } + + public static VendorVolumeAnalysisByPeriodResponse CreateDefault() + { + return new VendorVolumeAnalysisByPeriodResponse(new List()); + } + + public static VendorVolumeAnalysisByPeriodResponse CreateSuccess(IList data, Interval actualInterval) + { + return new VendorVolumeAnalysisByPeriodResponse(data) + { + ActualDataInterval = actualInterval + }; + } + + public static VendorVolumeAnalysisByPeriodResponse CreateError(string errorText) + { + return new VendorVolumeAnalysisByPeriodResponse(errorText); + } + + public static VendorVolumeAnalysisByPeriodResponse CreateError(Exception exception) + { + return new VendorVolumeAnalysisByPeriodResponse(exception.GetMessageRecursive()); + } + } + public class VendorVolumeAnalysisResponse : VendorIntervalResponse + { + private VendorVolumeAnalysisResponse(VolumeAnalysisData P_0) + : base(P_0) + { + } + + private VendorVolumeAnalysisResponse(string P_0) + : base(P_0) + { + } + + public static VendorVolumeAnalysisResponse CreateDefault() + { + return new VendorVolumeAnalysisResponse(new VolumeAnalysisData()); + } + + public static VendorVolumeAnalysisResponse CreateSuccess(VolumeAnalysisData data, Interval actualInterval) + { + return new VendorVolumeAnalysisResponse(data) + { + ActualDataInterval = actualInterval + }; + } + + public static VendorVolumeAnalysisResponse CreateError(string errorText) + { + return new VendorVolumeAnalysisResponse(errorText); + } + + public static VendorVolumeAnalysisResponse CreateError(Exception exception) + { + return new VendorVolumeAnalysisResponse(exception.GetMessageRecursive()); + } + } + public class VolumeAnalysisByPeriodRequestParameters : VolumeAnalysisRequestParameters + { + [CompilerGenerated] + private Period ??; + + [CompilerGenerated] + private bool ??; + + public override RequestType Type => RequestType.VolumeAnalysisByPeriod; + + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool ForceReload + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public new VolumeAnalysisByPeriodRequestParameters Copy => new VolumeAnalysisByPeriodRequestParameters(this); + + public VolumeAnalysisByPeriodRequestParameters() + { + base.CalculatePriceLevels = false; + } + + internal VolumeAnalysisByPeriodRequestParameters(VolumeAnalysisByPeriodRequestParameters P_0) + : base(P_0) + { + Period = P_0.Period; + ForceReload = P_0.ForceReload; + } + + public VolumeAnalysisDescription ToDescription() + { + return new VolumeAnalysisDescription(base.SymbolId, Period, base.CalculatePriceLevels); + } + } + [ProtoContract] + public class VolumeAnalysisMetadata + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + internal long ?(Period P_0) + { + return P_0.Ticks; + } + } + + [CompilerGenerated] + private readonly VolumeAnalysisAvailability ??; + + private readonly Dictionary ??; + + [CompilerGenerated] + private readonly Dictionary ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private TimeSpan ??; + + public VolumeAnalysisAvailability VolumeAnalysisAvailability + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public Dictionary DownloadingStepByPeriod + { + private get + { + return ??; + } + init + { + ?? = value; + if (DownloadingLevelsStepByPeriod == null || DownloadingLevelsStepByPeriod.Count == 0) + { + DownloadingLevelsStepByPeriod = new Dictionary(value); + } + } + } + + public Dictionary DownloadingLevelsStepByPeriod + { + [CompilerGenerated] + private get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + internal bool IsVolumeAnalysisAvailable + { + get + { + if (VolumeAnalysisAvailability == VolumeAnalysisAvailability.Available) + { + return DownloadingStepByPeriod.Count > 0; + } + return false; + } + } + + public bool BuildUncompletedBars + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeSpan MaxTicksLoadingPeriod + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + internal VolumeAnalysisMetadata Copy => new VolumeAnalysisMetadata + { + VolumeAnalysisAvailability = VolumeAnalysisAvailability, + BuildUncompletedBars = BuildUncompletedBars, + MaxTicksLoadingPeriod = MaxTicksLoadingPeriod, + DownloadingStepByPeriod = new Dictionary(DownloadingStepByPeriod), + DownloadingLevelsStepByPeriod = new Dictionary(DownloadingLevelsStepByPeriod) + }; + + public VolumeAnalysisMetadata() + { + VolumeAnalysisAvailability = VolumeAnalysisAvailability.NotAvailable; + MaxTicksLoadingPeriod = TimeSpan.FromHours(1.0); + DownloadingStepByPeriod = new Dictionary(); + } + + public IDictionary GetDownloadingStepByPeriod(bool includePriceLevels) + { + if (!includePriceLevels) + { + return DownloadingStepByPeriod; + } + return DownloadingLevelsStepByPeriod; + } + + public Period[] GetAllowedPeriods(bool includePriceLevels) + { + return GetDownloadingStepByPeriod(includePriceLevels)?.Keys.OrderByDescending((Period P_0) => P_0.Ticks).ToArray(); + } + + public bool TryFindLargestLoadingPeriod(DateTime from, DateTime to, bool includeLevels, out Period period) + { + return TryFindLargestLoadingPeriod(new Interval(from, to), includeLevels, out period); + } + + public bool TryFindLargestLoadingPeriod(Interval interval, bool includeLevels, out Period period) + { + period = default(Period); + Period[] allowedPeriods = GetAllowedPeriods(includeLevels); + foreach (Period period2 in allowedPeriods) + { + if (interval.Contains(period2)) + { + period = period2; + return true; + } + } + return false; + } + } + public class VolumeAnalysisRequestParameters : RequestParameters + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private DateTime ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private ISessionsContainer ??; + + public override RequestType Type => RequestType.VolumeAnalysis; + + public string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime FromTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public DateTime ToTime + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double MinVolumeAnalysisTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public Interval Interval + { + get + { + return new Interval(FromTime, ToTime); + } + set + { + FromTime = value.From; + ToTime = value.To; + } + } + + public bool CalculatePriceLevels + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ISessionsContainer SessionsContainer + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VolumeAnalysisRequestParameters Copy => new VolumeAnalysisRequestParameters(this); + + public VolumeAnalysisRequestParameters() + { + CalculatePriceLevels = true; + MinVolumeAnalysisTickSize = double.NaN; + } + + internal VolumeAnalysisRequestParameters(VolumeAnalysisRequestParameters P_0) + { + SymbolId = P_0.SymbolId; + FromTime = P_0.FromTime; + ToTime = P_0.ToTime; + CalculatePriceLevels = P_0.CalculatePriceLevels; + base.CancellationToken = P_0.CancellationToken; + SessionsContainer = P_0.SessionsContainer; + MinVolumeAnalysisTickSize = P_0.MinVolumeAnalysisTickSize; + } + } +} +namespace TradingPlatform.BusinessLayer.Integration.Limitation +{ + public record Limit + { + public Period Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public int Value + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public LimitInterval Interval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + public RequestType[] RequestTypes + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + + [CompilerGenerated] + private readonly Period ??; + + [CompilerGenerated] + private readonly int ??; + + [CompilerGenerated] + private readonly LimitInterval ??; + + [CompilerGenerated] + private readonly RequestType[] ??; + + public Limit(Period Period, int Value, LimitInterval Interval, params RequestType[] RequestTypes) + { + ?? = Period; + ?? = Value; + ?? = Interval; + ?? = RequestTypes; + base..ctor(); + } + + [CompilerGenerated] + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + stringBuilder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + if (PrintMembers(stringBuilder)) + { + stringBuilder.Append(' '); + } + stringBuilder.Append('}'); + return stringBuilder.ToString(); + } + + [CompilerGenerated] + protected virtual bool PrintMembers(StringBuilder builder) + { + RuntimeHelpers.EnsureSufficientExecutionStack(); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(Period.ToString()); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(Value.ToString()); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(Interval.ToString()); + builder.Append(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + builder.Append(RequestTypes); + return true; + } + + [CompilerGenerated] + public void Deconstruct(out Period Period, out int Value, out LimitInterval Interval, out RequestType[] RequestTypes) + { + Period = this.Period; + Value = this.Value; + Interval = this.Interval; + RequestTypes = this.RequestTypes; + } + } + public class LimitationMetadata + { + [CompilerGenerated] + private readonly IList ??; + + public IList Limits + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } + public enum LimitInterval + { + FixedCalendar, + FloatingWindow + } +} +namespace ? +{ + internal class ? : IDisposable + { + private class ? + { + private readonly CancellationToken ??; + + private readonly ManualResetEventSlim ??; + + private IList ??; + + public bool IsCancelled => ??.IsCancellationRequested; + + public IList History + { + get + { + return ??; + } + set + { + ?? = list; + ??.Set(); + } + } + + public ?(CancellationToken P_0) + { + ?? = P_0; + ?? = new ManualResetEventSlim(); + } + + public void ?(CancellationToken P_0) + { + WaitHandle.WaitAny(new WaitHandle[2] { ??.WaitHandle, P_0.WaitHandle }); + } + } + + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func ??; + + public static Func ??; + + public static Func> ??; + + public static Func ??; + + internal int ?(HistoryInterval P_0) + { + return P_0.History.Count; + } + + internal DateTime ?(HistoryInterval P_0) + { + return P_0.Interval.From; + } + + internal IEnumerable ?(HistoryInterval P_0) + { + return P_0.History; + } + + internal bool ?(? P_0) + { + return !P_0.IsCancelled; + } + } + + [CompilerGenerated] + private sealed class ? + { + public ? ??; + + public HistoryRequestParameters ??; + + public int ??; + + internal void ?() + { + IList history = null; + try + { + history = ??.?(??); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + lock (??.??) + { + if (??.??.TryGetValue(??, out var value)) + { + ??.??.Remove(??); + foreach (? item in value) + { + item.History = history; + } + } + } + } + } + } + + private readonly HistoryStorage ??; + + private readonly TaskFactory ??; + + private readonly DegreeOfParallelismTaskScheduler ??; + + private readonly ? ??; + + private readonly Dictionary> ??; + + private readonly object ??; + + public static ? ?(? P_0) + { + HistoryStorage historyStorage = null; + if (P_0.AllowLocalStorage) + { + historyStorage = HistoryStorage.Create(P_0.LocalStorageConnectionString); + } + return new ?(P_0.DegreeOfParallelism, P_0.LoadHistoryDelegate, historyStorage); + } + + internal ?(int P_0, ? P_1, HistoryStorage P_2 = null) + { + ?? = new DegreeOfParallelismTaskScheduler(P_0); + ?? = new TaskFactory(??); + ?? = P_1; + ?? = P_2; + ?? = new Dictionary>(); + ?? = new object(); + } + + public IList ?(HistoryRequestParameters P_0) + { + int ?? = ?(P_0); + ? ?2 = new ?(P_0.CancellationToken); + bool flag = false; + lock (??) + { + if (??.TryGetValue(??, out var value)) + { + value.Add(?2); + } + else + { + ??.Add(??, new List { ?2 }); + flag = true; + } + } + if (flag) + { + ??.StartNew(delegate + { + IList history = null; + try + { + history = ?(P_0); + } + catch (Exception ex) + { + Core.Instance.Loggers.Log(ex); + } + finally + { + lock (??) + { + if (??.TryGetValue(??, out var value2)) + { + ??.Remove(??); + foreach (? item in value2) + { + item.History = history; + } + } + } + } + }); + } + ?2.?(P_0.CancellationToken); + return ?2.History ?? new List(); + } + + internal virtual IList ?(HistoryRequestParameters P_0) + { + List result = new List(); + List list = new List(); + List historyParametersForServerRequest = new List(); + if (!P_0.ForceReload && ?? != null) + { + LoggerManager loggers = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(52, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + IList list2 = ??.Load(P_0, out historyParametersForServerRequest); + if (?(P_0)) + { + return result; + } + list.AddRange(list2); + LoggerManager loggers2 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(75, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list2.Sum((HistoryInterval historyInterval) => historyInterval.History.Count)); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers2.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + } + else + { + historyParametersForServerRequest.Add(P_0); + } + foreach (HistoryRequestParameters item in historyParametersForServerRequest) + { + if (?(P_0)) + { + break; + } + LoggerManager loggers3 = Core.Instance.Loggers; + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(50, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers3.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + DateTime dateTimeUtcNow = Core.Instance.TimeUtils.DateTimeUtcNow; + if (!(??(item) is List list3) || ?(P_0)) + { + break; + } + if (item.Aggregation is HistoryAggregationTick && !item.Symbol.HistoryMetadata.ServerSideTickDirectionAvailable) + { + list3.ProcessTickDirection(P_0.CancellationToken); + } + list.Add(new HistoryInterval + { + Description = item.ToDescription(), + Interval = item.Interval, + History = new List(list3) + }); + if (?(item, list3, dateTimeUtcNow, item.Symbol.HistoryMetadata.BuildUncompletedBars)) + { + ???.Save(new HistoryInterval + { + Description = item.ToDescription(), + Interval = item.Interval, + History = list3 + }); + } + LoggerManager loggers4 = Core.Instance.Loggers; + defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(73, 2); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(P_0.RequestId); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(list3.Count); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + loggers4.Log(defaultInterpolatedStringHandler.ToStringAndClear(), LoggingLevel.Performance); + } + return list.OrderBy((HistoryInterval historyInterval) => historyInterval.Interval.From).SelectMany((HistoryInterval historyInterval) => historyInterval.History).ToList(); + } + + public void Dispose() + { + ??.Dispose(); + ???.Dispose(); + } + + internal static bool ?(HistoryRequestParameters P_0, List P_1, DateTime P_2, bool P_3) + { + HistoryAggregation aggregation = P_0.Aggregation; + if (!(aggregation is HistoryAggregationTick)) + { + if (!(aggregation is HistoryAggregationTickBars historyAggregationTickBars)) + { + if (!(aggregation is HistoryAggregationTime historyAggregationTime)) + { + if (aggregation is HistoryAggregationTimeStatistics historyAggregationTimeStatistics) + { + return ?(P_0, P_1, P_2, P_3, historyAggregationTimeStatistics.Period); + } + throw new Exception(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??() + P_0.Aggregation.Name); + } + return ?(P_0, P_1, P_2, P_3, historyAggregationTime.Period); + } + if (!P_1.Any()) + { + if (P_3 && (P_2 - P_0.ToTime).TotalSeconds < 60.0) + { + return false; + } + return true; + } + IHistoryItem historyItem = P_1[P_1.Count - 1]; + if (historyItem.TicksLeft <= P_0.ToTime.Ticks && historyItem is HistoryItemBar historyItemBar && historyItemBar.Ticks < historyAggregationTickBars.TicksCount) + { + P_1.Remove(historyItem); + P_0.ToTime = historyItem.TimeLeft; + } + else + { + P_0.ToTime = new DateTime(Math.Max(historyItem.TicksRight, historyItem.TicksLeft + historyAggregationTickBars.TicksCount), DateTimeKind.Utc); + } + return true; + } + TimeSpan timeSpan = TimeSpan.FromSeconds(5.0); + if (P_0.Interval.To < P_2 && P_2 - P_0.Interval.To > timeSpan) + { + return true; + } + if (!P_1.Any()) + { + P_0.Interval = new Interval(P_0.Interval.From, P_0.Interval.To - timeSpan); + return !P_0.Interval.IsReversal; + } + P_0.Interval = new Interval(P_0.Interval.From, P_1.Last().TimeLeft.AddTicks(1L)); + return true; + } + + private static bool ?(HistoryRequestParameters P_0, List P_1, DateTime P_2, bool P_3, Period P_4) + { + if (!P_1.Any()) + { + if (P_0.ToTime.Ticks - P_0.FromTime.Ticks < P_4.Ticks) + { + return false; + } + if (P_3 && (P_2 - P_0.ToTime).TotalSeconds < 60.0) + { + return false; + } + long ticks = P_0.Interval.GetLength().Ticks; + ticks = ticks / P_4.Ticks * P_4.Ticks; + P_0.ToTime = P_0.FromTime.AddTicks(ticks); + return true; + } + IHistoryItem historyItem = P_1[P_1.Count - 1]; + long num = P_4.BasePeriod switch + { + BasePeriod.Month => historyItem.TimeLeft.AddMonths(P_4.PeriodMultiplier).Ticks, + BasePeriod.Year => historyItem.TimeLeft.AddYears(P_4.PeriodMultiplier).Ticks, + _ => historyItem.TicksLeft + P_4.Ticks, + }; + if (historyItem.TicksLeft <= P_0.ToTime.Ticks && num > P_0.ToTime.Ticks + 1) + { + P_1.Remove(historyItem); + P_0.ToTime = historyItem.TimeLeft; + } + else + { + P_0.ToTime = new DateTime(num, DateTimeKind.Utc); + } + return true; + } + + private static int ?(HistoryRequestParameters P_0) + { + HashCode hashCode = default(HashCode); + hashCode.Add(P_0.SymbolId); + hashCode.Add(P_0.Interval); + hashCode.Add(P_0.ForceReload); + hashCode.Add(P_0.Aggregation.Name); + HistoryAggregation aggregation = P_0.Aggregation; + if (!(aggregation is HistoryAggregationTick historyAggregationTick)) + { + if (!(aggregation is HistoryAggregationTickBars historyAggregationTickBars)) + { + if (!(aggregation is HistoryAggregationTime historyAggregationTime)) + { + if (!(aggregation is HistoryAggregationTimeStatistics historyAggregationTimeStatistics)) + { + throw new Exception(P_0.Aggregation.Name + 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + hashCode.Add(historyAggregationTimeStatistics.Period); + } + else + { + hashCode.Add(historyAggregationTime.Period); + hashCode.Add(historyAggregationTime.HistoryType); + } + } + else + { + hashCode.Add(historyAggregationTickBars.TicksCount); + hashCode.Add(historyAggregationTickBars.HistoryType); + } + } + else + { + hashCode.Add(historyAggregationTick.HistoryType); + } + return hashCode.ToHashCode(); + } + + private bool ?(HistoryRequestParameters P_0) + { + if (!P_0.CancellationToken.IsCancellationRequested) + { + return false; + } + int key = ?(P_0); + lock (??) + { + if (!??.TryGetValue(key, out var value)) + { + return true; + } + if (value.Any((? ?2) => !?2.IsCancelled)) + { + return false; + } + ??.Remove(key); + return true; + } + } + } + internal delegate IList ?(HistoryRequestParameters P_0); + internal class ? + { + [CompilerGenerated] + private string ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private ? ??; + + [CompilerGenerated] + private bool ??; + + public string LocalStorageConnectionString + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = text; + } + } + + public int DegreeOfParallelism + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = num; + } + } + + public ? LoadHistoryDelegate + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = ?2; + } + } + + public bool AllowLocalStorage + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = flag; + } + } + } +} +namespace TradingPlatform.BusinessLayer.History.Aggregations +{ + public sealed class HistoryAggregationPowerTradesParameters : ICustomizable, ICloneable, IPowerTradesBaseSettings + { + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private int ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double ??; + + [CompilerGenerated] + private double? ??; + + public double MinTradeVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double MaxTradeVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TotalVolume + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double TimeInterval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double BasisVolumeInterval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int MaxZoneHeight + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int MinZoneHeight + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double DeltaFilter + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double BasisRatioFilter + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public double? CustomTickSize + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + List list = new List + { + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MinTradeVolume) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MaxTradeVolume) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TotalVolume) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), TimeInterval) + { + Minimum = 0.1, + DecimalPlaces = 1, + Increment = 0.1, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BasisVolumeInterval) + { + Minimum = 0.1, + Increment = 0.1, + DecimalPlaces = 1, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), DeltaFilter) + { + Minimum = 0.0, + Maximum = 100.0, + DecimalPlaces = 0, + Increment = 1.0, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), BasisRatioFilter) + { + Minimum = 0.0, + Maximum = 100.0, + DecimalPlaces = 2, + Increment = 0.01, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MaxZoneHeight) + { + Minimum = 1, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }, + new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), MinZoneHeight) + { + Minimum = 0, + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + } + }; + if (CustomTickSize.HasValue) + { + list.Add(new SettingItemDouble(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), CustomTickSize.Value) + { + Text = loc._(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), null, 3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()) + }); + } + return list; + } + set + { + SettingsHolder settingsHolder = new SettingsHolder(value); + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value2) && value2.Value is double minTradeVolume) + { + MinTradeVolume = minTradeVolume; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double maxTradeVolume) + { + MaxTradeVolume = maxTradeVolume; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double totalVolume) + { + TotalVolume = totalVolume; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double timeInterval) + { + TimeInterval = timeInterval; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double basisVolumeInterval) + { + BasisVolumeInterval = basisVolumeInterval; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is int maxZoneHeight) + { + MaxZoneHeight = maxZoneHeight; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is int minZoneHeight) + { + MinZoneHeight = minZoneHeight; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double deltaFilter) + { + DeltaFilter = deltaFilter; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double basisRatioFilter) + { + BasisRatioFilter = basisRatioFilter; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2.Value is double value3 && !value3.IsNanOrDefault()) + { + CustomTickSize = value3; + } + } + } + + public object Clone() + { + return new HistoryAggregationPowerTradesParameters + { + TotalVolume = TotalVolume, + BasisRatioFilter = BasisRatioFilter, + BasisVolumeInterval = BasisVolumeInterval, + DeltaFilter = DeltaFilter, + CustomTickSize = CustomTickSize, + MaxTradeVolume = MaxTradeVolume, + MaxZoneHeight = MaxZoneHeight, + MinZoneHeight = MinZoneHeight, + MinTradeVolume = MinTradeVolume, + TimeInterval = TimeInterval + }; + } + } + public sealed class HistoryAggregationVwapParameters : ICustomizable, ICloneable + { + [CompilerGenerated] + private Period? ??; + + [CompilerGenerated] + private HistoryAggregation ??; + + [CompilerGenerated] + private VwapDataType ??; + + [CompilerGenerated] + private VwapPriceType ??; + + [CompilerGenerated] + private VwapStdCalculationType ??; + + [CompilerGenerated] + private TimeZone? ??; + + public Period? Period + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryAggregation Aggregation + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VwapDataType DataType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VwapPriceType PriceType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public VwapStdCalculationType StdCalculationType + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public TimeZone? TimeZone + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList Settings + { + get + { + List list = new List(); + if (Period.HasValue) + { + list.Add(new SettingItemPeriod(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), Period.Value)); + } + list.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)DataType)); + list.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)PriceType)); + list.Add(new SettingItemInteger(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), (int)StdCalculationType)); + if (Aggregation != null) + { + list.Add(new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), new List + { + new SettingItemString(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Aggregation.Name), + new SettingItemGroup(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), Aggregation.Settings) + })); + } + return list; + } + set + { + SettingsHolder settingsHolder = new SettingsHolder(value); + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), out var value2) && value2.Value is Period value3) + { + Period = value3; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2?.Value is int dataType) + { + DataType = (VwapDataType)dataType; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2?.Value is int priceType) + { + PriceType = (VwapPriceType)priceType; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out value2) && value2?.Value is int stdCalculationType) + { + StdCalculationType = (VwapStdCalculationType)stdCalculationType; + } + if (settingsHolder.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.?(), out value2) && value2?.Value is IList settings && settings.TryGetValue(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value4) && settings.TryGetValue>(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), out var value5)) + { + Aggregation = Core.Instance.HistoryAggregations[value4]; + if (Aggregation != null) + { + Aggregation.Settings = value5; + } + } + } + } + + public HistoryAggregationVwapParameters() + { + } + + public HistoryAggregationVwapParameters(HistoryAggregationVwapParameters original) + { + Period = original.Period; + Aggregation = original.Aggregation?.Clone() as HistoryAggregation; + DataType = original.DataType; + PriceType = original.PriceType; + StdCalculationType = original.StdCalculationType; + TimeZone = original.TimeZone; + } + + public object Clone() + { + return new HistoryAggregationVwapParameters(this); + } + } +} +namespace TradingPlatform.BusinessLayer.History.Storage +{ + public interface IHistoryLocalStorage : ILocalStorage + { + void Save(HistoryInterval interval); + + HistoryInterval Load(HistoryDescription description, Interval interval); + + void Delete(HistoryDescription description, Interval interval); + + HistoryStorageInfo GetInfo(HistoryDescription description, HistoryStorageInfoScope scope); + + List GetAllAvailableHistoryDescriptions(); + + void Vacuum(); + } + [Flags] + public enum HistoryStorageInfoScope + { + StoredIntervals = 1, + ItemsCount = 2, + All = 3 + } + public struct HistoryDescription + { + [CompilerGenerated] + private readonly string ??; + + [CompilerGenerated] + private HistoryAggregation ??; + + public readonly string SymbolId + { + [CompilerGenerated] + get + { + return ??; + } + } + + public HistoryAggregation Aggregation + { + [CompilerGenerated] + readonly get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryDescription(string symbolId, HistoryAggregation aggregation) + { + ?? = symbolId; + Aggregation = aggregation; + } + } + public class HistoryInterval + { + [CompilerGenerated] + private Interval ??; + + [CompilerGenerated] + private HistoryDescription ??; + + [CompilerGenerated] + private IList ??; + + public Interval Interval + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryDescription Description + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public IList History + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + } + public class HistoryStorage : DataStorage, IHistoryStorage + { + [Serializable] + [CompilerGenerated] + private sealed class ? + { + public static readonly ? ?? = new ?(); + + public static Func, bool> ??; + + internal bool ?(Interval P_0) + { + return !P_0.IsEmpty; + } + } + + [CompilerGenerated] + private sealed class ? + { + public HistoryRequestParameters ??; + + public HistoryStorage ??; + + public HistoryDescription ??; + + internal HistoryRequestParameters ?(Interval P_0) + { + if (P_0 == ??.Interval) + { + return ??; + } + return new HistoryRequestParameters(??) + { + FromTime = P_0.From, + ToTime = P_0.To + }; + } + + internal Interval ?(Interval P_0) + { + return P_0.Intersect(??.Interval); + } + + internal HistoryInterval ?(Interval P_0) + { + return ??.??.Load(??, P_0); + } + } + + [CompilerGenerated] + private sealed class ? + { + public HistoryStorage ??; + + public HistoryInterval ??; + + internal void ?() + { + ??.??.Save(??); + } + + internal void ?() + { + ??.??.Save(??); + } + } + + [CompilerGenerated] + private sealed class ? + { + public HistoryStorage ??; + + public HistoryDescription ??; + + public Interval ??; + + internal void ?() + { + ??.??.Delete(??, ??); + } + + internal void ?() + { + ??.??.Delete(??, ??); + } + } + + private readonly IHistoryLocalStorage ??; + + private static readonly Type ??; + + public HistoryStorage(IHistoryLocalStorage storage, string localFilePath) + : base(storage, localFilePath) + { + ?? = storage; + } + + public IList Load(HistoryRequestParameters requestParameters, out List historyParametersForServerRequest) + { + CheckDisposed(); + if (requestParameters == null) + { + throw new ArgumentNullException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + HistoryDescription ?? = requestParameters.ToDescription(); + HistoryStorageInfo info = ??.GetInfo(??, HistoryStorageInfoScope.StoredIntervals); + if (info.StoredIntervals.Count == 0) + { + historyParametersForServerRequest = new List { requestParameters }; + return new List(); + } + historyParametersForServerRequest = (from P_0 in requestParameters.Interval.Subtract(info.StoredIntervals) + select (P_0 == requestParameters.Interval) ? requestParameters : new HistoryRequestParameters(requestParameters) + { + FromTime = P_0.From, + ToTime = P_0.To + }).ToList(); + return (from P_0 in info.StoredIntervals + select P_0.Intersect(requestParameters.Interval) into P_0 + where !P_0.IsEmpty + select ??.Load(??, P_0)).ToList(); + } + + public void Save(HistoryInterval historyInterval, bool wait = false) + { + CheckDisposed(); + if (wait) + { + WaitForAction(delegate + { + ??.Save(historyInterval); + }); + } + else + { + PushAction(delegate + { + ??.Save(historyInterval); + }); + } + } + + public void Delete(HistoryDescription description, Interval interval, bool wait = false) + { + CheckDisposed(); + if (wait) + { + WaitForAction(delegate + { + ??.Delete(description, interval); + }); + } + else + { + PushAction(delegate + { + ??.Delete(description, interval); + }); + } + } + + public HistoryStorageInfo GetInfo(HistoryDescription description, HistoryStorageInfoScope scope) + { + CheckDisposed(); + return ??.GetInfo(description, scope); + } + + public List GetAllAvailableHistoryDescriptions() + { + CheckDisposed(); + return ??.GetAllAvailableHistoryDescriptions(); + } + + internal void ?() + { + ???.Vacuum(); + } + + static HistoryStorage() + { + try + { + ?? = AssemblyLoader.LoadTypes(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??(), typeof(IHistoryLocalStorage), null, SearchOption.AllDirectories)?.FirstOrDefault(); + } + catch + { + } + } + + public static HistoryStorage Create(string connectionString) + { + if (?? == null) + { + throw new InvalidOperationException(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + } + IHistoryLocalStorage obj = Activator.CreateInstance(??) as IHistoryLocalStorage; + if (obj == null) + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 1); + defaultInterpolatedStringHandler.AppendLiteral(3E560F35-EA4B-4F47-8302-BE30F80C1E18.??()); + defaultInterpolatedStringHandler.AppendFormatted(??); + throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); + } + string directoryName = Path.GetDirectoryName(connectionString); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + return new HistoryStorage(obj, connectionString); + } + } + public class HistoryStorageInfo + { + [CompilerGenerated] + private List> ??; + + [CompilerGenerated] + private int ??; + + public List> StoredIntervals + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public int ItemsCount + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public HistoryStorageInfo() + { + StoredIntervals = new List>(); + } + } + public interface IHistoryStorage + { + IList Load(HistoryRequestParameters requestParameters, out List historyParametersForServerRequest); + + void Save(HistoryInterval historyInterval, bool wait = false); + + void Delete(HistoryDescription description, Interval interval, bool wait = false); + + HistoryStorageInfo GetInfo(HistoryDescription description, HistoryStorageInfoScope scope); + } +} +namespace TradingPlatform.BusinessLayer.Chart +{ + public interface IFixLocationDrawing : IDrawing, ICustomizable + { + int[][] ScreenPoints { get; set; } + + bool IsFixed { get; set; } + } + public interface ILineDrawing : IDrawing, ICustomizable + { + Color Color { get; set; } + + LineStyle Style { get; set; } + + int Width { get; set; } + } + public interface IRotationStepDrawing : IDrawing, ICustomizable + { + double[][] Points { get; set; } + } + /// + /// Access to the chart panel + /// + [Published] + public interface IChart + { + /// + /// Chart panel unique ID + /// + string ID { get; } + + /// + /// Collection of chart windows + /// + IChartWindow[] Windows { get; } + + /// + /// Current X scale value - width of the bar in pixels + /// + int BarsWidth { get; } + + /// + /// Provides time zone of current chart. + /// + TimeZone CurrentTimeZone { get; } + + /// + /// Provides account of current chart. + /// + Account Account { get; } + + /// + /// Provides custom sessions of current chart. + /// + ISessionsContainer CurrentSessionContainer { get; } + + /// + /// Current tick size of the chart + /// + double TickSize { get; } + + /// + /// Main window of the chart + /// + IChartWindow MainWindow { get; } + + /// + /// Current right offset value + /// + int RightOffset { get; } + + /// + /// Collection of chart drawingsCollection + /// + IChartDrawingsCollection Drawings { get; } + + /// + /// The MouseDown event occurs when the mouse button is pressed down + /// + event EventHandler MouseDown; + + /// + /// The MouseUp event occurs when the mouse button is released + /// + event EventHandler MouseUp; + + /// + /// The MouseClick event occurs when the mouse button is clicked + /// + event EventHandler MouseClick; + + /// + /// The MouseMove event occurs when the mouse moving over the chart + /// + event EventHandler MouseMove; + + /// + /// The MouseDown event occurs when the user scrolling mouse wheel + /// + event EventHandler MouseWheel; + + /// + /// The MouseDown event occurs when the mouse enter the chart + /// + event EventHandler MouseEnter; + + /// + /// The MouseDown event occurs when the mouse leave the chart + /// + event EventHandler MouseLeave; + + /// + /// The SettingsChanged event occurs when any settings were changed + /// + event EventHandler SettingsChanged; + + /// + /// The AccountChanged event occurs when the account was changed + /// + event EventHandler AccountChanged; + + /// + /// Force chart redraw + /// + void RedrawBuffer(); + } + /// + /// Access to the chart drawingsCollection collection + /// + [Published] + public interface IChartDrawingsCollection + { + /// + /// The Added events occured, when new chart drawing was added to collection + /// + event Action Added; + + /// + /// The Moved events occured, when chart drawing was moved + /// + event Action Moved; + + /// + /// The Removed events occured, when chart drawing was removed from the collection + /// + event Action Removed; + + /// + /// The SelectionChanged events occured, when selected chart drawing was changed + /// + event Action SelectionChanged; + + /// + /// Add chart drawing to the collection + /// + /// + void Add(IDrawing drawing); + + /// + /// Remove specified chart drawing from collection + /// + /// + void Remove(IDrawing drawing); + + /// + /// Get chart drawing by ID + /// + /// + /// + IDrawing FindById(string drawingId); + + /// + /// Get all chart drawingsCollection assigned to specified symbol + /// + /// + List GetAll(Symbol symbol = null); + } + /// + /// Access to the particular window from chart panel + /// + [Published] + public interface IChartWindow + { + /// + /// Client rectangle of the chart window + /// + Rectangle ClientRectangle { get; } + + /// + /// Determines, whether this window is the main window of the chart + /// + bool IsMainWindow { get; } + + /// + /// Chart window number + /// + int WindowNumber { get; } + + /// + /// Special object, allows you to convert values from x/y scale to Time/Price and back + /// + IChartWindowCoordinatesConverter CoordinatesConverter { get; } + + /// + /// + /// + double YScaleFactor { get; } + } + /// + /// Converter between x/y and Time/Price scales + /// + [Published] + public interface IChartWindowCoordinatesConverter + { + /// + /// Get the DateTime value that is corresponding to specified x coordinate + /// + /// + /// + DateTime GetTime(double x); + + /// + /// Get the Price value that is corresponding to specified y coordinate + /// + /// + /// + double GetPrice(double y); + + /// + /// Get the X coordinate that is corresponding to specified DateTime value + /// + /// + /// + double GetChartX(DateTime dt); + + /// + /// Get the Y coordinate that is corresponding to specified price value + /// + /// + /// + double GetChartY(double price); + + /// + /// Get the bar index that is corresponding to specified DateTime value + /// + /// + /// + double GetBarIndex(DateTime dt); + } + /// + /// Access to the chart drawing + /// + [Published] + public interface IDrawing : ICustomizable + { + DrawingType Type { get; } + + /// + /// Determines, the way how chart drawing was created: manually or programmatically + /// + DrawingCreationMode CreationMode { get; } + + /// + /// Determines, the availability of drawing - only current chart or all charts with same symbol + /// + DrawingAvailability Availability { get; } + + /// + /// The unique ID of the chart drawing + /// + string Id { get; } + + /// + /// Determines, whether chart drawing draws above or below the main chart + /// + bool MoveToBackground { get; set; } + + /// + /// Determines, state of the chart drawing: Locked or Unlocked + /// + DrawingState State { get; set; } + + /// + /// Get time and price of the particular point of the chart drawing + /// + (DateTime, double) GetPoint(int pointIndex); + + /// + /// Set time and price value for particular point of the chart drawing + /// + void SetPoint(int pointIndex, DateTime time, double price); + } + [Published] + public enum DrawingState + { + Unlocked, + Locked + } + [Published] + public enum DrawingSelectionState + { + None, + Hovered, + Selected + } + [Published] + public enum DrawingCreationMode + { + Manually, + Programmatically + } + public enum DrawingCreationType + { + ByMouseClick, + ByMouseMove + } + [Published] + public enum DrawingAvailability + { + CurrentChart, + AllChartsWithSameSymbol + } + public enum IndicatorPosition + { + NewSubWindow = -2, + OnBackChart, + OverChart + } + [Obfuscation(ApplyToMembers = true, Exclude = true)] + public enum DrawingType + { + [Description("Trading tool")] + TradingTool = 0, + [Description("Horizontal line")] + HorizontalLine = 1, + [Description("Vertical line")] + VerticalLine = 2, + [Description("Line")] + Line = 3, + [Description("Rectangle")] + Rectangle = 4, + [Description("Triangle")] + Triangle = 5, + [Description("Poligon")] + Polygon = 6, + [Description("Circle")] + Circle = 7, + [Description("Ellipse")] + Ellipse = 8, + [Description("Andrew's pitchfork")] + AndrewsPitchFork = 9, + [Description("Price channel")] + PriceChannel = 10, + [Description("Fibonacci retracement")] + FibonacciRetracement = 11, + [Description("Fibonacci price expansion")] + FibonacciPriceExpansion = 12, + [Description("Fibonacci arc")] + FibonacciArc = 13, + [Description("Fibonacci spiral")] + FibonacciSpiral = 14, + [Description("Fibonacci ellipse")] + FibonacciEllipse = 15, + [Description("Fibonacci fans")] + FibonacciFans = 16, + [Description("Fibonacci phi-channel")] + FibonacciPhiChannel = 17, + [Description("Fibonacci time extension")] + FibonacciTimeExtension = 18, + [Description("Fibonacci time zone")] + FibonacciTimeZone = 19, + [Description("Gann line")] + GannLine = 20, + [Description("Gann fan")] + GannFan = 21, + [Description("Gann grid")] + GannGrid = 22, + [Description("Ruler")] + InfoLine = 23, + [Description("Symbol")] + Symbol = 24, + [Description("Text")] + Text = 25, + [Description("Up arrow")] + UpArrow = 26, + [Description("Down arrow")] + DownArrow = 27, + [Description("Uncpecified")] + Unspecified = 28, + [Description("Label")] + Label = 29, + [Description("Line by angle")] + LineByAngle = 30, + [Description("Regression channel")] + RegressionChanel = 31, + [Description("ABC Pattern")] + ABCPatern = 32, + [Description("Gartley Butterfly")] + ButterflyGartley = 35, + [Description("Custom profile")] + CustomProfile = 36, + [Description("Line arrow")] + LineArrow = 37, + [Description("Head&Shoulders")] + HeadAndShoulders = 38, + [Description("Gann box")] + GannBox = 39, + [Description("Price targets")] + PriceTargets = 40, + [Description("Flag marker")] + FlagMarker = 41, + [Description("Price marker")] + PriceMarker = 42, + [Description("Note")] + NoteMarker = 43, + [Description("Comment")] + Comment = 44, + [Description("Angled line")] + AngledLine = 45, + [Description("Horizontal alert")] + AlertHorizontalLine = 46, + [Description("Elliot triangle wave")] + ElliotTriangleWave = 47, + [Description("Three drives pattern")] + ThreeDrivesPattern = 48, + [Description("Triangle pattern")] + TrianglePattern = 49, + [Description("TPA Strategy")] + TPAStrategy = 50, + [Description("Anchor VWAP")] + CustomVWAP = 51, + [Description("Whale Splash")] + WhaleSplash = 52, + [Description("Fibonacci time expansion")] + FibonacciTimeExpansion = 53, + [Description("Fibonacci price extension")] + FibonacciPriceExtension = 54, + [Description("Minotauro Fibonacci price extension")] + MinotauroFibonacciPriceExtension = 55, + [Description("Minotauro Move Up")] + MinotauroFibonacciRetracementMoveUp = 56, + [Description("Minotauro Move Down")] + MinotauroFibonacciRetracementMoveDown = 57, + [Description("POC line")] + POCLine = 58, + [Description("Week POC line")] + WeekPOCLine = 59, + [Description("VIP Analysis")] + VIPAnalysis = 60, + [Description("Brush")] + Brush = 61, + [Description("Marker")] + Marker = 62, + [Description("Cross line")] + CrossLine = 63, + [Description("Vertical alert")] + AlertVerticalLine = 64, + [Description("Fixed text")] + FixedText = 65 + } + public class ChartEventArgs : EventArgs + { + [CompilerGenerated] + private readonly Account ??; + + public Account Account + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + init + { + ?? = value; + } + } + } + public class ChartMouseNativeEventArgs : NativeMouseEventArgs + { + [CompilerGenerated] + private readonly IChart ??; + + [CompilerGenerated] + private IChartWindow ??; + + [CompilerGenerated] + private bool ??; + + [CompilerGenerated] + private bool ??; + + public IChart Chart + { + [CompilerGenerated] + get + { + return ??; + } + } + + public IChartWindow Window + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + private set + { + ?? = chartWindow; + } + } + + public bool NeedRedraw + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public bool NeedMouseCapture + { + [CompilerGenerated] + get + { + return ??; + } + [CompilerGenerated] + set + { + ?? = value; + } + } + + public ChartMouseNativeEventArgs(IChart chart, IChartWindow window, NativeMouseEventArgs ev) + : base(ev.Button, ev.Clicks, ev.X, ev.Y, ev.Delta) + { + ?? = chart; + Window = window; + NeedRedraw = false; + } + } + public class DrawingEventArgs : EventArgs + { + public IDrawing Drawing; + + public DrawingEventArgs(IDrawing drawing) + { + Drawing = drawing; + } + } + public class DrawingSelectionEventArgs : DrawingEventArgs + { + public DrawingSelectionState SelectionState; + + public DrawingSelectionEventArgs(IDrawing drawing, DrawingSelectionState state) + : base(drawing) + { + SelectionState = state; + } + } + public interface IChartObjectTemplate + { + string Name { get; } + + string Group { get; } + + IList Settings { get; } + } +} +namespace ? +{ + [CompilerGenerated] + internal sealed class ? + { + internal static uint ?(string P_0) + { + uint num = default(uint); + if (P_0 != null) + { + num = 2166136261u; + for (int i = 0; i < P_0.Length; i++) + { + num = (P_0[i] ^ num) * 16777619; + } + } + return num; + } + } +} +namespace {C306A0DD-1657-4827-8B17-3122184442EB} +{ + [StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)] + internal class 3E560F35-EA4B-4F47-8302-BE30F80C1E18 + { + [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 39059)] + private struct 2 + { + } + + internal static 2 3/* Not supported: data(F9 DF C9 DB DA CA DE 83 C7 DB C5 9A 86 87 99 85 EF D5 CB CC CE CF D3 CF C6 D6 D4 91 C4 C2 D8 D0 AA FD E9 E5 FB EA AC F9 FB F3 E5 C0 EA EB EB F2 BA EF EA F8 FA F6 F2 FA D3 FF FC FE E1 B7 C7 D9 AB 87 84 86 99 CF B8 BD A3 8F 8C 8E 91 C7 B7 A9 DA AF 8A 98 97 93 95 93 95 B2 9C 9D 99 80 D4 98 A5 AF A1 AF B7 EF A3 BF A6 A6 B2 80 AA AB AB B2 FA B6 B7 BD B7 B9 A5 FD B3 BE BF A4 B8 A3 95 B9 46 44 5F 09 43 40 48 44 44 5A 00 51 54 4E 47 40 7B 57 54 56 49 1F 51 52 56 5A 56 48 16 43 5D 53 46 4E 5E 4C 42 3D 53 44 51 5C 41 46 41 55 41 42 5B 4F 5D 5D 5F 73 70 72 65 33 60 70 64 63 7D 74 06 4B 0B 05 01 1C 09 4D 12 0C 13 08 12 0E 0B 0B 3B 17 14 16 09 5F 19 05 02 1C 02 05 37 3B 38 3A 1D 14 1E 06 02 1A 01 08 1D 02 0E 00 0A 1E 17 0C 09 04 1E 0B 11 12 03 09 1B 10 1B 0E 1E 1E 07 01 E5 F9 F1 E8 E2 E3 E5 E3 ED ED E5 FE F6 E6 E7 EE FB FC FD F7 91 FE CE C8 DE D6 FE D0 DB D2 D5 D6 E9 E4 FD E7 FA FC F5 E0 E0 EC EC C0 E5 E4 EB F0 F4 EF B8 F8 F0 FB BC EE EB FE F2 FE FA B7 F9 E0 99 9F C8 8B 8B CF 8A 9F 8D 8E C0 92 87 8A 81 C5 99 94 96 97 9B 9C 88 94 9D 9D 9F 83 92 92 86 A1 B3 BB AD 88 AD AC A3 B8 AC B7 E0 A0 A8 A3 E4 AA A8 BF BD AB FE AB A5 AD B7 F3 BD A4 A5 A3 F4 B7 4F 0B 4E 5B 41 42 0C 5E 43 4E 45 01 45 48 4A 4B 5F 58 4C 50 51 51 6C 4F 5B 50 55 0B 16 17 67 5C 70 6E 32 29 34 2F 24 24 22 39 3A 21 4E 6E 77 71 75 69 61 58 79 78 6E 78 75 72 64 78 79 79 59 74 04 0A 0F 0C 1C 55 4C 04 0C 0A 14 08 07 0B 0D 1F 1B 0F 11 16 10 51 52 53 3A 1A 03 05 19 05 0D 25 38 24 2B 2C 3D 3C 23 3F 31 0B 29 32 32 28 36 3C 0A 29 37 3A 3B 2C 2F 32 20 14 35 25 1F 39 32 3A 8A 86 88 CF CF C6 C0 8D D6 CC 80 D3 C3 D3 D6 CC DF CD DD 99 D7 D1 DA D2 92 D2 D2 DE C3 C3 94 D4 ED EC FA EC E9 EE F8 E4 ED ED A0 AC A6 E1 E5 EC F6 BB EC F6 BE FC EE F8 F3 E7 F5 B1 F7 F0 F3 E7 8F 8C 89 9D 87 80 82 CD 8D 81 8A 84 85 93 C4 C8 DA 9A D8 9F 9B 88 DC 89 8B 83 95 82 D6 80 9D 81 A2 EB BC A1 AB EF BF AC AF A6 E0 AF A7 AA A1 8D B3 A8 AC B6 AC A6 9D BA B5 A1 B5 B6 B7 A3 BD BA 44 66 49 47 4F 48 49 5F 18 03 49 4F 4F 53 4D 44 56 52 42 5C 5A 1F 4F 48 51 50 55 42 45 51 41 59 66 72 78 68 7C 6E 61 68 76 66 72 40 61 60 76 60 7D 7A 6C 70 71 71 5F 7C 7C 73 64 31 70 7E 7A 71 4A 0A 0F 0E 1C 0A 0B 0C 16 0C 12 41 11 0E 10 0D 5A 08 08 1C 1D 16 1A 14 17 17 50 1F 17 1A 11 55 1A 79 0D 31 3E 20 22 28 2C 37 29 20 2A 67 09 2A 2C 32 36 3E 7E 1E 2A 38 20 32 37 34 1B 38 22 3C C4 CC 88 C8 D8 CA DE CC C5 C6 D3 F1 C3 D5 CD CA DE 9B D7 DF 9E FA C4 CD DD DD D5 DF C2 DE D5 D9 AA C6 E7 FF E7 E1 EB AD C3 F5 E5 F3 E7 E0 E1 D6 F5 EE EA FA FB EC BC ED E0 FA F3 F4 E5 B7 F2 FA 98 CB A5 A8 AD 8E 80 8E 97 8F 81 95 8F 88 8A C5 8E 82 88 9C B2 96 92 98 93 81 9C 88 D6 A0 91 9C AD A3 BC AC AA EF 81 A2 B4 AA AE A6 E6 86 B2 A0 A8 BA BF BC 8E BA AE B4 BD B7 F0 BE B0 F7 98 82 67 6A 7B 46 5B 5D 4F 48 51 03 50 53 4F 44 41 56 1A 5D 57 4B 1E 73 6B 70 73 60 59 5C 46 5B 51 15 47 64 7E 60 60 68 2C 4C 74 66 72 60 61 62 54 60 68 72 77 7D 3E 70 7A 3D 41 7A 7D 61 7A 72 34 58 05 1D 01 07 09 4F 2D 1B 07 11 01 06 03 34 09 0A 15 0F 10 1C 1A 5F 31 12 04 1A 1E 16 56 36 02 10 38 2A 2F 2C 1E 2A 3E 24 2D 27 60 2E 20 67 17 28 35 34 2C 31 3B 3B 7C 10 3D 25 39 3F 31 77 15 23 CF D9 C9 CE CB FF C5 DB CD D7 80 F1 C9 CE CA D1 9A F6 D7 CF D7 D1 DB 9D F3 C5 D5 C3 D7 D0 D1 E5 EF F9 E1 E6 EA AF E3 EB A2 D3 D0 CC C7 B4 C9 C4 C9 F2 FF F7 FF F3 CF F5 FD E1 E4 B1 DB F8 E2 FC 84 8C C8 A8 98 8A 9E 8C 85 86 C0 B1 83 95 8D 8A 9E B6 91 9D 9A 93 99 DD BF 9C 86 98 98 90 D4 B4 BC AE BA A8 A9 AA EC 9D A7 B1 A9 AE A2 8B AB AB BD FB 95 B6 A8 B6 B2 BA F2 92 A6 B4 A4 B6 B3 B0 0A 7B 4D 5B 47 40 48 6C 4F 4C 55 4F 52 07 4B 43 1A 59 59 4B 4D 1F 4C 5C 41 40 55 55 16 55 51 53 65 79 6D 29 61 7F 69 63 6B 6D 67 21 76 68 77 6C 6E 72 77 77 5C 70 70 71 7B 7D 77 74 64 37 56 74 04 0F 1B 2A 06 0E 02 03 07 0F 13 31 03 15 0D 0A 1E 5B 17 1F 5E 32 3D 5D 14 1C 02 51 13 19 02 10 26 24 38 2C 3D 19 2D 21 37 26 60 2E 20 67 27 2A 34 3D 31 3D 3B 31 3F 38 72 3A 3E 25 33 25 22 34 C6 FF D1 D9 CB 8F C3 CB 82 CE CF D7 CF C9 C3 85 DB CD DD CB DF D8 D9 FE DD DE DD DE D2 DE C0 CC AA C8 E0 E8 E0 E1 E9 E1 A2 CA EE E5 E3 FF CB F6 F9 F2 F4 F5 FF EB F3 EF E1 C3 F5 E3 FF F8 F0 C1 93 9B 8D C9 81 89 CC A0 8D 95 89 8F 81 C7 A5 93 9F 89 99 9E 9B B2 93 99 9B 95 99 94 92 D7 B9 9A BC A2 A6 AE EE 8E BA A8 B0 A2 A7 A4 96 A2 B6 AC B5 BF F8 B6 B8 FF 91 B2 B6 BA B6 B8 B3 B3 F4 98 45 5D 41 47 49 0F 6D 5B 47 51 41 46 43 75 41 42 48 5E 4B 4A 57 50 52 1D 7E 5A 5E 54 66 52 46 5C 65 6F 28 66 68 2F 40 64 6C 66 61 73 26 55 61 62 68 7E 6B 6A 77 70 72 4E 7D 66 62 72 73 64 34 65 18 02 0B 0C 1D 4F 0A 02 10 43 14 09 03 47 16 00 1D 09 1D 0A 0D 16 13 13 52 1F 19 1F 13 27 06 1C 29 2E 68 0A 26 2E 22 23 27 2F 10 24 34 2E 2B 21 7A 34 3E 79 2E 2D 35 3E 37 73 33 39 37 39 3A 30 C6 EA DD DD C1 DD C9 CA D0 C6 D3 D2 CF D1 C1 85 FC D2 D6 D0 CA DA 9C F4 DF C3 C5 DD C5 D2 94 E7 EF F8 F8 E6 E0 FC E9 AD CF EC F6 E8 E8 E0 A4 C4 EC FE EA F8 F9 FA D4 F4 F6 F7 F5 FF C1 FE FA F1 85 9C C8 B9 8B 9D 85 82 86 B0 8F 94 94 84 81 96 DA 8B 8A 90 9D 9A 8F DD 94 9C 82 D1 82 9F 91 D5 8B AD A1 BB A3 AE EC A1 AB AD A5 96 AF A9 A0 AA AD B2 B6 BE FE B9 A9 B3 B1 A7 B9 BE B8 9B B1 B4 59 5F 05 5A 5F 5A 4D 5F 47 50 00 4C 43 53 4C 4A 5E 69 5D 55 5F 4B 55 4B 57 13 63 45 44 52 5A 52 7E 63 28 40 60 6B 69 75 50 50 49 21 76 62 76 6C 75 7F 4B 76 6B 6D 7F 78 61 33 60 63 7F 74 71 66 4A 0D 07 1B 4E 1B 04 08 42 31 33 28 46 0B 0D 0B 1F 36 17 1D 1B 5F 1A 12 00 53 04 19 13 57 26 26 03 6B 24 20 20 2A 1F 20 2D 2C 34 29 2F 29 23 65 2A 3E 2A 30 31 3B 11 3E 15 3A 3E 3D 33 2E 74 11 D3 C5 C9 C4 C7 CC E8 D4 CC C2 CD C8 C5 87 D0 D7 DB D8 D3 D0 D0 D8 9C DB D3 D0 C4 DE C4 E4 DB C0 F8 E8 ED A9 FE FD E5 EE E7 CE EF F7 EF E9 E3 A5 DB ED FD EB FF F8 F9 BD D7 FD E6 F4 FA F8 E4 F0 BF 9B 8A 88 80 8B CC 89 87 95 89 80 92 8E 8B 8B DA 92 96 D9 DB BB 93 8A 9C 91 91 9F 92 D7 90 90 BC A2 A9 BD A7 A0 A2 ED AB AD E0 E4 96 A6 B6 A4 B8 B4 B4 B0 BD FF 8F 9C 80 87 A2 B4 B8 B3 87 A1 4F 5B 08 46 48 0F 5C 4C 50 42 42 4E 4A 4E 47 05 69 7A 6A 19 4D 46 4F 49 57 5E 7D 50 4E 5E 59 40 67 2B 7E 68 62 7A 69 2D 64 6C 72 21 72 6F 61 25 7B 78 7B 7C 72 7A 6E 7C 66 7A 7F 7F 36 71 75 76 1E 04 1A 28 19 0A 1F 02 0F 06 40 2E 15 04 0D 09 16 1A 0C 16 0C 3C 14 1C 1C 17 15 51 3B 18 19 10 24 3F 3D 24 6E 00 3F 2E 2B 2F 2C 20 32 28 36 13 35 37 39 2D 37 33 35 29 2B 09 39 36 0C 36 33 05 CF D9 CB CC C0 DB 8C E9 C7 D5 C9 C0 D2 CE CB CB FB C9 D7 D6 D0 FE EE F2 FD FD 90 E1 D3 C5 DD DA EE D8 FC E8 E0 EB ED FF E6 A3 C4 E4 F0 EE E5 F1 F3 F4 F6 D4 F1 E9 F5 F3 F5 B3 D1 E7 F3 E5 F5 F2 8F CB AB 86 80 99 89 9F 85 86 8E 82 83 C8 A0 8C 8C 9E 8A 9E 9B 91 9F 98 A2 96 82 98 99 93 D4 9A AC EB AE A8 BD BB EC 88 8F 82 90 A4 B4 AE AB A1 FA B4 BE F9 AD B3 B3 AA F2 96 9D 90 86 B2 A6 BC 45 4F 08 46 48 0F 5F 44 45 4D 41 4D 06 62 69 64 71 5A 51 4B 57 1F 6E 58 5E 52 44 58 40 52 14 7C 64 6F 6D 71 4C 60 60 61 6B 6D 67 64 74 27 46 64 74 7F 6B 39 58 73 7D 69 56 76 66 78 77 63 7D 7A 04 39 09 1D 0B 4F 03 0B 42 20 08 00 08 00 01 35 1F 09 11 16 1A 5F 13 1B 52 1E 1F 1C 13 19 00 00 27 06 27 24 2B 21 38 38 2F 13 25 33 2F 28 20 65 3C 34 2A 79 13 30 31 38 3C 27 25 3C 05 38 21 27 C9 CE DB 89 DE DD C5 CE C7 D0 80 C7 C9 D5 84 E8 D5 D6 DD D7 CA CA D1 98 E0 93 FC D0 C4 C5 CD 95 DD E2 E4 E5 E7 EE E1 FE D2 F1 E9 E2 E3 A7 CB F6 F9 F2 F4 F5 FF EB F3 EF C2 F6 E2 F8 F9 F3 B4 FA 8C CB A5 A8 DF BF 89 9F 8B 8C 84 C1 89 81 C4 A8 BB C9 B5 96 88 96 92 9A D2 B2 86 94 84 96 93 90 EA A4 AE E9 81 BC AF A4 AE AF A1 B5 A9 B5 8B AB FA 99 B9 B5 BF B1 BF B8 F2 85 BF BD A3 BA B1 83 45 47 5D 44 4B 7F 43 5E 4B 57 49 57 43 07 72 4A 56 4E 55 5C 1E 76 52 59 57 4B 7D 5E 58 52 4D 15 4C 67 67 7E 2E 46 62 69 67 7B 4D 47 4F 27 54 60 68 72 77 7D 5F 7C 7F 78 7E 76 62 70 62 7E 7B 7B 4A 24 1B 0A 07 03 00 0C 16 0C 12 20 10 02 16 04 1D 1E 58 2D 0C 0A 19 5D 20 12 1E 16 13 27 11 07 23 24 2C 69 21 29 6C 00 2D 35 29 2F 21 67 05 33 3F 29 39 3E 3B 14 3D 28 34 3E 31 3F 76 16 30 34 DA DF C1 DF CB 8F E1 C2 D4 CA CE C6 86 E6 D2 C0 C8 DA DF DC 9D F9 DD CE C6 90 E3 DD D9 C0 E5 C6 FE E2 EB E2 DD F8 E5 E3 E5 A3 C9 EF E2 E2 FC C1 F3 ED F1 FD FB ED C8 EF E7 F6 B0 C2 E2 E5 F1 FB 8D 9F 80 C9 A7 81 88 88 9A A5 89 93 95 93 C4 A8 BB DB 88 9C 8C 96 93 99 A1 96 93 9E 98 93 D4 B8 8B EB B8 AC BC A6 A3 A9 83 B5 A5 B3 A7 A0 A1 E5 9E B2 AA BC BD AB B5 B2 BC B2 BC F1 9F B9 B0 B0 52 60 4D 45 5A 41 49 5F 02 60 48 40 48 49 41 49 6A 5E 4A 50 51 5B 1C 52 54 13 7D 70 16 51 5B 47 2A 40 6D 65 7A 61 69 7F 25 70 20 42 6E 66 6A 6B 7F 77 5B 76 7B 79 7A 74 71 7A 75 7F 62 37 7B 73 4A 08 00 08 00 01 09 01 45 10 40 16 0F 03 10 0D 2A 1E 0A 1A 1B 11 08 1C 15 16 50 21 04 1E 17 10 6A 04 3B 2A 27 23 20 2C 36 2C 32 07 27 34 30 65 1F 16 19 79 0E 3A 2E 34 3D 37 03 3D 39 20 74 10 E7 EA 88 F9 CB DD C5 C2 C6 F0 C9 C6 C8 C6 C8 85 FF F6 F9 99 EE DA CE D4 DD D7 E3 C5 D9 D4 DC D4 F9 FF E1 EA AE DC E0 E2 F5 D0 ED EE E9 F3 EC EC F4 FC DC F6 EB FD F0 F8 B2 E0 FD FE F9 E3 FC FC 84 8C BC 90 9E 8A CC 82 84 C3 93 8C 89 88 90 8D 93 95 9F D9 AD 8B 93 9E 9A 92 83 85 9F 94 A7 81 A5 A8 A0 A8 BD BB A5 AE E2 BB E0 93 A3 AB A5 B1 B3 AD BD F9 8D AB AE B8 BC B4 A4 B9 F6 9E BA B1 4F 53 7A 7A 67 0F 7C 48 50 4A 4F 45 03 6C 04 75 5F 49 51 56 5A 1A 78 1D 62 56 42 58 59 53 7D 56 62 62 65 66 65 7A 58 68 6C 68 61 6F 26 54 61 6B 51 72 72 6C 70 3F 4F 78 7C 40 75 7F 7D 78 61 35 39 1B 09 07 4E 2D 28 04 10 06 03 15 0F 08 0A 04 16 5B 35 16 08 1A 11 18 1C 07 50 38 18 13 11 0D 0B 27 24 20 29 2E 38 22 30 17 39 31 23 67 2B 23 7A 11 39 2E 7E 12 33 2B 3B 3D 37 71 17 21 31 27 CB CC CD FA C1 DA DE CE C7 83 D0 D3 CF C4 C1 85 DC D4 CA 99 F4 DE CB 9D FF DC C6 D8 D8 D0 94 F4 FC EE FA E8 E9 EA DC E8 F0 EA EF E5 A6 E8 E2 A5 D0 FA EF B9 D3 F0 EA F4 FC F4 B0 D0 E0 F2 E6 F4 8D 8E BB 81 87 89 98 CD 8D 85 C0 AB 87 90 C4 A8 95 8D 91 97 99 DF BD 8B 97 81 91 96 93 A3 8D 85 AF EB A7 AF EE 9B A9 A8 B6 AB E0 8C A9 B1 AD AB BD FB 99 AF BB AD BD BA B7 80 BF A4 A4 B4 B1 F5 5A 59 41 4A 4B 0F 4A 42 50 03 74 44 43 53 4C 05 77 54 4E 50 50 58 1C 7C 44 56 42 50 51 52 64 50 78 62 67 6D 2E 60 6A 2D 56 66 65 75 6E 27 49 6A 6C 72 76 7E 3E 5E 6A 78 60 72 77 74 45 7F 7D 73 1E 4B 07 0F 4E 3B 09 08 16 0B 40 2C 09 11 0D 0B 1D 5B 39 0F 1B 0D 1D 1A 17 27 09 01 13 57 1B 13 6A 07 21 39 3D 6F 01 22 34 2A 2E 26 66 06 32 20 28 3A 3F 3C 0D 30 29 2F 31 36 70 21 24 3E 37 30 8A CD C7 DB 8E E3 C5 DD D1 83 ED CE D0 CE CA C2 9A FA CE DC CC DE DB D8 E2 D6 C2 D8 D9 D3 94 DA EC AB C4 E0 FE FC AC C0 ED F5 E9 EF E1 A7 C5 F3 FF E9 F9 FE FB CC F4 F4 F4 E7 B0 FE F0 B7 D8 FC 9A 98 C8 A4 81 99 85 83 85 C3 A1 97 83 95 85 82 9F B3 91 8A 8A 90 8E 94 91 92 9C D1 A0 98 98 94 BE A2 A4 A0 BA B6 9F 99 86 93 A5 B3 AF A8 A0 93 B5 B7 B9 AD B7 B3 B5 A9 AB 83 B5 A3 BF B8 B0 86 45 5E 5A 4A 4B 5C 0C 5D 50 4A 43 44 55 07 42 4A 48 1B 70 6F 7F 53 50 1D 5A 5A 43 45 59 45 4D 7D 63 78 7C 66 7C 76 2C 7D 67 71 69 6E 62 43 6D 76 6A 77 79 60 3E 72 73 79 77 33 3D 31 36 6B 34 56 05 07 07 1B 4E 52 4C 24 0C 07 09 02 07 13 0B 17 37 1A 16 18 19 1A 0E 47 52 1A 1E 18 02 1E 15 19 23 31 29 3D 27 20 22 63 6C 6D 09 2F 22 2E 27 24 2E 34 2A 14 3F 31 3D 3A 37 21 6A 71 3F 39 3D 21 C3 CA C4 C0 D4 CA C8 8D D1 D6 C3 C2 C3 D4 D7 C3 CF D7 D4 C0 D7 D1 D8 D4 D1 D2 C4 DE C4 F9 D5 D8 EF DB E4 E8 ED EA C3 FF E6 E6 F2 D2 F2 F5 E5 F1 FF FC E1 D4 FF F1 FD FA F7 E1 AA B1 FF F9 FD E1 83 8A 84 80 94 8E 98 84 8D 8D CE CF C8 B7 88 84 99 9E B7 8B 9A 9A 8E AE 86 81 91 85 93 90 8D B8 AB A5 A9 AE AB BD F6 ED AB AD A9 B5 AF A6 A8 AC A0 BE BC F9 AD AA BF BE B7 A0 A3 B7 A3 BB B8 AC 6C 4A 41 45 4B 4B 0C 59 4D 03 49 4F 4F 53 4D 44 56 52 42 5C 1E 4C 5F 4F 5B 43 44 11 11 10 48 69 24 6F 64 65 68 7D 63 60 52 62 74 69 72 68 54 64 6E 73 7E 70 72 7A 4F 69 60 72 64 74 71 6E 59 74 04 0A 0F 0C 1C 55 4C 04 0C 0A 14 08 07 0B 0D 1F 1B 0F 11 16 10 51 52 53 21 07 02 10 02 12 13 0C 07 2A 26 28 29 2A 3E 77 62 2A 2E 28 32 2E 25 29 33 21 3D 3D 7E 2C 29 3E 31 36 23 22 30 22 38 39 D3 D8 DC DB CF DB C9 CA DB ED C1 CC C3 D4 D0 D7 DB CF DD DE C7 D6 D2 DB DD 9D C8 DC DA FC D1 CC AA F9 ED F8 FB EA FF F9 AC A3 D2 E4 F7 F2 E1 F6 EE D2 FC B9 A3 BF A7 BD C1 F6 FE F5 FF F9 F3 B5 99 84 9D 9B 8D 8A CC D0 C2 B7 88 84 94 82 C4 8C 89 DB 96 96 DE 8F 9D 8F 97 9D 84 D1 98 96 99 90 AE AE B8 AC A0 AB A9 A3 B6 8A B4 A4 AB B7 A5 B7 BF B5 AC 90 AA BA B1 AE F2 B2 A2 B6 A3 BA B1 BB 5E 0B 45 5C 5D 5B 0C 4E 4D 4D 54 40 4F 49 57 05 5B 4F 18 55 5B 5E 4F 49 12 5C 5E 54 16 52 58 50 67 6E 66 7D 4A 6A 6F 64 6F 62 6C 51 6A 66 67 60 69 4D 79 75 6B 7A 48 6F 73 77 79 7F 71 37 5B 65 0F 19 09 1D 07 00 02 57 42 20 01 0F 05 02 08 45 15 09 1C 1C 0C 0C 52 5D 21 16 1E 15 1F 19 13 55 39 24 3D 3B 2D 2A 6C 70 62 17 32 20 22 2E 2A 22 7A 14 28 3C 2C 3E 28 34 3D 3D 6A 71 15 36 3A 36 CF C7 88 C6 DC CB C9 DF D1 8D 80 EE D4 C3 C1 D7 C9 9B DB D6 CB D1 C8 9D 8F 93 90 E2 D3 D9 D0 DC E4 EC A8 FA E1 FA FE EE E7 A3 BD A1 D2 F5 E5 E1 F3 F5 FF B9 D1 EF F9 EF F3 E7 F9 FE F8 AD B4 D6 8B 85 8B 8C 82 CF 83 9F 86 86 92 92 C8 C7 B7 9C 97 99 97 95 DE C2 DC A9 80 92 94 98 98 90 D4 BA BA AE BA A8 BA A6 A3 A3 F8 E3 83 A0 A8 A4 A1 A9 FA B4 AA BD BB AD AF F3 F2 92 B3 B2 B9 A2 BA A1 0A 16 08 12 0E 6E 4F 4E 4D 56 4E 55 06 1A 04 1E 1A 68 51 5D 5B 1F 01 1D 66 41 51 55 5F 59 53 15 45 7B 6D 7B 6F 7B 65 62 6C 39 20 42 67 69 67 60 76 3B 77 6B 7A 7A 6E 6E 3C 33 43 78 72 72 34 28 4A 50 48 3D 07 02 09 4D 0B 0D 40 07 09 15 07 00 5A 46 58 2D 0C 1E 18 14 1C 14 50 3E 06 12 06 14 3E 22 27 27 74 6F 0F 2C 2C 20 25 2D 66 28 36 21 3F 29 2B 77 7E 0B 35 30 37 73 39 3F 76 31 3B 27 C9 CE 88 94 8E 94 8C E2 D0 C7 C5 D3 86 D3 DD D5 DF 9B 85 99 85 9F F3 CF D6 D6 C2 91 C2 CE C4 D0 AA E9 ED E1 EF F9 E5 E2 F0 A3 BD A1 D2 F5 E5 E1 F3 F5 FF B9 D1 EF F9 EF F3 E7 F9 FE F8 AD B4 D6 8B 85 8B 8C 82 CF 83 9F 86 86 92 92 C8 C7 AB 97 9E 9E 8A D9 8A 86 8C 98 D2 91 95 99 97 81 9D 9A B8 EB F5 E9 8F A3 A0 A2 B5 E3 83 A0 A8 A4 A1 A9 9B B7 B4 96 AE BA B2 92 A0 B7 B5 A3 A5 98 BA 86 53 46 4A 46 42 6E 40 41 4D 54 00 62 47 49 47 40 56 7A 54 55 71 4F 59 53 7D 41 54 54 44 44 7B 5B 4B 68 6B 66 7B 61 78 4C 6E 6F 6F 76 26 44 65 6B 79 7E 74 58 72 73 53 6D 77 7D 5F 63 72 72 66 66 25 05 3B 10 03 0D 03 01 23 0D 04 20 05 04 0B 10 14 0F 2C 0B 1F 1B 15 13 15 53 3F 01 13 05 15 01 23 24 26 73 6E 0C 20 22 31 26 60 31 29 34 2D 31 33 34 36 2A 70 7F 0F 38 3C 37 39 3F 31 77 27 3A DF D9 CB CC 8E 92 8C F9 D0 C2 C4 C8 C8 C0 84 EA CA DE CA D8 CA D6 D3 D3 88 93 F3 DD D9 C4 D1 95 FA E4 FB E0 FA E6 E3 E3 F1 AD A0 D2 FF EA E6 EA F6 BB A5 B9 CA ED FD F9 FB FD F7 B1 D9 E7 F1 E7 8B 9F 81 86 80 D5 CC AE 8E 8C 93 84 C6 97 8B 96 93 8F 91 96 90 8C D2 DD B3 90 93 9E 83 99 80 D5 F7 EB 9C BB AF AB A5 A3 A5 E3 8F B1 A3 B5 A5 B1 B3 B4 B6 E3 FE 9C B0 B2 A1 B6 F0 A1 B9 A4 BD A1 43 44 46 5A 00 0F 7F 44 46 46 00 1C 06 73 56 44 5E 52 56 5E 1E 70 4C 58 40 52 44 58 59 59 0E 15 49 67 67 7A 6B 2F 7C 62 71 6A 74 68 70 62 24 75 75 68 71 6D 77 70 72 6E 3C 33 43 74 78 73 7D 7B 0D 4B 1B 06 1B 1D 0F 08 42 5E 40 35 14 06 00 0C 14 1C 58 36 0E 1A 0E 1C 06 1A 1F 1F 4C 57 37 19 25 38 2D 69 3E 20 3F 24 36 2A 36 24 66 37 2B 36 33 2F 31 36 30 2C 72 7D 01 2A 3D 33 39 3B 74 68 8A FF DA C8 CA C6 C2 CA 82 EC D0 C4 D4 C6 D0 CC D5 D5 82 99 FD D3 D3 CE D7 93 DE D4 D1 D6 C0 DC FC EE A8 F9 E1 FC E5 F9 EB EC EE F2 A8 A7 D7 E0 F4 FF F1 F7 F9 BF EF F2 E7 E1 F3 F4 B6 AA B4 C1 98 8A 8C 80 80 88 CC A2 92 86 92 80 92 8E 8B 8B C0 DB BB 95 91 8C 99 DD 9C 96 97 90 82 9E 82 90 EA BB A7 BA A7 BB A5 A2 AC B0 EE E1 95 BE A9 A7 B5 B7 F8 E4 FE 8B AE BC B6 BA BE B6 F6 98 A4 B0 58 4A 5C 40 41 41 16 0D 70 46 56 44 54 54 41 05 4A 54 4B 50 4A 56 53 53 41 1D 10 62 53 59 50 5C 64 6C 28 7A 61 7A 7E 6E 67 23 3D 21 52 75 65 61 73 75 7F 39 51 6F 79 6F 73 67 79 7E 78 2D 34 47 0F 1D 0D 1B 1D 0A 4C 1D 0D 10 09 15 0F 08 0A 16 54 5B 2B 00 13 1D 13 11 52 4E 50 25 04 16 10 1C 24 2C 68 06 3E 2A 3E 2C 36 2A 2F 2F 7C 67 16 20 2C 3E 2A 2A 3B 7F 2C 32 21 3A 24 38 39 39 27 7B 8A EA CB CA C1 DA C2 D9 82 9E 80 F5 D4 C6 C0 CC D4 DC 98 F6 CE DA CE DC C6 DA DF DF 8C 97 F2 D9 EB FF FC EC E0 A1 AC DE E7 ED E4 E8 E8 E0 A4 F6 F5 EE EA FA FB BF A1 BD C6 E1 F1 F5 FF F9 F3 B5 A5 9B 8D 9B 8F 9B 85 82 8C D9 C0 A7 8A 86 90 91 9F 95 D6 D9 AD 86 91 9F 9D 9F D0 CC D6 B1 98 94 BE BF AD A7 F4 EF A3 BF A6 A6 B2 B2 E6 B0 A1 B7 BF FB B6 B6 AA FF BF BC BC B0 B5 BD BA B2 B0 F5 4B 4D 5C 4C 5C 0F 19 0D 51 46 43 4E 48 43 57 09 1A 5D 57 4B 5D 5A 1C 4D 5D 40 59 45 5F 58 5A 15 69 67 67 7A 67 61 6B 23 56 71 61 65 6F 69 63 25 55 6B 7D 6B 7F 6B 75 72 7C 29 30 53 64 72 75 7E 0F 1D 0D 07 40 4F 3C 02 11 0A 14 08 09 09 44 58 5A 40 58 36 18 19 0F 18 06 53 4D 51 4D 57 35 11 2E 22 3C 20 21 21 2D 21 62 33 21 33 27 2A 21 31 3F 29 2B 79 3D 30 29 33 26 73 6D 71 26 38 27 3C DE C2 C7 C7 ED CE C2 8A D6 83 C6 C8 C8 C3 84 F6 F6 9B D7 CB DA DA CE F2 DC D6 90 C1 D9 C4 DD C1 E3 E4 E6 A9 E0 EA F8 F9 EB ED E7 A1 F2 FE F4 E0 BA E9 FD E8 EB F6 EE F8 F6 C0 E4 FE E6 B7 FB E7 8E 8E 9A C9 9A 96 9C 88 C2 91 85 90 93 8E 96 80 9E B4 88 9C 90 9A 98 DD 82 9C 83 98 82 9E 9B 9B EA B9 AD B8 BB A6 BE A8 A6 97 A9 AC A3 A8 B1 B1 88 BE BE AC AD BA 9F BC BC F4 A4 F1 B0 BE BA B1 0A 4A 46 50 0E 5C 58 42 52 0B 53 08 06 46 4A 41 1A 4F 59 52 5B 17 4F 14 12 5C 42 55 53 45 47 61 78 6A 6C 60 60 68 2C 42 72 66 72 60 72 6E 6B 6B 20 3B 59 7D 74 6A 6F 69 32 40 5C 3E 42 47 3A 35 3A 04 1B 00 1A 06 03 03 42 5E 40 28 08 11 05 09 13 1F 58 0A 0A 10 0C 5D 1E 1C 03 02 56 16 10 1F 3F 38 3C 24 2B 21 38 6D 30 26 33 34 2A 33 0D 2B 2C 3A 34 30 3A 7F 28 3C 39 36 70 21 24 38 32 3C DE 8B C9 CD C4 DA DF D9 CF C6 CE D5 86 D5 C1 D6 CF D7 CC F8 D2 D3 D3 CA 92 FF D9 DF DD 97 FB F6 C5 DF FA E8 EA E6 E2 EA A2 CC F0 E4 F4 E6 F0 EC F5 F5 A2 B9 DF FB F6 E8 E1 E7 B0 E2 E2 F8 E4 B5 86 84 9B 9A C0 CF BC 82 91 8A 94 88 89 89 C4 D8 DA C0 D8 AA 8A 90 8C 8E C8 D3 CB D1 BF 99 9D 81 A3 AA A4 E9 BD BB A3 BD E2 AF AF B2 B5 FD E4 91 A8 BA BC B0 B0 B8 FC 92 A2 B6 A2 B0 A2 BE BB BB 10 0B 69 4D 44 5A 5F 59 02 57 41 4A 43 07 54 57 55 5D 51 4D 10 1F 6C 52 41 5A 44 58 59 59 14 08 2A 30 28 5D 6F 64 69 7E 38 23 3B 21 4F 69 6D 71 73 7A 74 39 6A 7E 77 78 32 63 62 7E 70 7E 60 2F 4A 22 06 0A 01 1D 1E 08 01 17 40 15 07 15 03 00 0E 5B 0C 18 15 1A 5C 0D 00 1A 13 14 31 05 1B 00 3A 1F 3A 28 2A 26 22 2A 0D 33 25 33 27 33 2D 2A 34 7B 23 79 0A 26 2C 38 72 6E 70 7D 76 11 3D 39 DE CE DA DA 8E 92 8C DD C3 D1 C1 CC C3 D3 C1 D7 C9 EF CA D8 DA D6 D2 DA 92 DC C0 D4 C4 D6 C0 DC E5 E5 FB A9 E7 FC AC E1 ED E0 EB E4 E2 D3 F6 E4 FE F2 F6 FE BE F0 EC F8 E0 F2 E4 F8 F9 F9 E7 B5 83 98 C8 85 81 8C 87 88 86 C3 86 8E 94 C7 85 86 99 94 8D 97 8A AA 92 96 9C 9C 87 9F D6 83 86 94 AE A2 A6 AE EE A0 BC A8 B0 A2 B4 A8 A9 A9 B4 A4 A8 BA B5 BC AA BA AE AE 9E BA A3 A5 86 B6 A6 B0 44 5F 08 46 5C 4B 49 5F 02 4C 52 01 56 48 57 4C 4E 52 57 57 1E 56 4F 1D 5C 46 5C 5D 78 58 14 5A 78 6F 6D 7B 2E 7B 75 7D 67 70 20 67 69 75 24 66 76 74 6B 70 70 78 3C 72 60 77 75 63 65 44 6D 78 08 04 04 49 0F 01 08 4D 03 00 03 0E 13 09 10 45 1B 09 1D 59 10 0A 10 11 3D 01 14 14 04 57 1C 14 39 6B 26 26 3A 6F 29 35 2B 30 34 11 29 34 2D 31 33 34 36 79 36 3E 2F 7D 3C 3C 24 71 33 2F 3D 26 DE C6 DB CA C1 DD C0 C4 C0 F7 D2 C0 C2 CE CA C2 EA D7 D9 CD D8 D0 CE D0 9C F1 C5 C2 DF D9 D1 C6 F9 C7 E9 F0 EB FD CE E4 EC E7 E9 EF E1 D5 E1 E1 F3 E9 FD FA EA B1 E4 F0 FE DD F1 FC F3 C5 F1 F1 83 99 8D 8A 9A BF 8D 99 8A A5 81 88 8A C7 90 8A DA 8B 8A 96 9D 9A 8F 8E D2 B1 99 9F 92 9E 9A 92 98 AE AC A0 BC AA AF B9 EC BB AD AD E6 A1 AD A9 BF F1 F6 BD B2 B3 8F A4 A1 A7 B5 BC 95 A2 A7 A1 45 46 66 48 43 4A 60 42 41 48 45 45 68 73 66 68 51 1B 1B 15 0E 11 1F 1E 11 10 13 12 15 14 17 16 29 27 38 27 3E 2C 2C 44 6C 6D 65 73 26 62 7C 66 7F 6B 6C 70 71 71 26 3D 7B 67 75 7C 65 5E 7A 76 05 19 1A 0C 0D 1B 4C 0F 10 02 03 0A 03 13 17 45 0A 1A 0A 18 13 1A 08 18 00 00 5E 51 22 18 00 14 26 6B 2B 28 22 2C 39 21 23 37 25 25 66 36 31 24 34 2F 31 2D 27 7F 74 74 72 37 3F 34 25 77 3A 3A DE 8B C5 C8 DA CC C4 8D CD D1 C4 C4 D4 87 D5 D0 DB D5 CC D0 CA C6 9C 95 9B 9D F9 DF D5 D8 C6 C7 EF E8 FC A9 EC FD ED EE E9 E6 F4 F2 A6 F7 E5 F7 FB F6 FD ED FB ED EF B3 B2 D1 E2 F0 F5 FC F1 E1 CA 9A 9D 88 80 9B 85 99 9B C3 83 80 88 C7 8A 8A 8E DB 9A 9C DE CF D2 8D 93 87 98 BD 93 81 91 99 B9 9F 8D A7 BB A2 EC A0 B7 B0 B4 E1 A4 A2 E4 A4 B4 FB BD B7 AB B2 B9 AF B3 A7 B5 B5 F6 A3 AD A5 4F 7F 5A 48 4A 46 42 4A 71 5A 4D 43 49 4B 43 09 76 54 5F 5E 5B 4D 7F 52 5C 55 59 56 7A 58 53 52 6F 79 46 68 63 6A 2C 30 22 2F 20 4E 73 73 74 70 6E 5D 77 75 7A 7A 6E 4D 73 67 78 31 2B 37 38 35 39 08 07 19 0B 4F 51 4D 2E 0C 07 06 03 15 17 29 15 1C 1F 1C 0C 3E 0C 0D 1E 1A 13 10 02 1E 1B 1B 64 65 14 67 60 13 00 22 25 30 13 24 34 2E 28 2A 3D 37 37 3E 39 3E 3E 31 37 00 24 30 24 23 74 31 CF C7 CD DD C7 C1 CB 8D CD CF C4 81 CA C8 C3 85 DC D2 D4 DC CD 91 92 93 F6 D6 DC D4 C2 DE DA D2 AA ED E1 E7 E7 FC E4 E8 E6 AD CC EE E1 E0 E1 F7 A0 BB DC FC F2 FA E8 F8 B2 FF FF F6 B6 F1 FD F9 8F 98 C6 A6 A3 8A 9F 9E 83 84 85 DB C6 A2 9C 86 9F 8B 8C 90 91 91 C6 DD D1 9B 99 95 92 92 9A D6 89 A4 BA AC 82 A0 AF AC B0 AA BA A4 B4 AB AB A6 BB B7 BD F7 B3 B0 B9 B3 FF 86 83 9D B9 B4 B5 B9 43 51 4D 5B 00 66 42 44 56 66 6E 62 47 53 45 49 55 5C 17 17 4A 4B 74 75 08 5E 5D 59 5E 0D 59 58 2A 7F 7C 41 46 35 61 60 38 70 73 69 6E 3D 69 68 20 68 6B 39 6A 6B 48 74 7F 76 45 65 7F 7B 67 2F 4A 02 06 00 1A 06 0D 01 0B 19 01 15 0F 08 0A 4B 54 55 2C 10 13 1A 29 09 1B 1F 03 4B 56 1E 1A 1C 3E 22 29 25 27 35 29 29 62 30 35 22 25 22 37 36 3C 2E 34 35 27 18 38 2E 21 20 23 6B 30 31 32 21 CE 85 E5 87 D7 D6 C8 C9 8C EE ED 8F DF DE C0 C1 94 F6 F5 97 C7 C6 C5 C4 D6 94 9F 96 FB 90 9B 92 F3 F2 EC ED A9 A0 AB C0 CF A4 AF A6 FF FE E0 E1 BD B4 BF D4 D3 B8 B3 BA EB EA E9 E8 DB B9 F0 BB 93 92 A5 A4 C0 8B 88 C3 9B 9A AD AC C8 83 80 CB 83 82 81 80 B3 D8 D3 DA 96 D4 DF D6 8F 8E B9 B8 ED E4 EF AD AA E8 E3 EA BB BA 8D 8C E1 E8 E3 A1 BE FC F7 FE A7 A6 A5 A4 91 B2 BE F6 A2 F7 A7 B0 5E 0B 5B 59 4B 4C 45 4B 4B 40 00 55 4F 4A 41 7F 55 55 5D 70 50 59 53 1D 42 52 42 50 5B 52 40 50 78 2B 7F 60 7A 67 2C 41 6D 60 61 6D 26 73 7D 75 7F 4F 70 7C 3E 4B 75 70 77 49 7F 7F 73 5E 7A 73 05 4B 01 1A 4E 01 19 01 0E 2F 0F 02 07 0B 31 31 39 5B 50 2C 2A 3C 55 51 52 53 00 03 1F 14 11 55 26 2E 3E 2C 22 3C 1A 02 0E 16 0D 04 07 09 05 09 03 08 11 0A 01 0F 1D 1E 19 12 17 14 1B 02 18 01 E3 F4 E9 FA FD EA F8 F2 F2 E2 E3 EA E7 E0 E1 E6 E8 E2 E8 ED F1 E0 EC FC F1 F8 F1 F6 F3 EE DB C0 F8 AB E4 E0 ED EA E2 FE E7 A3 E4 EE E3 F4 EA A2 EE BB F9 F5 F2 F0 EB BD C4 FC FC E4 FB F2 B4 D4 84 8A 84 90 9D 86 9F B4 8D 96 92 C1 8A 8E 87 80 94 88 9D D9 9F 93 90 92 85 80 D0 9E 98 9B 8D D5 FB EB BF AC AB A4 EC A2 A4 E3 96 AE AA B2 A9 A0 FA 9A B6 B8 B2 A6 AF B4 A1 9A BE A7 B7 BB BD B1 0A 59 4D 5A 5E 40 42 5E 47 03 46 53 49 4A 04 68 55 5F 5D 03 1E 6A 52 56 5C 5C 47 5F 65 4E 59 58 6F 7F 7A 60 6D 2F 4D 6E 76 6A 76 64 55 7E 69 68 7F 6F 6A 70 7D 3F 4C 7C 61 7A 66 74 55 7B 7D 70 04 1F 3B 0C 1C 19 09 1F 20 11 0F 00 02 04 05 16 0E 76 72 35 11 1C 1D 11 52 07 19 1C 13 4D 54 78 40 07 27 2A 2F 23 6C 0E 2E 2C 23 2A 66 08 22 23 29 3E 2C 63 7E 7F 31 2E 5F 59 20 3E 39 3B 7A 3B DE DB 86 C6 DC C8 D8 C4 CF C6 8E D6 CF C9 C0 CA CD C8 96 DA D1 D2 C8 D4 DF D6 9E D6 D9 D8 D3 D9 EF A5 EB E6 E3 FB E5 E0 E7 AD EE E8 F5 F3 AA E2 F5 ED CC F0 F3 FA BC EA F3 E0 B0 E2 EF F9 F7 FD 98 84 86 80 94 8A 88 C3 C2 A0 95 93 94 82 8A 91 DA 94 9E 9F 8D 9A 88 DD DA 9E 83 D8 CC D7 A7 80 B9 BB AD AA BA AA A8 ED AB AD A3 AE B4 B5 A1 A6 AE FB B7 BF B8 AC B9 A9 F2 B5 A2 BE BB F7 A7 B0 58 5D 4D 5B 14 0F 7F 48 4E 46 43 55 43 43 04 4A 58 51 5D 5A 4A 1F 5F 5C 5C 14 44 11 54 52 14 46 6F 79 61 68 62 66 76 68 66 55 61 73 6F 66 66 69 7F 3B 6F 70 6A 77 3C 6E 62 76 73 78 70 7E 71 71 4A 05 09 04 0B 4F 02 02 16 43 05 19 0F 14 10 16 1D 17 17 1B 1F 13 2A 1C 00 1A 11 13 1A 12 07 03 2B 39 21 28 2C 23 29 23 23 2E 25 37 27 2B 31 20 33 28 16 2C 32 33 1B 31 3D 31 31 3D 00 36 26 3C CB C9 C4 CC DD 81 C8 CC D6 F7 D2 D4 C3 F3 CB CA 9A D9 D1 DE 9E D0 DE D7 D7 D0 C4 F3 C3 D1 D2 D0 F8 EE EC D9 FC E0 EF E8 F1 F0 EF F3 D1 EE F0 ED CA E9 F1 F6 EC F6 E8 E4 BC C3 E2 FE F5 F2 E7 E6 A7 8A 86 90 BA 8E 9F 86 91 D9 C0 A0 88 C7 81 97 88 94 8A D9 91 9C 9F 88 80 96 94 CB D6 B5 81 93 AC AE BA AC AA 9F BE A2 A1 A6 B3 B2 A9 B5 93 AC AE B3 88 AB B7 B0 AE B4 A6 AA FE 81 A3 A4 BC EF 0A 6A 46 09 4B 5D 5E 42 50 03 4F 42 45 52 56 40 5E 01 18 70 50 49 5D 51 5B 57 10 41 44 5E 5B 47 63 7F 71 79 62 7A 6B 20 6B 6D 73 2F 28 5B 2A 2B 46 35 36 45 56 76 6F 69 7D 61 69 47 79 7B 61 78 0F 2A 06 08 02 16 1F 04 11 36 13 04 14 33 16 04 1E 1E 0B 3A 1F 1C 14 18 21 16 04 05 1F 19 13 06 19 28 3A 20 3E 3B 3F 1E 21 31 29 31 32 34 00 24 2E 3A 11 37 3A 36 3F 3C 26 3C 22 22 05 23 26 34 DE CE CF C0 CB DC FC C1 C3 C0 C5 EE D4 C3 C1 D7 E9 CF CA D8 CA DA DB D4 D7 C0 E6 D4 D8 D3 DB C7 F9 E9 E1 E7 DA EA E1 FD CF E6 E4 E8 E7 CA E1 F6 E9 FE F6 FE FB ED EF D4 FC E7 F5 E3 E0 F6 F8 AF CA 86 89 91 AA 8A 8B 9F 87 86 AF 87 B6 86 96 84 96 97 9D 95 97 8C 91 BE 9D 9D 9E 94 95 83 9D 9A A4 EB AE A0 A0 A6 BF A5 A7 A7 83 AE A8 A9 A1 A6 AE B2 B7 B7 FE B3 B3 AE A6 9C A2 B5 B3 A5 F4 B6 58 4E 49 5D 4B 4B 03 4E 43 4D 43 44 4A 42 40 0A 48 5E 48 55 5F 5C 59 59 7D 41 54 54 44 17 52 5C 66 67 6D 6D 41 7D 68 68 70 23 72 64 6C 62 67 71 7F 7F 48 76 6D 76 68 74 7D 7D 30 72 7A 78 67 70 0E 2F 0D 0F 0F 1A 00 19 42 02 0C 04 14 13 31 15 1E 1A 0C 1C 5E 3E 0A 1C 1B 1F 11 13 1A 12 17 1A 24 25 2D 2A 3A 26 23 23 04 2A 2E 28 35 2F 21 21 74 2C 39 2F 3D 30 32 33 37 30 24 38 39 39 18 3A D9 DF 86 DE CF D9 E3 DF C6 C6 D2 E2 D4 C2 C5 D1 DF DF 96 CE DF C9 D3 CF D6 D6 C2 F7 DF DB D8 D0 EE A5 FF E8 F8 E0 FE E9 E7 F1 D2 E4 EC E2 E7 F1 FF FF B6 EE FF E9 CC F2 E1 FA E4 F8 F9 F9 D7 F9 85 98 8D 8D C0 98 8D 9B A6 86 86 80 93 8B 90 A4 96 9E 8A 8D D0 88 9D 8B A7 83 94 90 82 92 DA 82 AB BD 93 E6 E5 F2 91 B4 E2 A7 9C A5 9A E7 AC 99 B2 B3 84 B1 82 FF B1 81 BF BE BD 8D EC A4 A7 A6 76 58 4C 09 46 0F 41 0D 51 6F 49 42 43 49 47 40 71 5E 41 6A 4A 5E 4E 49 76 52 44 54 62 5E 57 5E 79 4E 66 6D 4A 6E 78 68 56 6A 63 6A 75 4E 6A 73 7B 77 71 7D 3E 6B 73 76 77 7D 30 65 6F 67 71 2F 4A 29 29 3A 27 2C 33 3D 23 20 2B 20 21 22 29 2C 28 29 37 2B 21 2B 2E 3C 36 3A 3E 36 27 22 35 3B 1E 04 1F 0C 1C 10 00 04 16 06 03 13 1F 17 10 0A 05 12 16 1D 17 1E 03 0D 13 10 1B 10 11 12 04 07 EF E6 E1 FC E3 F0 FC E1 F7 F0 FF F1 E7 E4 EF E4 FD FE E8 F6 E9 FA EE E9 E0 F2 F4 F4 E5 E8 E4 F4 C9 C0 C9 CE CB DF DE C8 CF CA D5 CC D9 D7 C5 C6 D1 DA DF DC D1 CF C8 D4 DD DD C3 CE C6 D6 D7 DE AB AC AD BD BE A0 AF A5 A3 B1 B4 BE B6 A6 A7 AE BB BC BD AD AC BE B8 B4 BC B4 AF A2 BF B0 BA B4 86 94 98 88 8D 84 8D 8A 87 87 8F 8C 95 92 96 83 9B 98 9D 86 8E 9E 9F 96 93 94 95 9E 84 93 91 87 6C 67 67 7E 71 7F 6D 6E 69 62 67 64 72 75 71 60 7E 7A 6C 78 61 69 79 71 7D 70 79 65 6F 74 61 66 5E 44 45 4C 5C 5F 5E 42 52 5C 4C 48 45 42 4A 56 5F 4A 4D 58 50 4B 53 4A 57 41 4F 50 52 41 55 5B 29 2E 2C 36 2B 3E 39 24 36 3A 31 34 27 29 30 2A 2D 3E 2A 26 3F 3B 2A 3C 3C 30 35 35 29 3E 3A 31 03 08 0D 1A 1F 1A 0D 03 16 0C 17 04 14 18 05 01 0C 1A 16 1A 1B 1B 03 1E 1D 1E 1D 1E 12 1E 00 0C FB FE E9 E7 FA E0 FB E8 F0 FC E1 E5 F0 E6 EA E6 FF FF E7 FC EF EA F5 E9 EB EC F3 FE FB FA FB F1 C3 DF C1 CC DD CC C9 C9 D0 CC CD C0 D4 CC C1 D1 DE DA CC D8 C1 CF DD DE D9 D2 D7 D4 D4 F6 E7 FC 89 A8 9A 90 9E 9B 83 CD B2 82 83 8A 87 80 81 A8 8F 97 8C 90 D3 9E 8F 8E 97 87 D0 A1 97 94 9F 94 AD AE 89 AD B8 AE A2 AE A7 A7 E0 87 A3 A6 B0 B0 A8 BE AB 89 AC BA B1 B4 A7 BE F0 81 BA A2 A7 94 46 47 08 40 40 0F 43 43 47 75 4F 4D 53 4A 41 05 7B 55 59 55 47 4C 55 4E 62 5C 47 54 44 17 60 47 6B 6F 6D 7A 4A 40 41 2D 71 76 72 67 67 64 61 4A 68 7F 7D 6B 3E 59 70 72 65 47 40 5E 36 54 7C 74 18 1F 27 19 1A 06 03 03 42 17 12 00 02 0E 0A 02 39 0E 0B 0D 11 12 19 0F 22 01 1F 01 3B 1E 06 07 25 39 68 1D 3C 2E 28 24 2C 24 14 33 27 23 2D 2B 3D 7B 0B 20 2D 2B 39 30 21 02 25 30 38 23 3B 22 CF D9 88 E5 C7 DB C9 FC D7 C2 CE D5 C9 D0 C1 D7 9A FA DC CF DF D1 DF D8 D6 93 9D 91 F3 C6 C1 DC FE F2 DC FB FB EA AC C9 E3 F7 E1 A1 D0 E2 E8 EA F9 F2 EC E0 CF EA FD F3 E6 FC E7 F4 E4 B7 D5 F1 9C 8A 86 8A 8B 8B CC C0 C2 AA 8E 85 8F 84 81 96 DA D3 B1 97 9A 9A 84 DD B4 D5 BF D8 A7 82 95 9B BE A4 BF AC BC EF 8D A9 B4 A2 AE A2 A3 A3 E4 ED 99 B4 B5 B4 B1 BB B5 A9 AB FA 81 A4 B7 B9 A0 BA 5D 4E 5A 09 6F 4B 5A 4C 4C 40 45 45 06 0A 04 60 4B 4E 51 4D 47 1F 1A 1D 71 5C 5D 5C 59 53 5D 41 73 48 6D 6D 7C 60 2C 40 63 71 6B 64 72 27 60 64 6E 7A 5B 78 70 7C 79 71 32 64 71 78 62 37 75 76 09 0E 1B 1A 4E 1B 03 06 07 0D 05 0F 02 14 01 16 09 12 17 17 58 21 5A 1E 1F 17 5F 12 56 04 00 14 38 3F 68 31 2A 28 61 22 32 26 2E 2E 36 22 2A 02 3F 2F 1E 2B 3B 3A 0C 32 20 27 19 3F 04 36 3A 32 CF 87 88 E6 DB DB 8C C2 C4 83 D0 CE D4 D3 D7 D6 CF D9 DD D4 DF D6 D0 D8 DC C7 D9 C5 CF 86 D1 DB FE E2 FC F0 BC A1 AC CE ED ED F6 E4 F4 F3 E1 F7 E9 BB A5 B9 DD F0 F2 F3 F7 F0 E4 F8 F9 F9 DD F1 AD 99 87 9C 9E C2 AE 84 8C 82 8E 82 83 A5 8D 8B 9B 95 9B 9C DE AC 8C 92 86 B1 99 9F 97 99 97 90 EA 9E 9B 8B A7 A1 AD A3 A1 A6 E0 92 B6 A8 B0 E5 8F 88 9A B0 B0 BE B2 BE B7 F3 96 A4 A2 A2 A6 B0 59 69 41 47 4F 41 4F 48 02 76 73 65 72 0A 69 05 7C 4E 4C 4C 4C 5A 4F 15 1F 1A 18 1C 4A 13 1D 15 76 2B 28 75 2E 4C 63 78 6C 77 20 3C 26 27 78 25 4E 74 6C 78 72 3F 70 78 64 76 7C 62 36 2A 34 43 0F 19 1B 00 01 01 3F 08 10 0A 01 0D 0F 1D 01 17 40 5B 1E 18 17 13 5C 09 1D 53 02 14 05 03 1B 07 2F 6B 21 3D 2B 22 62 3E 27 37 34 28 28 20 37 31 33 38 33 2A 1F 0A 18 72 11 12 14 10 03 13 7B 16 E2 ED E9 FC EA 80 E6 FD FB E2 F5 E5 89 ED F4 FC 9A 93 EF FC FB F4 F9 F3 F6 9A F1 E4 F2 98 FC FE CE CA DD CD A1 C1 D6 C9 C3 D6 C4 AE D5 C0 C0 C4 CF DF B7 CC CD DB DD C8 D6 BC C5 C2 D2 B7 BC C2 AF AE A3 AC A0 AB C5 AE A3 A7 CF A2 AE A1 A7 A4 BE D4 B0 B2 BA BC BD B9 DD B9 A0 A8 B5 B6 B0 DA 99 8C 8C 8A 86 89 E3 85 89 87 83 89 80 E8 8E 95 83 98 90 9F F1 85 9D 8F 97 86 82 FE 97 82 90 90 7F 79 07 6A 6F 6B 69 78 70 0C 63 69 60 62 71 77 15 78 62 72 7B 6A 6E 12 76 78 7B 74 63 65 1B 72 48 5B 4D 5C 5C 20 44 46 46 46 55 53 29 4F 51 43 5F 4E 4A 36 54 4F 45 58 47 41 3F 5C 4E 59 51 40 38 44 26 26 25 2A 39 3F 4D 2D 3A 25 23 32 36 4A 2A 37 36 3C 2B 2D 53 2F 3D 3D 35 24 24 58 26 20 08 0E 1D 1B 61 1C 09 06 07 16 12 6E 15 00 00 00 0F 09 77 0D 0C 06 19 08 00 7C 05 02 12 12 01 07 85 FE FB ED 8E 87 FB E8 E7 E8 E5 EF E2 8E E1 F0 E8 94 E2 F8 EC F8 FE ED 9D F2 E5 F5 F1 F5 E4 9A C9 CA CC CE CC DF A3 CE CA C5 C7 C3 D6 A8 C7 DF D1 DC DA C9 B1 DB D7 D6 D5 D1 C0 BE DE DC D0 D2 A8 BB C7 A1 BB A9 AB AF B2 CC AA B1 BF A0 A6 B5 D5 B6 A0 B7 B9 BD AC D2 BC BC BB B6 B4 A7 DB BB 90 8F 8F 8B 9E E0 9C 81 8C 84 82 91 E9 94 81 8E 9D 99 88 F6 8D 98 98 9A 90 83 FF 85 84 8E 93 97 7A 04 7D 7A 6A 68 6E 7D 0D 76 73 65 06 0F 73 60 7F 70 7D 77 7A 16 7B 7F 62 1C 6A 70 64 7F 7F 71 25 41 58 50 40 40 47 22 51 46 4B 4F 5C 43 2B 46 5B 5F 56 43 5A 30 5F 55 54 5D 4A 55 39 5F 5F 51 24 31 2C 46 24 3F 35 23 38 27 4F 32 21 23 2A 3F 3E 54 2D 2A 3A 2C 3B 39 5D 30 38 37 25 30 30 5A 02 00 0C 1A 09 0B 63 07 12 1A 14 13 1F 68 0E 15 03 0E 0B 1D 71 1C 1D 19 07 00 14 7E 15 1F 12 00 F9 EF 87 EA E6 E9 8C 85 F5 E6 E5 EA E3 E9 E0 8C EF E8 FC 96 FD F1 F4 E8 E1 F7 9F F2 EC FC E1 E6 CE A4 CC C2 C5 DA DF C9 AD CB CB C5 D3 D4 C0 AA D3 D5 CA CC CD DB B3 D5 C7 D5 C5 C2 D2 B8 DD D9 B9 BE BB AD C1 A5 BC B4 B7 B0 A4 CE AC B7 BD C5 D2 AC BD BC B5 BA B2 B9 DB A6 A3 B5 D9 BA AC BB 9F 98 8C E6 80 80 87 98 91 87 EF 91 8A 89 91 96 9E F4 8A 96 90 8A 8F 99 FD 81 85 93 83 84 90 FA 79 6A 7A 7C 7D 6B 03 7E 67 68 75 72 62 08 77 62 7E 6E 6B 7D 11 6B 74 7F 67 60 74 1E 62 65 6D 60 59 4F 27 53 4F 5D 56 4C 50 2C 4A 51 5F 40 48 41 35 58 56 51 4D 53 4A 32 51 5D 58 56 59 5B 50 3A 2B 3E 2C 2E 21 23 28 42 21 22 24 26 29 2B 20 4A 39 33 3E 3E 31 33 38 52 37 26 22 36 39 3B 30 5A 0D 09 18 0E 01 03 08 62 0A 08 04 06 09 0B 00 6A 10 0B 01 1E 11 13 18 72 1C 09 14 16 19 1B 10 7A F9 EC EC EE E1 E3 E8 82 F1 EA EC F7 E3 F5 F7 EC F6 ED FD EB 91 FE E9 F9 E1 FA FC E7 F3 E5 9B F6 CB CF DB C0 C2 D9 C9 DF AD C0 C8 C7 D5 CE C8 D3 DF C9 B7 DC CB CD CF D4 DE C5 D5 C3 B9 D0 D6 C5 B9 A2 A4 BF AB BD C3 A5 A9 A7 B3 A8 AA B1 A1 B7 D5 B1 A8 A0 AD B6 B0 AB B7 A1 DF BF AC B3 A7 BC 86 9D 8D 9B E1 9C 8B 89 9A 82 87 EE 87 92 80 9D 9B 9C F7 8C 8D 9B 84 9C 87 FC 91 84 92 8F 95 80 05 6E 7D 7B 76 6E 79 02 77 70 64 79 76 63 0B 70 69 7F 60 69 6A 10 69 6E 76 72 65 62 04 07 04 74 5F 58 5C 5B 4F 43 45 4C 22 31 30 31 45 4F 4D 4B 5B 3B 59 2C 2E 5C 53 4D 42 56 42 54 45 47 27 20 2F 3E 3A 26 3E 2A 4C 58 52 26 35 32 32 3F 51 55 3C 29 39 4D 4E 39 2E 3C 3C 30 35 51 42 47 33 30 18 78 78 0E 0B 1D 01 0C 0C 1A 60 72 76 00 01 17 17 1A 16 00 7E 6C 6C 7D 7A 1E 19 1F 1F 7E 13 10 F8 E6 E9 E7 F7 8F 9F 9D 82 8B F7 E4 E3 EC E1 EB FE 92 F0 F2 F9 8C 8F F5 FD FD F7 91 FD F8 FA F2 AA B8 BB C1 C1 C1 CB AD C9 CC CE C6 A6 B2 B4 CC D4 DF D1 D8 BE AA AC D4 C6 D2 A4 A1 DC C7 DA A7 D8 DE A2 A8 BE AE A2 CD D0 D1 D5 AB A7 B7 A5 AB DA C9 CA CC DE D7 AB B8 B7 B8 B5 BF B2 DE BA B4 99 FA F8 F9 80 8A 88 FF F7 8D 85 95 8E 82 96 89 9B 95 9C 8A FE ED E9 8E 9B 9D 97 90 86 98 86 90 0A 18 18 7A 7E 6E 65 63 02 10 15 72 76 7F 11 15 0A 68 6D 70 0C 0F 6F 6A 77 00 00 62 61 7E 67 66 2A 39 38 5D 4F 46 5B 4C 4C 23 49 4F 42 42 5C 50 51 2A 28 29 4B 54 3C 2C 22 23 45 5A 36 26 24 4C 4A 2C 21 25 3A 3A 3F 5E 52 36 33 41 28 26 37 45 4B 4B 48 2C 2D 5F 2E 28 21 20 50 43 46 47 44 20 19 6B 1B 19 16 6F 79 7D 72 16 13 61 15 17 1C 65 6F 6B 68 79 76 12 15 13 1B 7A 05 02 76 03 11 16 E2 8B 99 99 9E FA FF 8D F6 E6 E3 E9 86 96 94 95 9A 93 F5 F0 F0 F6 95 E8 E1 93 E7 F0 FA FB 94 E6 DE AB BB B9 D9 CE C0 C1 A2 D0 D4 D3 C3 C2 D0 A5 A9 AB CF D8 D2 D3 BC CE C6 C1 D5 D4 C2 B7 A7 A5 CA C3 A5 A0 A0 A6 C5 BE AD BA A6 A3 B4 A2 AA B1 DA B8 AA AC BA BA DC B2 BB BF B3 BE A4 B9 B3 BA 86 8F 8F 86 82 8B EC E5 91 93 8F 95 EF 80 8B 89 9E FB F0 8A 8E 90 88 FD 9F 9A 9E 98 FF 90 9B 99 6E 0B 00 7A 7E 60 78 04 02 0B 77 64 63 6C 61 6B 7E 12 6B 70 72 69 79 6F 61 7A 7C 67 73 65 14 1D 59 5B 47 5D 27 5C 45 41 54 46 52 21 2E 54 54 4A 4E 3B 55 50 50 56 35 53 55 52 43 5F 57 43 41 47 2B 27 48 2E 2F 3C 3C 2C 2E 2F 21 25 2F 32 29 35 36 3A 2C 30 30 2A 31 2E 3D 2A 32 34 37 39 27 26 1F 0C 09 1B 1B 04 6C 0F 10 06 0E 15 66 6F 17 15 15 0F 71 0C 0D 7F 1F 0F 07 17 15 71 7E 04 04 1A FE 82 FD FA 8E EC FE F8 E6 E6 80 89 F5 F7 EB F1 93 9B 90 EE FB FA F7 F8 FC F7 99 E4 E5 97 FA F4 DE DE DA C8 C2 AF CB CC D1 A3 A8 D2 D6 C8 D0 AC CF C8 D7 D0 D2 CA D7 D2 DB DF C7 D4 C5 C3 B4 C1 AF B3 A9 BA CE A0 A5 A1 B5 AB A5 A0 B2 A4 AC AB CF CB C9 C9 AB AC B2 B2 A6 B6 C5 A4 A5 B9 BB A1 8F 89 9D 87 8A 9B 8E 82 8C 87 8A 91 88 85 8B 8B 9E 8E 93 9B 91 91 98 88 81 F3 E1 E1 8F F7 80 F8 64 64 7C 6C 7B 7C 0C 1F 7B 03 74 0C 68 68 70 60 6F 68 18 0C 67 1F 68 10 7C 7C 64 74 63 64 14 61 27 49 47 47 4A 5A 5F 49 4D 4F 4C 40 54 5F 46 51 35 4E 4B 5D 46 5A 48 32 47 40 54 49 54 59 3B 40 39 2F 30 25 2D 40 39 3E 26 3B 32 31 49 32 37 21 3B 0E 0B 0D 0C 1E 10 14 13 1D 50 35 19 1B 18 14 38 6B 3E 3A 60 6F 0F 2C 2C 22 24 28 27 29 64 01 35 37 34 38 2C 1E 29 2E 26 21 31 3D 3F 36 3A 75 EE C4 C4 C5 CF DD 8C DB D1 8D 80 F2 D1 CE D7 D6 9A FD CA D8 D0 DC FD C8 C1 C7 C2 D0 DA DE D5 DB AA CF E7 E5 E2 EE FE AD F4 F0 AE A1 CC E6 F4 E4 F4 FE EB FC BE C6 F9 F3 D3 E6 E3 E5 E4 F6 F8 FC 8B 85 C8 AD 81 83 80 8C 90 C3 96 92 C8 C7 AE 84 8A 9A 96 9C 8D 9A DC A4 97 9D D0 D9 A1 92 91 9E AF A5 AC E0 8F BA BF B9 B0 A2 AC A8 A7 A9 E4 81 B5 B7 B4 B8 AC FF AA AE FC F3 98 BE B8 B0 F4 9E 45 45 4F 09 6A 40 40 41 43 51 61 54 55 53 56 44 56 52 59 57 1E 7B 53 51 5E 52 42 11 40 44 1A 15 44 6E 7F 29 54 6A 6D 61 63 6D 64 21 42 68 68 69 7B 69 59 6C 6D 6B 6E 7C 7E 7A 71 7F 36 53 7B 79 06 0A 1A 49 18 1C 42 4D 31 0A 0E 06 07 17 0B 17 1F 5B 3C 16 12 13 1D 0F 33 06 03 05 04 16 18 1C 2B 25 68 0D 21 23 20 2C 30 63 36 32 68 67 11 16 7A 1F 37 35 32 3E 2E 1C 27 20 24 23 37 3B 3D 34 C4 8B EC C6 C2 C3 CD DF 82 D5 D3 8F 86 F2 F7 85 FE D4 D4 D5 DF CD 9C 95 E5 D6 D5 DA D3 D9 D0 9C C9 EA E6 E8 EA E6 ED E3 A2 C7 EF ED EA E6 F6 A5 EC E8 B6 B9 CD E8 F5 EE E1 B3 D6 E3 F7 F9 F7 D6 8B 85 89 8D 87 8E 82 CD A6 8C 8C 8D 87 95 C4 93 89 D5 D8 B1 91 91 9B DD B9 9C 9E 96 D6 B3 9B 99 A6 AA BA 8A AF A1 AD A9 AB A2 AE E1 82 A8 A8 A9 BB A9 F8 AF AD F1 FC 97 B3 A3 B1 BF B3 A4 B1 F5 73 4E 46 6A 4F 41 4D 49 4B 42 4E 01 62 48 48 49 5B 49 18 4F 4D 11 1C 6E 5B 5D 57 50 46 58 46 50 2A 4F 67 65 62 6E 7E 5E 75 6A 73 72 26 41 76 64 74 78 38 6F 6D 31 3C 55 7D 7D 77 31 5D 78 7A 72 4A 2F 07 05 02 0E 1E 3E 15 0A 13 12 46 21 16 04 14 18 58 0F 0D 51 5C 37 13 03 11 1F 13 04 11 55 13 2E 26 1A 39 26 3F 3E 62 05 32 20 28 24 64 33 29 75 78 0A 31 2A 28 35 72 12 36 23 3F 34 35 3B 8A F9 C9 C7 CA EA D9 DF CD 83 D6 D2 88 87 E5 D0 C9 CF CA D8 D2 D6 DD D3 92 F7 DF DD DA D6 C6 F0 FF F9 E7 A9 F8 FC A2 AD C1 E2 EE E0 E2 EE E5 EB BA DF F7 F5 F2 FE EE D8 E7 E1 FF B1 E0 E4 BA B5 B9 9C 81 9A 9D CF AA 9F 83 8D 83 A4 93 95 8B C5 8C 88 D6 D9 BD 85 99 9E 9A D3 BB 9E 84 82 9A 94 8F BE BA A6 EE B9 BF E3 E2 87 A1 AF AF B4 AC E5 91 A9 B7 B7 BB 9A A9 AF BD F3 A6 A2 F8 F7 96 A7 43 5F 41 5A 46 0F 7C 42 57 4D 44 64 53 55 4B 05 4C 48 16 19 76 50 52 5A 12 78 5F 5F 51 17 70 5A 66 67 69 7B 4B 7A 7E 62 22 75 73 2F 26 4F 71 6B 7D 7A 6A 70 7F 71 3C 5B 7D 61 79 7F 62 52 61 67 05 4B 1E 1A 40 4F 26 0C 12 02 0E 04 15 02 44 3C 1F 15 3D 0C 0C 10 5C 0B 01 5D 50 3C 13 0F 1D 16 2B 25 68 19 2B 3C 23 08 37 31 2F 61 30 34 6A 65 14 34 2A 2E 3B 38 35 3C 3C 73 1B 23 39 39 31 10 DF D9 C7 89 D8 DC 82 8D EC C6 D7 81 FC C2 C5 C9 DB D5 DC 99 FA D0 D0 D1 D3 C1 F5 C4 C4 D8 94 C3 F9 A5 A8 D9 E1 E3 E5 FE EA A3 DA ED E9 F3 FD C0 EF E9 F7 B9 E8 EC B2 BD C0 FC FD F0 F8 FE F5 FB CA A7 8D 9C AB 9A 9E 82 C2 95 93 CF C6 B5 91 96 89 92 99 97 DE AD 89 9F 9E 96 B5 84 84 98 D4 83 B9 E5 E8 9A B9 AA A8 A4 B1 AB E0 8A B4 A8 AA A4 9F AE AA B6 FE A9 AF F3 F2 80 B9 BF B1 B6 A4 BA 58 4E 08 6D 41 43 40 4C 50 66 55 53 49 07 52 56 14 1B 6C 4C 4C 54 55 4E 5A 13 7C 58 44 56 71 40 78 64 28 7F 7D 21 2C 58 51 23 44 6E 6A 6B 65 77 5F 6E 6A 76 3E 69 6F 33 32 46 43 31 52 78 78 79 0B 19 48 41 39 0A 09 06 07 0D 04 48 23 12 16 0A 5A 0D 0B 57 5E 2C 13 08 06 1B 50 30 10 05 1D 16 2B 25 68 1B 2F 21 28 0F 30 2A 34 28 35 2F 64 15 35 2E 36 3D 7E 29 2F 73 72 12 25 22 22 25 35 39 C3 CA C6 89 EA C0 C0 C1 C3 D1 E2 D3 CF D3 CD D6 D2 9B E8 D6 CB D1 D8 9D C4 C0 9E 91 F5 D6 DA D4 EE E2 E9 E7 AE CB E3 E1 EE E2 F2 C3 F4 EE F0 EC E9 F3 B8 C9 F1 EA F2 F9 B2 E5 E3 BF B6 C4 E3 FC 99 98 C8 AF 9C 8E 82 8E A0 91 89 95 8F 94 8C C5 AA 94 8D 97 9A DF 8A 8E DC D3 B3 8B 93 94 9C D5 81 A4 BA BC A0 AE 8E BF AB B7 A9 B2 AE E7 94 AA AF B5 BC F9 A8 AC F2 FD 96 B2 BE B8 A5 BF F4 9E 58 44 46 4C 6C 5D 45 59 4B 50 48 01 76 48 51 4B 5E 1B 4E 4A 10 1F 74 52 5C 54 10 7A 59 59 53 15 4E 64 64 65 6F 7D 4E 7F 6B 77 69 72 6E 27 54 6A 6F 75 7C 39 68 6C 32 3D 5A 66 7E 76 77 65 7D 74 04 4B 2E 06 1C 06 02 19 20 11 09 15 0F 14 0C 45 2A 14 0D 17 1A 5F 0A 0E 5C 53 3A 10 06 16 1A 10 39 2E 68 10 2B 21 0E 3F 2B 37 29 32 2E 67 14 2A 2F 35 3C 79 28 2C 72 7D 1F 36 28 38 35 36 3A 75 FA CE DB C6 EC DD C5 D9 CB D0 C8 81 F6 C8 D1 CB DE 9B CE CA 90 9F F2 D2 C0 C4 D5 D6 DF D6 DA 95 C1 F9 E7 E7 EB CD FE E4 F6 EA F3 E9 A6 D7 EB F0 F4 FF B8 EF ED B1 BC D3 F7 E4 B0 CB F3 F6 F8 F4 84 8F C8 AD 81 83 80 8C 90 A1 92 88 92 8E 97 8D DA AB 97 8C 90 9B DC 8B 81 DD D0 A1 99 9B 9D 86 A2 EB 92 A5 A1 BB B5 8F B0 AA B4 A8 B5 AF E4 95 B5 AE B6 BD FE A9 AF F3 F2 80 A7 B4 B2 BE A7 BD 0A 60 5A 46 40 4E 6E 5F 4B 57 49 52 4E 07 74 4A 4F 55 5C 19 48 4C 12 1D 61 5A 5E 56 57 47 5B 47 6F 2B 4C 66 62 63 6D 7F 40 71 69 75 6F 74 6C 25 4A 74 6D 77 7A 3F 6A 6E 3C 33 44 64 64 7C 7D 66 02 4B 24 00 1C 0E 2E 1F 0B 17 09 12 0E 47 34 0A 0F 15 1C 59 08 0C 52 5D 27 20 50 35 19 1B 18 14 38 09 3A 20 3A 26 3F 25 62 13 2F 34 28 23 64 33 29 75 78 0C 0D 7F 18 32 3E 3F 31 23 76 7F 03 30 CF C0 CD C7 CA 86 EE DF CB D7 C9 D2 CE 87 F4 CA CF D5 DC 99 C8 CC 92 9D E1 DC C5 C5 DE 97 F5 D3 F8 E2 EB E8 E0 AF DE EC EC E7 C8 EE E8 E0 A4 CE F5 F5 FF B9 DA F0 F0 F1 F3 E1 B0 E7 E5 B9 B4 DF 8B 9B 89 87 8B 9C 89 CD BB 86 8E AF 89 95 93 80 9D 92 99 97 DE B4 8E 92 9C 96 D0 87 85 D9 D4 A6 BD AE AC A0 BD A7 EC 86 B0 AC AE A0 88 A2 B3 E5 80 BE B9 B5 BF B1 B8 FD 96 BC BC BD B7 A5 F4 A3 59 05 08 6A 4F 41 4D 49 4B 42 4E 01 62 48 48 49 5B 49 76 5C 49 1F 66 58 53 5F 51 5F 52 17 70 5A 66 67 69 7B 2E 79 7F 23 22 50 77 68 75 74 24 43 68 7A 76 7A 50 7A 6B 3D 48 76 71 7D 77 79 70 35 2E 04 04 05 0F 1D 4C 1B 11 4D 40 29 09 09 03 45 31 14 16 1E 5E 3B 13 11 1E 12 02 3F 13 00 54 2F 2F 2A 24 28 20 2B 6C 09 2D 2F 2C 20 34 67 32 36 74 7B 12 38 2E 3E 32 38 21 36 70 08 33 39 1A 30 DD 8B F2 CC CF C3 CD C3 C6 83 E4 CE CA CB C5 D7 9A CD CB 97 9E EC D5 D3 D5 D2 C0 DE C4 D2 94 F1 E5 E7 E4 E8 FC C1 E9 FA A2 D9 E5 E0 EA E6 EA E1 BA DF F7 F5 F2 FE EE BD E4 E0 BE B1 C3 C4 B4 D1 85 87 84 88 9C BC 85 83 85 82 90 8E 94 82 C4 A1 95 97 94 98 8C DF 8A 8E DC D3 A3 86 9F 84 87 D5 8C B9 A9 A7 AD 9C A5 A3 A5 A2 B0 AE B4 A2 E4 81 B5 B7 B4 B8 AC FF AA AE FC F3 98 BE B8 B0 F4 9E 45 45 4F 09 6A 40 40 41 43 51 73 48 48 40 45 55 55 49 5D 19 7A 50 50 51 53 41 10 47 45 19 14 7F 6B 7B 69 67 6B 7C 69 2D 5B 66 6E 55 73 75 6F 6C 69 73 38 55 77 6D 7D 3D 64 60 3E 31 5C 76 64 74 04 0E 1B 0C 4E 36 09 03 37 30 40 25 09 0B 08 04 08 5B 0E 0A 50 5F 3F 1C 1C 12 14 18 17 19 54 31 25 27 24 28 3C 1A 1F 6D 06 2C 2C 2D 27 35 64 33 29 75 78 0A 29 36 2F 2E 72 15 22 30 38 34 01 06 8A EF C7 C5 C2 CE DE 8D D4 D0 8E 81 F5 D0 CD D6 C9 9B FE CB DF D1 DF 9D 9A E4 D5 D4 DD D2 DA D1 A3 DE DB A9 CA E0 E0 E1 E3 F1 A0 F7 F5 A9 A4 C6 F2 F2 F6 FC ED FA BC C4 E7 F2 FE C4 C5 B7 D0 FA 86 87 89 9B CE 99 9F C3 C2 A0 9A 84 85 8F C4 AE 95 89 8D 97 9F AA AF DD B6 9C 9C 9D 97 85 D4 83 B9 E5 E8 8D AF A1 A5 BE AA E3 8B B3 A9 A9 A1 90 89 FB 9C B6 B2 B3 BD AF F2 A5 A3 FF F6 9F BB BB 4D 0B 63 46 40 48 0C 69 4D 4F 4C 40 54 72 77 05 7E 54 54 55 5F 4D 1C 4B 41 1D 10 78 58 53 5D 54 64 2B 5A 7C 7E 6A 69 58 51 23 44 6E 6A 6B 65 77 3A 6D 6B 37 3E 57 69 73 75 72 62 78 77 79 34 53 05 19 01 07 1A 3A 3F 4D 26 0C 0C 0D 07 15 44 13 09 55 58 30 0D 0D 1D 18 1E 1A 50 3F 13 00 54 26 22 2E 39 2C 22 1A 1F 6D 06 2C 2C 2D 27 35 64 33 29 75 78 13 3F 2F 3D 33 37 20 35 71 0F 32 3A 00 F9 8B EC C6 C2 C3 CD DF 82 D5 D3 8F 86 ED C5 D5 DB D5 DD CA DB 9F E5 D8 DC 93 98 E6 D3 D2 DF D0 E4 EF A1 DC DD AF C8 E2 EE EF E1 F3 A6 F1 F7 AB BA D6 FD E1 F7 FC FD F3 B2 C3 F5 E2 F9 C2 C7 B5 AE 84 84 85 8F 9D CC 9B 91 CD C0 AF 89 95 93 80 9D 92 99 97 DE B4 8E 92 9C 96 A5 A2 D6 B3 9B 99 A6 AA BA E9 B8 BC E2 ED 92 AC AC A8 B5 AF E4 9F B6 B4 AC A0 8B AC FC 99 BD BF BC B0 A4 F7 A2 A6 04 0B 7A 46 43 4E 42 44 43 4D 00 6D 43 52 71 76 1A 7F 57 55 52 5E 4E 1D 44 40 1E 11 64 42 47 46 63 6A 66 29 5C 7A 6E 61 67 56 53 21 42 68 68 69 7B 69 38 6F 6D 31 3C 4E 73 66 74 78 36 56 66 74 08 02 09 07 4E 3D 05 14 03 0F 35 32 46 23 0B 09 16 1A 0A 59 08 0C 52 5D 21 04 15 15 1F 04 1C 55 01 39 27 27 2F 1A 1F 6D 06 2C 2C 2D 27 35 64 33 29 75 78 0A 37 31 3B 3C 22 3C 22 34 76 13 3B 39 C6 CA DA FC FD 8F E8 C2 CE CF C1 D3 86 D1 D7 8B 9A EF D0 D8 D7 9F FE DC DA C7 E5 E2 96 F3 DB D9 E6 EA FA A9 F8 FC A2 AD D6 F6 F2 EA EF F4 EC A5 D6 F2 EA F8 CB CC BC D9 FD FF FC F0 E4 B7 E2 E6 C4 CB BB 86 9B 9B 84 CD A3 85 92 88 85 86 8A C5 A8 9A 96 9D AD 90 89 89 9A D3 B1 97 84 9E 97 94 A4 EB 9A A8 A0 AB EC BB B1 ED E0 8B A7 B7 A5 AB BF A8 BD F9 87 BA B2 9A BD BF B4 F1 A0 A4 FA F5 69 43 41 47 4B 5C 49 0D 7B 56 41 4F 75 4E 48 53 5F 49 18 4F 4D 11 1C 7E 5A 5A 5E 54 45 52 14 6C 7F 6A 66 4E 61 63 68 2D 74 70 2E 21 47 72 77 71 68 7A 74 70 7F 71 3C 59 7D 7F 7C 70 64 50 7B 79 0E 4B 1E 1A 40 4F 2F 0C 0C 02 04 08 07 09 44 21 15 17 14 18 0C 38 13 11 16 53 06 02 58 57 27 02 23 38 3B 69 08 3D 2D 23 21 04 2F 2D 22 67 32 36 74 7B 1D 2C 2C 30 1B 32 3E 37 70 27 25 79 74 17 D8 C2 DC C0 DD C7 8C FD CD D6 CE C5 E1 C8 C8 C1 9A CD CB 97 9E F7 D3 D3 D5 93 FB DE D8 D0 94 F1 E5 E7 E4 E8 FC C8 E3 E1 E6 A3 F6 F2 A8 A7 CE E4 EA FA F6 FC ED FA BC C4 F7 FD D7 FE FA F3 B4 E3 99 C5 C8 A7 8B 98 CC B7 87 82 8C 80 88 83 C4 A1 95 97 94 98 8C B8 93 91 96 D3 86 82 D8 D7 A7 9C A4 AC A9 B9 A1 BD A9 ED 86 AC AC AD A7 B5 83 AA B6 BF F8 AF AD F1 FC 8E BB BF A6 B4 A4 84 BD B9 5C 4E 5A 09 58 5C 02 0D 63 56 53 55 54 46 48 4C 5B 55 18 7D 51 53 50 5C 40 60 59 5D 40 52 46 15 7C 78 26 29 4D 6E 62 6C 66 6A 61 6F 26 43 6B 69 76 7A 6A 4A 77 73 6A 78 60 33 66 62 38 37 52 67 0B 05 0B 3A 07 03 1A 08 10 43 16 12 48 47 21 10 08 14 2B 10 12 09 19 0F 52 05 03 5F 56 27 1B 00 24 2F 1B 20 22 39 29 3F 62 35 33 6F 66 0F 2B 2B 3D 7B 13 36 30 38 7C 19 3D 3F 3C 30 24 04 3D 39 DC CE DA 89 D8 DC 82 8D E8 C2 D0 C0 C8 C2 D7 C0 9A E2 DD D7 ED D6 D0 CB D7 C1 90 C7 C5 99 94 FB EF FC A8 D3 EB EE E0 EC EC E7 A0 C5 E9 EB E8 E4 E8 C8 F1 F5 E8 FA EE BD E4 E0 BE B1 C5 FE FA F2 8B 9B 87 9B 8B CF A8 82 8E 8F 81 93 B5 97 8B 91 DA A8 91 95 88 9A 8E AE 82 9C 84 D1 B1 98 98 91 99 BB A7 BD EE 9F AD A1 AE A2 A4 A8 B3 AA 97 B5 B5 AF F8 89 B2 BE A8 B4 BC A6 BD 82 F0 87 FB 94 79 73 08 40 40 4B 49 55 02 4C 46 01 67 52 57 51 48 5A 54 50 5F 51 1C 51 5B 40 44 54 52 17 47 5D 6B 79 6D 7A 4F 5C 54 2D 51 53 49 21 34 37 34 25 5F 6A 6D 70 6A 66 3C 54 7C 77 75 69 36 54 52 51 4A 28 07 07 1A 1D 0D 0E 16 20 08 08 08 06 44 24 4F 4B 58 10 10 1B 19 05 52 1C 16 51 35 1F 1D 1B 2F 38 2D 69 22 26 3F 39 27 27 60 32 2E 26 36 20 29 18 37 29 2E 3A 2E 7D 1B 3D 34 34 2E 1E 16 10 F2 8B 9B 9C 8E C6 C2 C9 C7 DB 80 CE C0 87 F7 D5 DB D5 D1 CA D6 9F D0 D4 C1 C7 D5 D5 96 C4 DC D4 F8 EE FB DA DA C0 D4 D5 B7 B3 C5 A1 C3 F6 F1 EC EE E2 B8 D0 F0 FB F9 E5 B2 D0 D6 D5 B6 D4 FB FB 9E 99 89 8A 9A AA 99 9F 8D C3 B3 95 89 9F 9C C5 CF CB D8 90 90 9B 99 85 D2 9C 96 D1 B3 82 86 9A BA AE A9 A7 EE A3 A5 BE B6 A6 A4 E1 B5 AF A5 B7 BF A8 9B 98 9D FF E8 ED F2 BA BE B5 B3 AF F4 BA 4C 0B 6E 5B 4B 41 4F 45 02 4F 49 52 52 42 40 05 49 53 59 4B 5B 4C 7F 7C 71 13 04 01 16 72 45 40 63 7F 71 29 47 61 68 68 7A 23 43 47 42 27 47 6A 74 6F 6A 78 7D 6B 58 5C 4A 33 79 7F 72 72 6C 35 05 0D 48 2E 0B 1D 01 0C 0C 43 0C 08 15 13 01 01 5A 08 10 18 0C 1A 0F 39 33 2B 50 42 46 57 31 04 3F 22 3C 30 6E 06 22 29 27 3B 60 02 00 03 64 06 35 35 2C 2B 3F 3C 28 19 13 0B 70 62 66 77 11 24 DF C2 DC D0 8E E6 C2 C9 C7 DB 80 EC CF C9 CD 85 F9 FD FC 99 FD D0 D2 C9 C0 D2 D3 C5 F2 F6 EC 95 B9 BB A8 CC FF FA E5 F9 FB A3 C9 EF E2 E2 FC A5 D9 DD DC B9 DD F0 F2 E9 E0 F2 F3 E5 B6 BF C3 F0 8F 80 8D 87 8A C6 A4 8C 8C 84 C0 B2 83 89 83 C5 93 95 9C 9C 86 DF 93 9B D2 BB 9F 9F 91 D7 BF 9A A4 AC E8 A5 A7 BC B8 A8 A6 E3 B3 A9 A7 B5 A1 B6 92 BA B6 BE FE 8C B9 B3 B5 F3 B9 BF B2 B2 AC F5 45 4D 08 61 41 41 4B 0D 69 4C 4E 46 06 4B 4D 56 4E 5E 5C 19 4D 57 5D 4F 57 40 10 72 70 73 7C 54 64 6C 28 5A 6B 61 6B 2D 47 72 75 68 72 7E 24 4C 74 7F 7D 61 3E 5C 5A 59 32 50 7F 7F 62 65 75 76 1E 22 06 0D 07 0E 4C 58 52 43 09 0F 02 02 1C 45 15 1D 58 30 10 1B 15 1C 1C 53 1C 18 05 03 11 11 6A 38 20 28 3C 2A 3F 0B 16 10 05 61 0B 0E 06 65 33 35 3C 3C 26 7F 33 3B 72 1A 24 30 3A 3E 35 3B 8A C7 C1 DA DA CA C8 8D D1 CB C1 D3 C3 D4 EA CC D1 D0 DD D0 9E 8D 8E 88 92 DA DE D5 D3 CF 94 DA EC AB C2 E8 FE EE E2 E8 F1 E6 A0 ED EF F4 F0 E0 FE BB EB F1 FF ED F9 EE DC FA FB FA F3 FE B4 A7 D8 DE C8 AC 9F 9A 85 99 9B C3 A9 8F 82 82 9C C5 B9 BD BC D9 BD 90 92 89 80 92 93 85 B8 9E 9F 9E AF A2 E8 FB FC FA EC 88 B3 B6 A9 B5 BF E7 8D AB BE BE A0 F9 9D 99 98 FD 91 BC BE A5 A4 B6 B7 A1 0A 03 7F 4C 4B 44 49 43 46 0A 74 64 65 6F 04 14 0A 0B 18 50 50 5B 59 45 12 5C 56 11 63 64 14 59 63 78 7C 6C 6A 2F 7F 65 63 71 65 72 48 62 60 60 68 77 79 77 7A 3F 2E 28 32 50 71 62 7E 37 5D 7B 0E 0E 10 28 2B 37 4C 04 0C 07 05 19 46 08 02 45 32 14 14 15 1F 11 18 5A 01 53 1C 18 05 03 11 11 6A 38 20 28 3C 2A 3F 6D 01 05 04 08 28 23 21 3D 7A 34 3E 79 2A 30 2C 7D 01 14 08 71 25 3F 35 27 CF D8 88 EA E8 EB E5 EF E7 FB 80 92 93 87 E1 D4 CF D2 CC C0 9E F6 D2 D9 D7 CB 90 F2 F0 F3 94 F6 E5 E5 FC FB EF EC F8 DE A4 D3 A0 B4 B6 B7 A4 EC F4 FF FD E1 BE F0 FA BD C7 C0 B0 FD FF E4 E0 F0 8E CB 9B 81 8F 9D 89 9E B1 94 89 92 95 C7 A9 84 88 90 9D 8D DE B6 92 99 97 8B D0 9E 90 D7 A7 82 A3 B8 BB E9 A2 A6 BF B9 A7 A7 E0 B2 AE A6 B6 A0 A9 94 95 81 FE 8C A8 B2 B1 B8 B8 BE BA BA F4 E6 1A 0B 61 47 4A 4A 54 7E 6F 6A 00 67 53 53 51 57 5F 48 18 7A 78 7B 68 5C 5B 44 51 5F 16 5E 5A 51 6F 73 28 66 68 2F 58 6C 6B 74 61 6F 63 74 61 25 76 72 6B 6D 7B 7B 3C 6E 7A 72 62 74 65 51 40 46 2F 4B 59 59 5E 4F 05 03 06 06 18 41 09 01 44 30 31 5B 14 10 0D 0B 19 19 52 00 18 10 04 12 07 33 1E 18 0D 69 7F 7F 7C 6D 07 32 35 28 32 3E 64 0C 34 3F 3D 21 7E 1C 1A 19 72 10 3F 3F 22 25 35 36 DE E7 C7 C7 C9 8F EB C4 CE D7 80 E7 D3 D3 D1 D7 DF C8 98 FA F8 FB F5 D3 D6 D6 C8 91 D9 D1 94 C1 E5 FB A8 BA BE AF FF E5 E3 F1 E5 F2 A6 E8 EA A5 CD FA F4 F5 BE CC E8 EF F7 F6 E4 DF D7 C4 D0 D4 BB CB D9 D9 DE CF 85 83 86 86 98 C1 89 81 C4 B0 A9 DB 94 90 8D 8B 99 99 D2 80 98 90 84 92 87 D5 89 8D 8C 9B BB BC BF A8 AE AF E0 F3 F6 F7 F4 E5 93 B5 BC BC A6 FF 91 B4 BC BA F0 97 A3 A3 A1 A7 4F 58 08 6A 68 6B 7F 0B 72 03 15 11 16 07 61 54 4F 52 4C 40 1E 76 52 59 57 4B 10 72 70 73 14 76 65 65 7C 7B 6F 6C 78 5E 24 53 20 34 36 37 24 40 6B 6E 71 6D 67 3F 55 73 76 76 68 31 5B 7E 7A 7C 4A 28 2E 2D 4E 2C 03 03 16 11 01 02 12 29 05 16 1E 1A 09 59 4F 4F 4C 5D 37 02 05 18 02 0E 54 3C 24 2F 2D 31 6E 0C 0A 09 62 00 2F 2F 32 35 25 26 2E 15 39 2A 3A 3E 2D 7D 63 63 60 71 13 26 21 3C DE D2 88 E0 C0 CB C9 D5 82 EE C9 CF CF 87 E7 E3 FE 9B FB D6 D0 CB CE DC D1 C7 F9 DF D2 D2 CC 95 E5 ED A8 FD E6 EA AC F9 ED F3 A0 F2 EE E6 F6 E0 E9 BB F7 F7 BE C8 FD F1 FE B3 C3 E5 E4 F2 F1 E1 CA A8 AE AD AA 80 9B CD A8 8C 8E 84 95 C7 D7 D5 DA BE 89 8C 97 8B 85 DD BB 9D 94 94 8E D7 B7 B3 8E EB 8B A6 A0 BB BE AC A1 B7 84 AE B1 E7 8E AA B4 BE AB F9 ED EF FC 98 A3 A6 B9 A5 AF F7 9D BB 4E 4E 50 09 63 46 42 44 02 60 66 65 06 64 4B 4B 4E 49 59 5A 4A 6C 53 44 50 56 51 5F 75 45 41 51 6F 2B 47 60 62 2F 24 4F 70 66 6E 75 2F 44 6B 77 74 3B 7E 6C 6A 6A 6E 78 61 33 53 57 52 50 7B 79 0E 4B 3B 19 01 1B 2B 02 0E 07 40 32 16 08 10 45 3C 23 58 3A 11 11 08 0F 13 10 04 36 19 1B 10 55 19 3B 27 3D 6E 02 25 23 2B 63 06 19 66 04 2B 2B 2E 29 39 3A 2A 18 33 31 36 73 03 21 39 23 74 13 F2 8B EB C6 C0 DB DE CC C1 D7 80 89 F1 C2 C1 CE DF D5 DC 90 ED D6 D0 CB D7 C1 90 E2 C6 D8 C0 E6 E3 E7 FE EC FC AF DF FD ED F7 A0 C7 DE A7 C7 EA F4 EF EA F8 FD EB CF F4 FE E5 F5 E3 B6 C4 E4 FA 9E CB A5 80 80 86 CC AB BA C3 A3 8E 88 93 96 84 99 8F AB 89 91 8B DC B3 93 87 85 83 97 9B D4 B2 AB B8 86 A8 BA BA BE AC AE E3 87 A0 B5 E7 A2 B0 AE AE AA BC AD FF 9F 9B 96 83 B1 BD BA B6 B0 BC 5F 46 08 5F 5D 01 0C 78 71 03 64 4E 4A 4B 45 57 6A 57 59 4D 57 51 49 50 12 45 43 1F 16 62 67 15 4E 64 64 65 6F 7D 5F 62 7B 61 65 60 68 74 24 63 6F 6F 6D 6B 7B 6C 3C 5E 54 57 43 64 71 76 66 35 0C 1E 1C 1C 1C 0A 1F 4D 21 25 24 34 2D 47 26 17 1F 15 0C 59 2D 0F 13 09 52 35 28 51 35 18 1A 01 38 2A 2B 3D 1B 1C 6C 0E 30 36 24 24 66 14 34 2A 2E 7B 1E 01 7E 1C 33 33 26 21 31 32 22 02 07 75 E9 D9 DD CD CB 8F FF DD CD D7 80 E7 FE 87 E7 CA D4 CF CA D8 DD CB 9C 95 E5 D6 D5 DA D3 D9 D0 9C DF D8 A8 C7 EF FB F9 FF E3 EF A0 C6 E7 F4 A4 D6 EA F4 EC B9 D8 C7 BC DE FD FD E4 E3 F7 F4 E0 C6 9A 84 9C C9 BB BC CC AE 90 96 84 84 C6 A8 8D 89 A9 8B 97 8D DE AA B7 DD B1 81 85 95 93 D7 BB 9C A6 88 BA BC AA AA EC 82 AB AF E0 E9 91 93 8D EC 8D B3 BD B8 AA FF BA A8 A6 A6 A2 B4 A5 F7 97 93 6E 68 40 40 40 4E 0C 6C 17 13 00 68 48 43 41 5D 6F 68 18 08 0E 1F 65 58 53 41 43 11 62 45 51 54 79 7E 7A 70 2E 41 63 79 67 56 53 21 33 27 5D 60 7B 69 6B 39 4A 6D 79 7C 61 66 62 68 36 59 7B 61 0F 2E 1D 1B 01 4F 2E 18 0C 07 35 32 46 54 54 45 23 1E 19 0B 0D 5F 28 0F 17 12 03 04 04 0E 54 37 25 25 2C 3A 04 2E 3C 2C 2C 63 14 33 23 26 37 30 28 22 78 17 31 2B 39 08 19 73 04 23 33 36 27 20 D8 D2 88 E7 C1 DB C9 F9 C7 CD 8D D8 C3 C6 D6 85 EF 95 EB 97 9E EB CE D8 D3 C0 C5 C3 CF 97 FA DA FE EE A8 CA C8 CB D8 FA ED AE F9 E4 E7 F5 A4 D0 B4 C8 B6 B9 CA ED F9 FC E1 E6 E2 E8 B6 D9 FB E1 8F CB AB AF AA A9 85 9B 87 CE 99 84 87 95 C4 B0 D4 A8 D6 D9 AA 8D 99 9C 81 86 82 88 D6 B9 9B 81 AF EB 8B 8F 8A 9A E2 9E EC E3 94 B3 A3 A6 B7 B0 A8 A2 F8 9B B1 B1 B8 FD 91 95 94 84 85 F7 90 BA 46 47 49 5B 0E 66 42 49 47 5B 62 48 52 44 4B 4C 54 1B 4E 4A 1E 6A 6F 1D 76 5C 5C 5D 57 45 71 41 62 6E 7A 6C 7B 62 2C 7B 71 23 55 52 26 43 6B 69 76 7A 6A 5B 77 6B 72 72 66 76 30 67 65 37 41 46 4A 2F 07 05 02 0E 1E 21 07 15 09 00 14 47 12 16 5A 2E 2B 59 3A 10 10 11 13 01 22 18 06 07 18 10 6A 6B 3E 3A 6E 1A 1F 6D 06 2C 2C 2D 27 35 6A 65 1F 29 2A 36 2C 7F 2B 35 3B 3F 35 71 26 3E 3A 32 C3 C5 CF 89 C6 C0 DF D9 98 83 F6 C4 C8 C3 CB D7 F7 DA D6 D8 D9 DA CE 87 92 DA DE D8 C2 DE D5 D9 E3 F1 E9 FD E7 E0 E2 A3 AC AD D6 E4 E8 E3 EB F7 CC FE F6 FD F1 ED D1 FC FC F2 F7 F4 E4 AD B4 F3 8B 82 84 C9 9A 80 CC 81 8D 82 84 C1 B0 82 8A 81 95 89 D8 8D 87 8F 99 D3 D2 BA 9E 98 82 9E 95 99 A3 B1 A9 BD A7 A0 A2 ED B1 A8 A9 B1 B6 A2 A0 EB 8C BE B6 BD B1 AD 91 BC BC B2 B7 B4 A4 ED F4 F5 5C 4E 46 4D 41 5D 0C 44 56 46 4D 52 06 50 45 56 1A 5D 57 4C 50 5B 7B 58 46 65 55 5F 52 58 46 78 6F 7F 69 4D 6F 7B 6D 5B 67 6D 64 6E 74 4A 65 6B 7B 7C 7D 6B 24 3F 6A 78 7C 77 7F 63 36 7A 71 61 0B 0F 09 1D 0F 4F 05 1E 42 0D 0F 15 46 04 0B 17 08 1E 1B 0D 50 5F 28 04 02 16 50 4C 56 21 11 1B 2E 24 3A 04 2F 21 2D 2A 27 31 7A 61 30 22 2A 21 35 29 78 30 2D 7F 3D 31 20 36 31 35 2F 77 35 31 CE CE CC 89 DA C0 8C CE C3 C0 C8 C4 88 87 EA C4 D7 DE 98 84 9E 9F CA D8 DC D7 DF C3 96 C0 D5 C6 AA E2 E6 E0 FA E6 ED E1 EB F9 E5 E5 A6 F4 F1 E6 F9 FE EB EA F8 EA F0 F1 EB B3 BD B1 F0 F6 FD F9 CA 9F 87 C9 9C 8A 98 9F 8B 86 96 84 C6 8E 8A 83 95 DB 99 9B 91 8A 88 DD 84 96 9E 95 99 85 A2 90 A4 AF A7 BB 83 AE A2 AC A5 A6 B2 FB E6 AE AA AC AE B2 B9 B5 B7 A5 B9 B9 F2 A0 A5 B2 B5 B2 A7 A6 4C 5E 44 45 57 63 45 40 4B 57 70 44 54 4E 4B 41 1A 06 18 15 1E 69 5D 51 47 56 10 0C 16 1B 14 7C 64 7F 6D 7B 78 6E 60 2D 3F 23 2C 21 54 62 75 70 7F 68 6C 4D 67 6F 79 6E 32 2E 30 59 7F 64 60 7A 18 12 48 1B 0B 1E 19 08 11 17 40 3A 0F 03 59 38 40 5B 2A 1C 0A 0D 15 18 04 1A 1E 16 56 13 15 01 2B 6B 2E 3B 21 22 6C 2E 23 20 28 24 68 69 6A 18 60 7B 0A 3C 2A 2D 35 38 24 3A 3E 36 76 33 35 21 CB 8B CE DB C1 C2 8C CE C3 C0 C8 C4 86 C1 CD CB D3 C8 D0 DC DA 91 9C E6 FB C7 D5 DC C5 97 D7 DA FF E5 FC B3 AE D2 D1 B7 A2 CF EF E0 E2 EE EA E2 BA FF F9 ED FF BF FA EF FD FE B0 E2 F3 E5 E2 F0 98 C5 C6 C7 B3 D5 CC A1 8D 82 84 88 88 80 C4 81 9B 8F 99 D9 98 8D 93 90 D2 80 95 83 80 92 86 D5 AC A2 A6 A0 BD A7 A9 A9 EC E3 9B 88 B2 A2 A9 B6 FA B8 B7 AC B0 AB E6 FD 87 BD A3 A4 A6 A7 BB A7 5E 4E 4C 09 4F 48 4B 5F 47 44 41 55 4F 48 4A 1F 1A 1B 59 5E 59 4D 59 5A 53 47 59 5E 58 17 5A 5A 7E 2B 7B 7C 7E 7F 63 7F 76 66 64 45 35 46 30 30 2C 58 2A 2E 29 5C 28 5E 23 22 23 26 21 25 26 50 5C 5D 2A 5A 5C 5B 29 2E 57 21 57 59 22 21 26 27 3B 4D 4A 4C 4E 4F 48 49 30 46 40 40 37 40 4C 44 0B 08 0D 08 7C 0E 79 7E 72 77 01 07 71 77 02 7D 69 6C 6A 6F 6E 1D 6B 6A 67 12 68 1C 37 3E 3A 11 CF CD C9 DC C2 DB FF C8 D1 D0 C9 CE C8 D4 E7 CA D4 CF D9 D0 D0 DA CE F0 D7 C0 C3 D0 D1 D2 F5 C6 F9 EE FC C0 EA C8 FE E2 F7 F3 C9 EF E0 E8 D7 EA E8 EF D1 F7 FA FA E4 D3 F3 FE F5 DA F3 EE C0 FA 85 87 BC 80 9E A4 89 94 A6 82 94 80 B2 9E 94 80 BC 94 8A 94 9F 8B 95 93 95 A7 89 81 93 B4 81 86 BE A4 A5 88 BD BC A9 B9 8B 87 96 A8 B5 AE A6 A9 BF 92 AB 95 B7 B1 B7 94 B6 F3 ED F1 FA F7 93 A7 45 5E 58 09 13 0F 00 0D 74 4A 53 48 44 4B 41 05 07 1B 14 19 76 56 58 59 57 5D 10 0C 16 60 55 5C 7E 62 66 6E 2E 69 63 7F 22 70 74 60 74 73 24 71 73 76 7D 5A 71 73 70 78 71 67 30 78 62 72 79 66 4A 1F 07 49 0C 1A 0A 0B 07 11 40 32 07 11 01 01 5A 5B 11 0D 1B 12 0F 53 0A 20 09 1C 14 18 18 36 25 2E 2E 2F 27 2C 25 28 2C 37 14 33 27 23 21 17 3B 2F 31 36 0F 2A 3D 33 26 3A 24 28 04 3E 27 3E F8 C2 DB C2 8E DF C9 DF C1 C6 CE D5 EF C9 C7 CA D7 D2 D6 DE 9E DE CE DA C7 DE D5 DF C2 97 DC D4 F9 AB FF FB E1 E1 EB AD F6 FA F0 E4 A8 A7 C1 FD EA FE FB ED FB FB BC BA B5 B3 E4 E8 E6 F2 DC FA 86 82 8C 88 97 A6 82 8B 8D A7 81 95 83 B4 81 96 89 92 97 97 B1 8F 99 93 A6 9A 9D 94 A2 8E 84 90 83 B8 98 BB A7 A2 AD BF BB 80 AC AE B5 A2 90 AC B7 BE 8B BC AD AC B5 B2 BC A0 94 B0 AF A4 90 B4 53 64 4E 7E 4B 4A 47 6E 47 51 54 40 4F 49 60 44 4E 5E 4B 7B 4B 4C 55 53 57 40 43 7E 54 5D 51 56 7E 42 66 6F 61 4E 6F 6E 6D 76 6E 75 52 7E 74 60 3A 75 77 6D 3E 6C 69 6D 62 7C 62 65 73 73 50 70 19 08 1A 00 1E 1B 05 02 0C 59 40 41 5D 24 05 0B 1A 0F 58 1F 17 11 18 5D 1E 1A 03 05 56 00 1D 01 22 6B 3B 39 2B 2C 25 2B 2B 26 24 61 28 26 29 20 7A 66 78 3F 2A 2F 72 2C 27 32 3E 25 39 20 31 27 84 C2 C6 CB CF CC C7 D8 D2 D0 CD C0 C8 C6 C3 C0 C8 FE D5 FF C8 D1 D4 FC F5 80 D3 C8 D9 CD D5 8C DB B3 DE FE C5 E2 E5 FE E1 F0 F9 EC E4 E8 E8 F6 C5 F7 F1 EA EA EC E8 E4 E2 F6 C3 DD C2 C7 E4 E7 83 88 8D 98 9B 8E 82 99 8B 97 99 91 94 8E 87 80 B7 9E 99 8A 8B 8D 99 90 97 9D 84 B0 94 84 9B 99 BF BF AD 86 A8 A9 BF A8 B6 AA B3 95 B4 A6 AD A9 B3 B5 BF A8 AB BE B2 A9 BB A7 A9 81 B3 A5 B7 B0 44 5F 49 4E 4B 7F 5E 44 41 46 70 53 4F 44 41 68 5F 5A 4B 4C 4C 5A 51 58 5C 47 79 42 62 45 55 5C 66 62 66 6E 5F 7A 6D 63 76 6A 74 78 56 62 76 66 7F 75 6C 78 79 7A 20 3D 2E 2E 30 47 77 65 7D 74 08 07 0D 3D 07 0C 07 21 07 05 14 23 09 15 00 00 08 29 11 1E 16 0B 3E 12 00 17 15 03 3F 19 17 19 3F 2F 2D 05 2B 29 38 0F 2D 31 24 24 34 13 2D 26 31 08 31 23 3B 0B 35 3E 39 10 3F 22 22 07 26 30 C9 C2 DB C0 C1 C1 ED C1 D0 C6 C1 C5 DF 87 C7 CA D4 D5 DD DA CA D6 D2 DA 92 DD DF C6 F2 DE C7 D6 E5 E5 E6 EC ED FB E5 E3 E5 A3 EE EE F1 A7 E7 EA F4 F5 FD FA EA F6 F2 FA BC BD BE B1 F5 F8 FA FB 8F 88 9C 80 80 88 CC 8B 83 8A 8C 84 82 C9 C4 B7 9F 9A 8B 96 90 C5 DC B1 9D 92 94 98 98 90 D4 86 AF B8 BB A0 A1 A1 BF E3 EC ED 83 FB 9A 80 AD B1 B6 BA BA F4 8C AA B2 B3 B7 A1 8C B3 A3 BE B8 B1 59 77 1A 4A 76 1A 6E 63 6E 73 7C 11 7A 44 48 4C 5F 55 4C 65 4A 5A 4E 50 5B 5D 51 5D 6A 53 51 43 6F 67 67 79 63 6A 62 79 5E 41 75 72 6F 69 61 76 69 57 79 60 7B 6D 40 49 60 72 74 78 78 70 44 79 0B 1F 0E 06 1C 02 42 2F 17 10 09 0F 03 14 17 29 1B 02 1D 0B 22 3C 13 13 1C 16 13 05 1F 18 1A 06 16 08 27 27 20 2A 2F 39 2B 2C 2E 6F 25 34 08 2A 3B 3F 31 37 39 7F 39 25 31 3B 31 3F 31 32 27 7B 84 85 E4 C6 CF CB C5 C3 C5 83 D3 D8 CB C5 CB C9 9A DC CA D6 CB CF CF 93 9C 9D FC DE D7 D3 DD DB ED AB E7 FB EA EA FE AD F6 FA F0 E4 F5 A9 AA AB D6 F4 F9 FD F7 F1 FB BD F3 E0 E3 F4 E2 E4 BA BB C4 A7 87 88 8A 86 82 8A C2 82 83 82 89 92 8A 91 89 D5 D6 D7 B2 90 9D 99 9B 9D 97 D1 99 87 80 9C A5 A5 E8 BA AB BD A5 A8 B1 ED EE EF 8A A8 A5 A1 B3 B5 BF F9 AD A6 B1 BF BD BF A3 FF F8 F9 98 BA 4B 4F 41 47 49 0F 5E 58 4E 46 53 0F 08 09 68 4A 5B 5F 51 57 59 1F 4C 52 41 5A 44 58 59 59 47 1B 24 25 44 66 6F 6B 65 63 65 23 63 6D 69 74 61 61 3A 6B 77 6A 77 6B 75 72 7C 60 3E 3F 38 5B 7B 74 0E 02 06 0E 4E 1D 09 1D 0D 11 14 12 48 49 4A 29 15 1A 1C 10 10 18 5C 12 00 17 15 03 05 59 5A 5B 06 24 29 2D 27 21 2B 6D 23 20 23 2E 33 29 30 65 35 2B 3D 2B 3F 2B 35 32 3C 20 7E 7F 78 1B 3B 34 CE C2 C6 CE 8E DB DE CC C6 CA CE C6 86 D4 CD C2 D4 DA D4 CA 90 91 92 ED C0 DC D3 D4 C5 C4 DD DB ED AB E5 EC FD FC ED EA E7 F0 AE AF A8 EF ED F6 EE F4 EA E0 B0 FB FE EB FD FF E5 FC F3 BA F5 FB 8B 87 91 9A 87 9C C2 89 80 96 93 84 94 CA 90 97 9B 9F 9D 8A D0 9B 9E B2 82 96 82 90 82 9E 9B 9B EA BC A9 BA EE AC AD A3 A1 A6 AC AD A3 A3 E4 A6 B5 B5 B6 BC BD AB B9 B9 F2 A0 A5 B2 B5 B2 A7 A6 4C 5E 44 45 57 4C 43 43 4C 46 43 55 43 43 67 4A 54 55 5D 5A 4A 56 53 53 12 44 51 42 16 53 5D 46 69 64 66 67 6B 6C 78 68 66 23 64 74 63 27 70 6A 3A 6F 70 7C 3E 73 7D 7E 79 33 7F 77 36 7B 7D 76 0F 05 1B 0C 37 00 19 4D 0A 02 16 04 46 05 01 00 14 5B 1B 16 10 11 19 1E 06 16 14 51 05 02 17 16 2F 38 3B 2F 3B 23 20 34 0D 37 28 24 34 67 32 20 34 3F 37 2B 2D 7F 2B 38 20 36 70 35 3F 24 37 3A C4 C5 CD CA DA CA C8 8D C6 D6 C5 81 D2 C8 84 D1 D2 DE 98 D5 DF DC D7 9D DD D5 90 DD DF D4 D1 DB F9 EE CB E6 E0 E1 E9 EE F6 EA EF EF C1 F5 EB F0 EA F4 D9 EC EA F7 BC F2 E2 E7 F9 FE F8 E4 B4 E2 8B 98 C8 87 81 9B CC 9E 87 97 A6 80 8F 8B C4 91 95 DB 9F 9C 90 9A 8E 9C 86 96 D0 83 97 99 90 9A A7 EB B8 A6 BC BB A4 B9 B6 B3 FA EE E9 AB AB A6 BB B7 B0 B6 AD AB E6 BE 86 A1 B1 B5 B3 A5 B7 B9 43 4E 46 5D 71 46 48 4E 4E 4A 45 4F 52 78 57 40 59 49 5D 4D 4C 5A 5A 4F 57 40 58 6E 42 58 5F 50 64 6C 7A 68 60 7B 53 79 7B 73 65 40 65 64 61 76 69 4F 77 72 7B 71 4E 78 74 61 75 62 7E 43 7B 7E 0F 05 2D 11 1E 06 1E 08 11 2A 0E 22 09 09 0A 00 19 0F 11 16 10 45 5C 2E 17 07 50 23 13 11 06 10 39 23 1C 26 25 2A 22 1F 27 30 35 2D 32 67 34 37 35 2B 3D 2B 2A 36 39 2E 31 3C 34 34 35 38 30 30 8A CF C7 CC DD 8F C2 C2 D6 83 C5 D9 CF D4 D0 D7 DF DF D1 CB DB DC C8 E2 C7 C1 D9 D0 C3 C3 DC DA F8 E2 F2 E8 FA E6 E3 E3 DD E0 EF E5 E3 E3 ED F6 F9 F4 F6 F7 FB FC E8 F4 FC F4 B0 F5 FF E4 F7 FA 84 85 8D 8A 9A 86 82 8A CC CD CE C1 82 8E 97 86 95 95 96 9C 9D 8B 99 99 D2 90 9F 9F 98 92 97 81 A3 A4 A6 E9 A2 A0 BF B9 E2 82 B5 B5 A9 E7 B6 A0 B9 B8 B7 B7 BB BC A8 B4 BD BD F0 B8 A5 F7 B0 BC 59 4A 4A 45 4B 4B 6F 42 4C 4D 45 42 52 4E 4B 4B 1A 52 4B 19 50 50 48 1D 51 5C 5E 5F 53 54 40 50 6E 48 67 67 60 6A 6F 79 6B 6C 6E 21 6F 74 24 50 74 70 76 76 69 71 3C 72 60 77 75 63 36 63 6D 65 0F 24 1A 0D 0B 1D 4C 1D 03 11 01 0C 03 13 01 17 09 5B 11 0A 5E 1A 11 0D 06 0A 23 08 1B 15 1B 19 39 6B 2E 3B 21 22 6C 29 2B 25 26 24 34 22 2A 31 7A 38 37 37 30 3A 3F 29 3B 3C 3E 22 17 3B 38 3A DD 8B E6 CC D9 8F E3 EE ED F3 CC C0 C5 C2 84 EA F9 F4 98 D7 D1 CB 9C DC DE DF DF C6 D3 D3 F3 D0 FE C5 E7 E7 C8 E6 F4 E8 E6 D0 F9 EC E4 E8 E8 A5 E8 FE E9 EC FB EC E8 BD E6 FA FD F4 B6 F8 E1 E1 CA 98 91 84 8C 80 80 CD 8B 87 C0 DC C6 AB 8B 84 9E 92 96 9E DE DF 9A 8F 9D 9E CA D1 D6 83 9B CF EA EB AE A0 A0 A6 BF A5 A7 A7 E0 A7 A7 AE A8 B6 AF B8 BB BC AD AC F0 FD 90 B2 A2 A2 EC F7 F8 F5 6E 5E 5A 48 5A 46 43 43 18 03 6E 13 06 54 41 46 4F 4B 5C 58 4A 5A 7D 5E 46 5A 5F 5F 16 54 5B 40 66 6F 28 67 61 7B 2C 6F 67 23 6E 74 6A 6B 67 64 76 77 7A 78 7D 74 72 72 32 72 73 65 7F 61 71 35 05 19 0C 0C 1C 1C 4C 0C 01 17 09 17 03 47 0B 17 1E 1E 0A 51 0D 56 5C 55 1C 1C 50 01 19 04 1D 01 23 24 26 3A 6E 3F 23 3E 2B 37 29 2E 28 6F 37 6C 7A 73 78 2E 37 2B 34 7D 72 32 3E 35 76 1A 31 26 D9 CA CF CC E1 DF C9 C3 ED D1 C4 C4 D4 87 CC C4 CC DE 98 D7 D1 9F FD DE D1 DC C5 DF C2 FE D0 99 AA DB E7 FA E7 FB E5 E2 EC CA E4 A1 BB A7 C9 E0 E9 E8 F9 FE FB D0 EC F8 FC DC E2 F5 F3 E5 B4 FD 8B 9D 8D C9 80 80 CC BE 9B 8E 82 8E 8A AE 80 C9 DA AB 97 8A 97 8B 95 92 9C BA 94 D1 CB D7 B9 90 B9 B8 A9 AE AB 80 BC A8 AC 93 AF B2 AF B3 AD AA B4 FB B0 B8 A8 BA FC B3 BD F3 91 B2 B5 B8 A1 BB 5E 62 4C 05 0E 7F 43 5E 4B 57 49 4E 48 6E 40 05 07 1B 75 5C 4D 4C 5D 5A 57 7C 40 54 58 67 5B 46 63 7F 61 66 60 2F 64 6C 74 66 20 6F 69 27 57 7C 77 79 77 75 57 7B 30 3D 42 7C 63 78 62 7E 7B 7B 23 0F 48 54 4E 22 09 1E 11 02 07 04 25 0B 0B 16 1F 1F 28 16 0D 16 08 14 1D 1D 50 19 17 01 11 55 24 24 68 08 2D 2C 23 38 2C 37 09 25 6A 67 14 2A 29 32 2C 30 31 31 15 39 72 6E 70 1C 33 24 27 34 CD CE EB C5 C1 DC C9 C9 F2 CC D3 C8 D2 CE CB CB 9A D3 D9 CF DB 9F D2 D2 92 E0 C9 DC D4 D8 D8 FC EE A7 A8 D9 E1 FC E5 F9 EB EC EE C8 E2 A7 B9 A5 D7 FE EB EA FF F8 F9 DE E0 EA E0 E5 F9 D6 E7 E6 8F 9F AA 88 82 8E 82 8E 87 90 C0 89 87 91 81 C5 94 94 D8 B8 9D 9C 93 88 9C 87 B9 95 BB 92 87 86 AB AC AD 8A BC B6 BC B9 AD 82 B3 B2 A3 B3 86 A4 B6 BA B6 BA BB AC FC B5 B3 A5 B5 F1 B8 B8 F4 94 59 58 4D 5D 67 4B 6F 5F 5B 53 54 4E 67 44 47 4A 4F 55 4C 19 57 4C 1C 4F 57 42 45 58 44 52 50 15 6C 64 7A 29 43 6A 7F 7E 63 64 65 42 74 7E 74 71 75 5A 6B 6A 7B 6B 5E 7C 7E 72 7E 72 73 64 3A 35 2B 08 0B 06 1B 01 18 4D 0B 07 40 5C 46 24 05 0B 1A 0F 58 1F 17 11 18 5D 13 10 13 1E 03 19 00 55 3D 22 3C 21 6E 26 28 6D 7F 63 03 2E 28 29 21 26 2E 32 37 37 7E 31 3D 30 37 05 35 3F 32 38 26 1B CB C6 CD E0 DD E9 CD DB CD D6 D2 C8 D2 C2 E7 CA D4 D5 DD DA CA D6 D3 D3 E1 C7 D1 C5 D3 F4 C6 D0 EB FF E1 E6 E0 DB F5 FD E7 CD E1 EC E3 BD A4 A5 CC FE F6 FD F1 ED A6 BD B2 D5 F1 E7 F9 E5 FD E1 8F D1 C8 AA 81 81 82 88 81 97 89 8E 88 94 DE C5 93 95 91 8D 97 9E 90 94 88 92 84 98 99 99 DA DB E4 88 A7 A7 A0 AA AF B9 AB AC AE B2 FC E7 AD AB B3 AF B1 B8 B2 B6 A6 B8 B6 F3 A3 A4 B5 B4 B1 A6 59 4D 5D 45 42 56 5A 48 4C 47 4F 53 68 46 49 40 79 5A 56 1E 4A 1F 5A 54 5C 57 10 55 53 51 55 40 66 7F 28 6A 61 61 62 68 61 77 69 6E 68 27 6D 6B 7C 74 38 7F 71 6D 3C 6B 77 7D 74 7E 64 37 29 35 4A 0A 06 0D 4E 08 1E 02 17 13 40 5C 46 24 16 00 1B 0F 1D 59 1D 0A 0F 09 1D 1E 50 12 19 19 1A 10 29 3F 21 26 20 3C 6C 24 31 63 24 24 28 2E 21 21 7A 3D 37 2B 7E 29 39 33 36 3C 22 71 6B 77 37 3A C4 C5 CD CA DA C6 C3 C3 EB CD C6 CE E7 C3 C0 85 CE DE DB D1 D0 D6 DF DC DE 93 F3 DE D8 D9 D1 D6 FE E2 E7 E7 C7 E1 EA E2 A2 EA F3 A1 E2 E2 EA EC FF FF F6 FC E9 D1 FD F0 F7 D0 FF E3 F3 AD B4 FC 84 82 9C 80 8F 83 85 97 83 97 89 8E 88 C9 CA CB B6 94 9F 9E 9B 8D C6 DD 9B 9D 99 85 9F 96 98 9C B0 AE AC E9 BD BA AF AE A7 B0 B3 A7 B3 AB A8 BC 99 B4 AA BC E4 FF B5 B3 BB A7 B9 B0 BA BE AE B0 4E 0B 5B 5C 4D 4C 49 5E 51 45 55 4D 4A 5E 45 46 59 54 4D 57 4A 76 52 5B 5D 70 65 62 62 78 79 6A 59 52 45 4B 41 43 53 4E 4D 4D 4E 44 45 53 4D 4A 54 53 51 4A 4A 50 4E 54 51 52 5C 4E 45 4E 59 57 25 27 37 2A 21 21 22 28 21 37 29 2E 28 38 2D 21 23 14 0D 59 16 1E 0A 18 52 1E 1F 03 13 57 00 1D 2B 25 68 26 20 2A 6C 2C 21 37 29 37 23 67 27 2A 34 35 3D 3A 2A 36 33 33 7E 73 29 3E 23 77 27 3D C5 DE C4 CD 8E DC DC C8 C1 CA C6 D8 86 C4 CB CB D4 DE DB CD D7 D0 D2 F4 D6 93 C0 D0 C4 D6 D9 D0 FE EE FA A9 FA E0 AC EA E7 F7 A0 F2 FF EA E6 EA F6 E8 E1 F4 FC F0 F0 D4 FC F5 FF E3 F3 E6 E1 F0 99 9F B8 88 9C 8E 81 88 96 86 92 92 BF 88 91 C5 97 8E 8B 8D DE 8C 8C 98 91 9A 96 88 D6 A5 9B 9A BE EB A7 BB EE BA A2 A9 A7 B1 AC A8 A3 B5 9D AA AF FB B0 B8 A8 BA FC B0 BD A1 B5 F1 A2 BF B5 BB 0A 44 46 4C 0E 4E 4F 59 4B 55 45 01 45 48 4A 4B 5F 58 4C 50 51 51 10 1D 4B 5C 45 11 45 5F 5B 40 66 6F 28 7A 7E 6A 6F 64 64 7A 20 62 69 69 6A 60 79 6F 71 76 70 56 78 3D 62 72 62 70 7B 72 60 70 18 4B 1C 06 4E 08 09 19 42 05 15 15 13 15 01 45 19 14 16 0D 0C 1E 1F 09 01 26 1E 15 13 05 18 1C 2F 39 01 2D 1D 2A 3E 24 27 0A 24 0E 34 23 21 37 7A 2E 28 3D 3F 2B 39 12 20 37 35 23 76 25 31 38 C5 DD CD C6 DC CB C9 DF F6 DA D0 C4 EF C3 FD CA CF 9B D0 D8 C8 DA 9C D0 DD C1 D5 91 C2 DF D5 DB AA E4 E6 EC AE EE EF F9 EB F5 E5 A1 E5 E8 EA EB FF F8 EC F0 F1 F1 B0 BD EB FC E5 B1 E5 FF FB E0 86 8F C8 9A 9E 8A 8F 84 84 9A C0 82 89 89 8A 80 99 8F 91 96 90 B6 98 DD 82 92 82 90 9B 92 80 90 B8 EB BC A6 EE A8 A9 B9 E2 8C B2 A5 A3 B5 90 BC AA BE 96 B6 FE B2 BD A9 B1 BB B9 BF B1 F7 B7 BA 44 45 4D 4A 5A 46 43 43 76 51 41 45 43 09 04 6A 48 5F 5D 4B 1E 56 52 5B 5D 09 10 52 57 59 13 41 2A 6D 61 67 6A 2F 63 7F 66 66 72 4E 74 63 61 77 3A 73 71 6A 6A 70 6E 64 41 67 7F 61 45 63 7B 65 26 02 05 00 1A 3B 1E 43 11 17 0F 11 2B 06 16 0E 1F 0F 0A 1C 0F 0A 19 0E 06 01 15 00 03 12 07 01 39 0A 24 25 21 38 6C 2A 30 2C 35 31 66 28 36 21 3F 29 2B 36 2C 3B 39 2F 21 2A 3D 33 39 3B 27 19 C3 D8 DC E7 CF C2 C9 DE DB CE C2 CE CA D4 CA C0 CD E8 C1 D4 DC D0 D0 CE FE DA C3 C5 F8 D6 D9 D0 C8 F9 E9 E7 EA E6 E2 EA C7 EE F5 ED E7 F3 EB F7 D7 FA EA F2 FB EB BC CF F7 E3 FC F0 EF C3 E6 F4 8E 82 86 8E CE BC 85 80 97 8F 81 95 89 95 B6 80 8B 8E 9D 8A 8A DF 8E 98 98 96 93 85 93 93 D4 91 BF AE E8 BD A1 EF B8 BF A3 A7 A9 AF A1 E7 B4 B7 B5 AF BD BA AA B6 B3 B3 F2 A0 A9 A2 A2 B2 B9 FB 0A 68 40 4C 4D 44 0C 54 4D 56 52 01 55 42 50 51 53 55 5F 4A 1E 17 7B 58 5C 56 42 50 5A 17 47 50 7E 7F 61 67 69 7C 2C 20 3C 23 54 73 67 63 6D 6B 7D 3B 68 6B 71 6B 79 7E 66 7A 7F 7F 3F 54 2E 49 2D 02 1C 05 0F 0D 41 3F 17 0D 0E 04 14 3B 06 10 13 17 1C 0A 22 4D 1F 25 47 31 3E 3D 26 2B 44 29 29 27 21 2C 20 3B 10 39 27 31 2D 28 28 26 28 19 3E 3E 2E 3C 32 30 2C 30 37 3D 24 0D 14 22 27 3C C4 CE DB DA E2 CE D5 C8 D0 FF F4 D3 C7 C3 CD CB DD EB D4 D8 CA D9 D3 CF DF 9D F2 C4 C5 DE DA D0 F9 F8 C4 E8 F7 EA FE D1 C1 EC F2 E4 A8 E4 F7 CA E8 FF FD EB BE ED F9 EC E7 F6 E3 E5 B6 E5 F1 FF 8F 88 9C 8C 8A CF 88 98 87 C3 94 8E C6 C0 A7 8A 94 9D 91 8B 93 DF 88 8F 93 97 99 9F 91 D7 9B 9B EA B9 AD A8 A2 EF AF A2 AC AD A5 A2 B2 AE AB AB FA AC B1 AD B6 FF AE A8 BC BD B9 BF B1 F7 A7 BC 47 5E 44 48 5A 40 5E 0A 02 50 45 55 52 4E 4A 42 14 1B 7B 51 5B 5C 57 1D 4B 5C 45 43 16 44 51 41 7E 62 66 6E 7D 2F 24 4A 67 6D 65 73 67 6B 24 76 7F 6F 6C 70 70 78 6F 3D 3F 2D 30 52 79 79 72 7C 18 06 09 1D 07 00 02 1E 42 45 40 36 07 15 0A 0C 14 1C 0B 50 17 0C 3D 1E 06 1A 06 14 12 16 00 10 25 3B 2D 27 01 29 2A 3E 27 37 23 2D 29 34 21 0A 3C 3D 2B 3C 2A 3B 3D 24 21 3C 20 34 38 03 3D 38 CF C8 C4 C6 DD CA F8 C4 CF C6 C9 C5 C5 C8 CA CB DF D8 CC D0 D1 D1 F5 D9 D7 CB D3 D9 D7 D9 D3 D0 C3 EF FB F0 E3 ED E3 E1 CB E7 E3 EE E8 F3 E5 EC F4 FE EA D0 FA EB F5 F0 F7 C9 FF FF F3 E3 FD F8 8F B1 87 87 8B A6 82 8B 8D 90 85 92 95 8E 8B 8B 89 93 97 95 97 9B 9D 84 81 80 95 82 85 9E 9B 9B 89 A4 A6 BD AF A6 A2 A8 B0 B0 A1 B2 B5 AE A3 AB B7 BE B6 AD AD 9C BD B3 B2 A7 F0 B7 BF B9 B0 F5 4B 4C 4F 5B 4B 48 4D 59 4B 4C 4E 01 51 4E 50 4D 1A 48 48 5C 5D 56 5A 54 57 57 10 5F 57 5A 51 15 59 7F 69 7B 7A 2F 7C 7F 6D 60 65 72 75 6E 6A 62 34 35 36 39 45 4C 68 78 62 33 3E 3F 38 37 4F 48 50 4B 3B 1D 0B 1F 4C 43 42 22 07 06 14 02 03 04 0E 12 17 17 5E 17 15 0E 06 1C 02 08 58 59 5A 55 39 24 3D 3B 2D 2A 6C 25 2B 30 34 2E 34 3E 64 26 35 2E 36 2D 7E 71 7C 1C 35 34 22 34 31 36 20 3C C5 C5 88 C1 C7 DC D8 C2 D0 DA 80 C7 CF C9 CD D6 D2 DE DC 97 9E E4 F5 C9 D7 DE C3 91 D5 D8 C1 DB FE B1 A8 A9 FE FD E3 EE E7 F0 F3 E4 E2 A9 D0 EC F9 F0 C8 EB F1 FC F9 EE E1 FA FE F6 B6 F1 FD FB 83 98 80 8C 8A C1 CC B6 B6 8C 94 80 8A C7 94 97 95 98 9D 8A 8D 96 92 9A D2 87 99 9C 93 CD D4 D5 B9 E5 E8 9D A1 BB AD A1 E2 B3 B2 AE A5 A2 B7 B6 BF BF F8 B0 AA BA B1 AE E8 F3 FE F1 84 B2 A7 A0 46 5F 08 48 49 48 5E 48 45 42 54 44 42 07 4D 51 5F 56 4B 03 1E 7C 5D 53 15 47 10 57 5F 59 50 15 63 65 6C 60 6D 6E 78 62 70 23 77 68 72 6F 24 62 73 6D 7D 77 3E 71 7D 70 77 50 71 7F 76 63 34 73 03 05 0C 49 0F 08 0B 1F 07 04 01 15 09 15 44 03 15 09 58 0A 1B 13 19 1E 06 16 14 51 06 16 06 14 27 2E 3C 2C 3C 3C 27 28 3B 15 21 2D 33 22 64 28 2F 28 2C 79 3C 3A 7C 3A 20 36 31 25 33 25 74 21 C2 CA C6 89 9E DF C9 DF CB CC C4 EC D3 CB D0 CC CA D7 D1 DC CC EA D2 D6 DC DC C7 DF 96 D5 D5 C6 EF AB F8 EC FC E6 E3 E9 C1 B9 DC C6 EF F3 E8 E4 F8 B6 CA EC F0 F1 F9 EF CE F1 E5 F8 FA F3 E7 C9 D8 88 B0 DC AC A1 A0 BD BE D3 BC 82 8A 8E 81 8B 8E A7 8C 9C 8C 92 95 93 93 9F AC 95 93 81 91 99 A5 BB A5 AC A0 BB 90 8F B7 B0 A9 AF A3 B4 B7 89 BB A2 BD AB 82 8B AE BC B6 BA BE B6 86 BB B5 A1 4C 44 5A 44 00 6D 59 5E 4B 4D 45 52 55 6B 45 5C 5F 49 64 71 57 4C 48 52 40 4A 6C 61 53 45 5D 5A 6E 25 6B 7A 63 47 48 5A 5B 41 61 72 63 57 61 77 73 74 7C 49 7B 6D 75 72 76 5E 65 7D 62 7E 64 79 13 0E 1A 20 00 1F 19 19 42 13 01 13 07 0A 01 11 1F 09 0B 3A 44 23 3B 14 06 1F 11 13 5B 25 01 1B 24 2E 3A 15 2C 3A 25 21 26 30 1C 73 25 1F 71 07 14 17 08 05 6E 03 3F 31 3B 36 3E 25 0A 23 31 27 C7 C2 C6 C8 C2 F3 C8 C8 D4 C6 CC CE D6 CA C1 CB CE E7 FA CC CD D6 D2 D8 C1 C0 FC D0 CF D2 C6 E9 DE F9 E9 ED E7 E1 EB DD EE E2 F4 E7 E9 F5 E9 AB D8 EE EB F0 F0 FA EF EE DE F2 E9 F4 E4 CB D9 FA 8E 9E 84 8C 9D B3 A9 95 87 80 95 95 8F 88 8A A0 94 8F 91 8D 87 D1 9F 8E BB 9D 80 84 82 A7 95 87 AB A6 AD BD AB BD BF ED EF E3 B0 A0 B4 A6 A9 A0 AE BE AA F9 FC FD FC BC BE A1 B5 B0 B2 AE F4 B0 52 42 5B 5D 5D 7C 4F 5F 4B 53 54 6A 43 5E 6D 4B 59 54 4A 4B 5B 5C 48 1D 5E 56 5E 56 42 5F 14 5A 6C 2B 5E 68 7C 66 6D 63 76 70 2E 21 4F 73 24 68 6F 68 6C 39 7C 7A 3C 78 64 76 7E 31 3E 7C 71 6C 4A 46 48 1F 0F 03 19 08 42 13 01 08 14 14 4D 28 1F 16 1A 1C 0C 5F 08 04 02 16 50 1C 03 04 00 55 28 2E 68 00 0D 20 21 3D 23 31 21 23 2A 22 0B 27 30 3E 3B 2D 2D 7F 28 24 22 36 70 3E 30 77 02 34 D8 C2 C9 C7 DA DC 82 8D EB D7 80 CC D3 D4 D0 85 D8 DE 98 F0 FD D0 D1 CD D3 C1 D1 D3 DA D2 E2 D4 F8 E2 E9 E7 FA FC AC E4 F6 E6 ED A1 E2 E8 E1 F6 BA F5 F7 ED BE EB F4 F8 B2 E0 F1 FC F3 B7 E0 EC 9A 8E C8 9D 86 8E 98 CD 83 97 94 93 8F 85 91 91 9F 9F D8 9A 92 9E 8F 8E D2 9E 95 9C 94 92 86 DB EA 82 BC E9 A3 BA BF B9 E2 A1 A5 E1 88 A8 B0 E5 A9 AE A8 A9 B1 AD A8 B8 B6 F3 B9 BF A6 A2 A0 F5 5A 4A 5A 48 43 4A 58 48 50 03 54 58 56 42 04 0D 53 55 5C 50 5D 5E 48 52 40 7A 5E 55 5F 54 55 41 65 79 28 60 7D 2F 6D 61 70 66 61 65 7F 27 65 61 7E 7E 7C 55 77 71 79 5B 7D 61 7D 70 62 63 71 71 3C 0A 04 1C 0B 20 1E 09 07 11 13 29 0F 14 10 0A 08 02 2A 1C 0F 0A 19 0E 06 23 11 03 17 1A 11 01 2F 39 3B 2F 3C 20 21 39 2D 17 32 20 22 22 37 0D 33 28 2C 36 2C 26 0E 38 23 26 35 22 22 07 35 27 CB C6 CD DD CB DD DF CB CD D1 C3 C4 F4 C2 C8 CA DB DF F7 F8 CB CB D4 EF D7 C0 C5 DD C2 F2 DA D6 F8 F2 F8 FD EB EB DE E8 E4 F1 E5 F2 EE D3 EB EE FF F5 CD EA FB CC FD EB F7 F7 C4 FE FD F2 FA E6 A6 82 86 82 BA 8A 94 99 B2 82 93 92 91 88 96 81 B2 94 94 9D 9B 8D AC 9C 81 80 87 9E 84 93 A7 94 BC AE 98 A8 BD BC BB A2 B0 A7 B4 B3 A7 A3 A5 A7 B6 BE 8B A0 B3 BD B3 B1 A3 A6 BF A5 B3 A4 87 AC 47 49 47 45 5A 46 4F 46 6A 4A 53 55 49 55 5D 76 43 56 5A 56 52 52 55 53 47 47 55 79 5F 44 40 5A 78 72 5B 70 63 6D 63 61 66 62 79 49 6F 74 70 6A 68 62 4B 60 73 7D 73 71 64 7C 7C 64 7B 72 55 7B 0B 07 11 1A 07 1C 3F 14 0F 01 0F 0D 15 1E 09 07 15 17 35 18 0E 0C 05 10 10 1C 1C 3C 17 07 3D 11 1E 39 29 2D 2F 2D 20 28 11 3A 2D 23 29 2B 17 3C 37 39 37 35 7E 32 3D 2D 72 35 3F 23 76 77 35 39 D8 CE C9 CD D7 8F C9 D5 CB D0 D4 D2 F2 D5 C5 C1 DB D9 D4 DC 9E DE D2 D9 92 C2 C5 DE C2 D2 C7 95 F9 F2 E5 EB E1 E3 AC EC F0 E6 A0 F5 EE E2 A4 F6 FB F6 FD B7 BE D2 FD ED E2 FA FE F6 B6 FE E7 B5 8C 84 9A 8B 87 8B 88 88 8C C3 94 8E C6 8E 90 96 9F 97 9E AD 8C 9E 98 9C 90 9F 95 D1 97 99 90 D5 BE A2 AB A2 BD EF A4 A4 B1 B7 AF B3 BF E7 B7 BC B7 B9 B7 B5 FE BE AE B8 F2 A7 B8 B4 F6 A4 B5 B8 4F 05 08 64 4F 5F 5C 44 4C 44 00 48 55 07 42 4A 48 59 51 5D 5A 5A 52 1D 46 5C 10 58 42 44 51 59 6C 5F 7A 68 6A 6E 6E 61 67 23 61 6F 62 27 69 6C 74 6E 6C 7C 6D 3F 74 74 61 67 7F 63 6F 37 67 6C 07 09 07 05 4E 0E 1E 08 42 17 08 04 46 14 05 08 1F 55 58 34 1F 0F 0C 14 1C 14 50 18 05 57 12 1A 38 29 21 2D 2A 2A 22 6D 36 2C 60 28 32 34 21 29 3C 0F 2A 38 3A 3E 3E 31 37 73 31 3F 32 77 30 34 D3 D8 88 C1 C7 DC D8 C2 D0 DA 80 D2 DF CA C6 CA D6 9B D9 CB DB 9F C8 D5 D7 93 C3 D0 DB D2 9A 95 C7 EA F8 F9 E7 E1 EB AD EB F0 A0 E7 E9 F5 E6 EC FE FF FD F7 BE EB F3 BD FB E7 E3 F4 FA F1 C0 E7 8B 8F 89 8B 82 8A CC 8C 8C 87 C0 97 89 8B 91 88 9F DB 99 97 9F 93 85 8E 9B 80 D0 82 8F 9A 96 9A A6 EB A9 BB AB EF B8 A5 A7 E3 B3 A0 AB A2 EA E5 97 BA A8 A9 B7 B1 BB FD BB A0 F0 B7 B9 A5 B6 BC 4E 4F 4D 47 0E 5B 43 0D 4B 57 53 44 4A 41 04 08 04 1B 61 56 4B 1F 54 5C 44 56 10 5F 59 43 14 45 65 78 7B 60 6C 66 60 64 76 7A 20 75 69 27 67 77 7F 7A 6C 7C 3E 6C 65 70 70 7C 7C 62 36 7A 75 65 1A 02 06 0E 4E 0D 09 0E 03 16 13 04 46 0E 10 45 1D 14 0C 59 0A 10 5C 1E 1B 01 13 1D 13 57 07 0C 27 29 27 25 3D 6F 21 2C 32 33 29 2F 21 67 6C 16 23 36 3A 36 32 1E 3F 3E 3D 26 3E 25 06 36 3D 27 F9 D2 C5 CB C1 C3 8C 90 82 8F 80 E0 C5 C4 CB D0 D4 CF 98 84 9E EE C9 DC DC C7 DF C6 D3 C5 76 1C AA DA FD E8 E0 FB E3 FA E7 F1 A0 CD CA C4 A8 A5 A8 AB A9 A1 B0 BF DD F1 FE B3 E2 F8 F1 FF E0 E6 CA 99 8D 9A 8B 9D 9A 88 86 8B 94 95 96 94 DE CA D5 8A 8D 98 90 8B 93 8A 97 81 DE 92 99 9A DB 85 B8 A2 BE A8 AD B6 A4 B9 B6 B3 B3 FB E9 E8 B3 B2 AD F5 A9 AC BF B1 A8 B2 A5 B6 A2 FF B5 B8 B9 FA 5E 4E 5A 44 5D 02 43 4B 0F 56 53 44 4E 53 50 55 49 01 17 16 4F 4A 5D 53 46 5C 47 54 44 19 57 5A 67 24 60 7D 7A 7F 7F 37 2D 2C 76 33 28 7D 6B 75 73 76 36 7A 71 72 33 6A 7B 77 77 74 62 38 78 7C 1C 0E 0B 01 0F 1B 42 05 16 0E 0C 5E 07 17 0D 3A 19 1A 14 15 0D 42 59 48 30 56 45 35 50 1F 1B 06 3E 25 29 24 2B 72 3D 38 23 2D 34 2E 31 22 36 6B 39 34 35 7F 35 3A 25 60 67 04 1E 35 1B 27 63 67 9D E8 DF E8 CC F7 EA E2 ED F9 D4 DB EA C8 EF D5 E2 CF 81 F2 E6 C9 F4 FB 94 DF D1 DF D1 8A D1 DB AC E3 FC FD FE FC B6 A2 AD F6 F0 E5 E7 F3 E1 F6 B4 EA ED F8 F0 EB F3 EA F7 E1 BE F2 F9 FA BB C4 9F 8A 86 9D 81 98 89 9F 8A 97 94 91 95 DD CB CA 8B 8E 99 97 8A 90 8B 98 80 DD 93 9E 9B D8 84 87 A3 A8 A1 A7 A9 A7 B8 B9 B2 B0 FA EE E9 A6 A7 A6 B5 AE B6 AD AD F1 AD A8 B3 BD A4 BE A1 B2 A6 FB 49 44 45 7E 4B 0F 44 4C 54 46 00 52 43 53 04 50 4A 1B 4C 51 5B 1F 58 58 54 52 45 5D 42 17 40 47 6B 6F 61 67 69 2F 69 63 74 6A 72 6E 68 6A 61 6B 6E 3B 7E 76 6C 3F 65 72 67 33 67 78 62 7F 34 57 03 05 09 07 0D 0A 4C 24 0C 05 0F 41 0B 08 00 00 54 47 1A 0B 40 43 1E 0F 4C 2A 1F 04 56 1A 15 0C 6A 28 27 27 20 2A 2F 39 62 37 2F 61 34 22 25 29 7A 39 2A 36 35 3A 2E 7D 25 3B 35 3F 76 2E 3B 20 8A CA DA CC 8E DD C9 CC C6 DA 80 D5 C9 87 D7 D1 DB C9 CC 99 CA CD DD D9 DB DD D7 9F F5 D8 C1 D9 EE AB E6 E6 FA AF E0 E2 E3 E7 A0 F3 E3 F6 F1 EC E8 FE FC B9 FF EC EF F8 FF F1 FC E8 B6 F6 E1 E1 85 86 89 9D 87 8C 8D 81 8E 9A C0 AF 87 8A 81 DF DA DB AA 9C 8F 8A 99 8E 86 9A 9E 96 B7 84 87 90 A7 A9 A4 B0 F4 EF 8E A4 AC A7 A9 AF A1 E7 B6 A0 BE B2 AA BC BD AB FC AA B3 A0 F0 B0 A6 A7 B8 BC 4F 4F 08 5D 41 0F 62 4C 4F 46 1A 01 06 75 41 41 53 49 5D 5A 4A 6F 5D 49 5A 09 10 7F 57 5A 51 15 69 6A 66 29 60 60 78 2D 60 66 20 64 6B 77 70 7C 4E 73 7D 39 77 6B 79 70 32 64 79 65 7E 37 67 74 07 0E 48 07 0F 02 09 4D 03 0F 12 04 07 03 1D 45 1F 03 11 0A 0A 0C 29 56 3C 12 1D 14 56 14 1B 00 26 2F 68 2A 21 21 38 2C 2B 2D 33 7B 66 0A 25 2C 36 1D 2A 36 33 1E 38 39 20 36 23 22 76 3E 27 75 C4 DE C4 C5 8E C0 DE 8D C7 CE D0 D5 DF D3 C1 DD CE 94 C8 D5 DF D6 D2 81 F0 E1 8E BB 8A F5 E6 8B AA CE E5 EB EB EB E8 E8 E6 A3 E9 EC E7 E0 E1 A5 A6 F2 F5 FE BE EC EE FE AF F0 F9 F5 AC F4 FB F8 9A 8A 86 90 82 80 8B 82 DC DF A2 B3 D8 93 81 9D 8E D4 90 8D 93 93 9F 92 9F 83 91 9F 8F 9B 9B 92 A5 98 AD BD BA A6 A2 AA B1 8E A1 AF A7 A0 A1 B7 F4 96 B9 B0 B2 8C B9 AF A4 B6 A2 FF 9B B6 BD B9 7F 58 4D 7A 7D 63 6F 42 4C 4D 45 42 52 4E 4B 4B 6F 48 5D 19 6D 6C 70 1D 51 5C 5E 5F 53 54 40 5C 65 65 5B 6C 7A 7B 65 63 65 70 4D 60 68 66 63 60 68 35 55 78 77 73 4F 78 60 65 75 63 38 5A 75 7C 06 27 07 0E 07 01 2D 18 16 0B 05 0F 12 0E 07 04 0E 12 17 17 5E 13 13 1A 1B 1D 23 14 02 03 1D 1B 2D 38 05 28 20 2E 2B 28 30 6D 0D 20 2F 2B 17 20 28 2D 3D 2B 70 12 3D 34 3E 03 31 22 25 20 3B 27 CE EA DD DD C6 CA C2 D9 CB C0 C1 D5 CF C8 CA 85 CA DA CB CA C9 D0 CE D9 E1 D6 C4 C5 DF D9 D3 C6 C7 EA E6 E8 E9 EA FE A3 CF E2 E9 ED D5 E2 F6 F3 FF E9 B6 D4 FF F6 F0 CE DF C7 C0 C2 F3 E5 E2 F0 98 BF 81 84 8B 80 99 99 B1 AE B4 B1 C6 94 81 97 8C 9E 8A D9 8A 96 91 98 9D 86 84 DD D6 9A 87 A6 AF BF BC A0 A0 A8 BF 80 A3 AD A1 A6 A3 B5 EA 88 BB B2 B4 8A BB AD AA B8 A0 FD 9D B0 BF BB 87 98 7E 7B 7B 4C 5C 59 49 5F 71 6E 74 71 06 54 41 57 4C 5E 4A 6A 5B 4B 48 54 5C 54 43 7C 57 59 55 52 6F 79 26 44 6F 66 60 5E 67 71 76 64 74 29 49 64 73 77 4B 54 4A 4F 4C 72 60 67 43 5C 42 47 34 65 05 19 1C 39 0F 06 1E 2E 0D 0F 0F 13 25 08 08 0A 08 4A 3B 16 12 10 0E 4F 21 0A 1D 13 19 1B 07 55 26 22 3B 3D 6E 21 2D 20 27 63 23 20 28 67 2A 2A 2E 7B 3A 3C 7E 3A 31 2D 26 2A 03 30 3B 32 74 26 D3 C6 CA C6 C2 DC 8C C1 CB D0 D4 81 C8 C6 C9 C0 9A DA D4 CB DB DE D8 C4 92 D6 C8 D8 C5 C3 9A 95 C5 F9 EC EC FC AF C5 E9 B8 A3 A0 D3 E3 F6 F1 E0 E9 EF D1 FD A4 BF C8 EF F3 F7 F9 FF F1 B7 FB E5 8F 99 89 9D 87 80 82 CD 90 86 93 94 8A 93 C0 B3 95 97 8D 94 9B DF 9D 93 93 9F 89 82 9F 84 D4 96 AB A7 AB BC A2 AE B8 A4 AD AD E0 A7 B4 A8 A9 E5 AE B2 BB B2 AD FF B4 B4 A1 A7 BF A3 AF F7 BD A6 0A 45 47 5D 0E 4E 40 41 4D 54 45 45 06 41 4B 57 1A 1B 59 5B 51 4D 48 58 56 1D 10 62 4F 5A 56 5A 66 2B 35 29 61 7F 78 64 6D 6D 55 6F 62 62 76 69 73 7E 6A 50 6A 7A 71 5C 71 67 79 7E 78 56 73 72 18 0E 1B 1A 01 1D 2A 01 03 04 23 00 0A 04 11 09 1B 0F 17 0B 44 5F 3D 11 17 01 04 34 18 16 16 19 2F 2F 01 3A 0D 20 20 22 30 2A 2E 26 07 2B 21 37 2E 1D 31 35 2A 3A 2E 1C 3E 36 22 25 18 32 31 31 E9 C4 C6 CF C7 DD C1 F9 D0 C2 C4 C8 C8 C0 E1 DD CA D2 CA DC FB C7 CC D4 C0 CA E4 D8 DB D2 D0 D1 C7 C6 F1 F0 F7 F6 AC C5 CA B9 ED EC BC F4 F7 AB FC FD FE FF F8 F9 CE F8 E2 F6 F1 E5 D7 FB F1 E7 9E AA 8B 9D 87 80 82 9E B0 86 90 84 87 93 A9 84 82 B8 97 8C 90 8B AE 98 82 96 91 85 A6 92 86 9C A5 AF 85 A0 A0 BA B8 A8 B1 90 A5 A0 B4 A4 AC 84 B6 BE AA AD 97 9B 9F B2 BC B7 B9 A5 BF B8 BA 92 58 44 5D 59 5D 6E 4F 59 4B 4C 4E 52 65 48 4A 41 53 4F 51 56 50 4C 69 53 56 56 56 58 58 52 50 66 73 66 6A 66 62 20 4E 78 71 6A 6E 64 75 74 4B 67 70 7E 7B 6D 57 71 7A 72 53 70 73 7E 63 79 60 3A 28 1E 1B 00 00 0A 1F 1E 2D 01 0A 04 05 13 2D 0B 1C 14 31 0A 2D 1A 10 18 11 07 15 15 35 18 19 18 23 38 3B 20 21 21 0D 3F 20 2A 34 33 27 20 21 16 23 36 3A 36 32 0B 35 30 37 15 22 30 3B 32 17 3A C4 CD C1 CE C7 DB C9 C0 F6 CA C3 CA 86 8A 84 F1 D3 D8 D3 99 93 9F 8D C9 DB D0 DB C2 E2 DE D7 DE AA E9 E9 FB FD CC E0 F8 F1 F7 E5 F3 C5 F2 F7 F1 F5 F6 DB F6 F2 F0 EE D1 F7 E5 F5 FD DF E4 D7 FD 8F 88 83 8C 8A BB 89 95 96 A0 8F 8D 89 95 A6 84 99 90 9F 8B 91 8A 92 9A B1 9C 9C 9E 84 B4 9B 99 A5 B9 9B BD B7 A3 A9 9A AB B7 A8 82 A9 AB AB B7 89 AF A1 B5 BB 88 B5 B9 A6 BB 93 BE BA A2 B9 BB 69 44 46 4D 47 5B 45 42 4C 6A 54 44 4B 64 4B 4B 5E 52 4C 50 51 51 68 44 42 56 73 5E 58 53 5D 41 63 64 66 5F 6F 63 79 68 41 6C 6C 74 6B 69 35 4A 7C 7D 6B 7C 6A 5C 73 71 67 7E 7E 23 59 71 72 66 0F 1F 2B 06 02 1A 01 03 50 31 01 0F 01 02 37 00 16 1E 1B 0D 11 0D 2E 1C 1C 14 15 25 0F 07 11 30 24 2F 07 2F 28 3C 29 39 04 31 2F 2C 12 28 02 2C 38 34 36 38 3D 3C 35 11 37 25 35 3D 1A 32 22 30 C6 FE DB CC ED DA DF D9 CD CE E9 D2 E3 C9 C5 C7 D6 DE DC FA DF CF C8 D4 DD DD F6 DE D8 C3 F7 DA E6 E4 FA CA EF FF F8 E4 ED ED C6 EE E8 F3 C2 E4 F7 F2 F4 E0 D0 FE F1 F8 D1 F2 E0 E5 FF F8 FA D3 85 85 9C BA 87 95 89 BD 8D 8A 8E 95 AA 8E 8A 80 B5 8B 8C 90 91 91 8F AA 9B 87 98 B2 9E 92 97 9E 88 A4 B0 9E A7 BB A4 83 B7 AE A5 B3 AF A4 93 AC AE B3 9B B6 B2 B0 AE 9B BD BD A4 9C B7 AF BD B8 5F 46 7F 40 4A 5B 44 61 4B 4D 45 72 52 5E 48 40 68 48 4B 70 4A 5A 51 4E 60 40 43 62 53 43 40 5C 64 6C 7B 4B 7B 7C 65 63 67 70 73 21 48 62 73 76 3A 49 7D 6C 6A 7A 6E 6E 7A 67 64 61 2C 38 3B 73 0F 0E 0C 1A 40 1D 09 18 16 06 12 12 48 04 0B 08 55 09 1D 0C 0A 1A 0E 0E 5D 11 05 02 1F 19 11 06 39 25 2D 3E 3D 0D 0E 0E 62 16 0B 29 32 33 34 7F 75 74 3E 3C 3B 3B 2F 73 30 31 33 38 78 34 3B 7B DF C0 87 C7 CB D8 DF 82 D6 C6 C3 C9 C8 C8 C8 CA DD C2 97 CB CD CC 92 C5 DF DF 8F D4 D2 DE C0 DC E5 E5 B5 FC E5 C2 ED FF E9 E6 F4 F1 F3 EB F7 E0 F2 EF EC E9 A4 B0 B3 FB F7 F6 F4 E2 B8 FA F5 E7 81 8E 9C 9E 8F 9B 8F 85 CC 80 8F 8C C9 8A 85 97 91 9E 8C 8E 9F 8B 9F 95 DD 9E 91 83 9D 92 80 85 BF A7 BB AC E1 9D BF BE 8B B7 A5 AC 8F B4 85 A6 AE B2 AE BC 8B AD B0 B8 BC B2 B2 BD B3 B3 97 EF 76 6C 41 5D 42 4E 4E 00 70 56 4E 4F 43 55 78 47 4F 52 54 5D 4D 63 0E 5E 6A 06 72 7F 7A 67 68 05 56 68 64 60 6B 61 78 51 76 66 72 6C 6F 69 65 69 46 7F 7D 6F 7B 73 73 6D 7F 76 7E 65 4A 55 61 66 03 05 0D 1A 1D 23 0D 14 07 11 3C 35 14 06 00 0C 14 1C 28 15 1F 0B 1A 12 00 1E 5E 33 03 04 1D 1B 2F 38 3B 05 2F 36 29 3F 1E 16 34 28 2A 34 18 11 28 3A 3C 30 30 38 0C 2F 3D 27 35 32 22 3E 3B 3B F6 FF DA C8 CA C6 C2 CA F2 D1 CF D5 C3 C4 D0 CA C8 95 DB CA CE DA CE D4 DD D7 DC D8 DB DE C0 FA F8 EF ED FB FD AF E0 E4 EF EA F4 D2 E3 F3 F0 EC F4 FC EB D4 FF F1 FD FA F7 E1 BE C5 E4 F6 F0 FC 84 8C B8 9B 81 9B 89 8E 96 8A 8F 8F C8 A8 96 81 9F 89 8B B5 97 92 95 89 93 87 99 9E 98 D9 A4 90 B8 A2 A7 AD 9D AA B8 B9 AB AD A7 B2 8B A6 AA A4 BD BE AA F7 8A AD BD B9 BB BD B7 81 A4 B8 A0 B0 49 5F 41 46 40 01 63 5F 46 46 52 52 6A 4E 49 4C 4E 5A 4C 50 51 51 12 71 5B 5E 59 45 75 42 46 47 6F 65 7C 59 6F 7B 64 5E 6D 76 6E 65 4F 73 61 68 69 6F 77 6B 7F 78 79 59 73 67 71 42 62 78 66 74 0D 0E 48 00 1D 4F 08 04 11 13 0F 12 03 03 2B 31 2A 33 17 15 1A 1A 0E 32 26 23 26 10 1A 02 11 36 25 25 2C 20 3A 26 23 23 06 22 34 20 09 37 21 37 3B 35 3C 68 11 2F 39 2F 33 3D 34 63 15 38 3A 31 C3 DF C1 C6 C0 E6 D8 C8 CF D0 EF D1 C3 D5 C5 CB DE F8 CD CA CA D0 D1 EE C6 C1 D9 DF D1 F8 C4 D0 F8 EA E6 ED CD FA FF F9 ED EE D3 F8 EB E5 EB E9 D5 EB FD EB FF F1 F8 DE E7 E0 E4 FE FB D3 F5 E1 8F A4 98 8C 9C 8E 82 89 A1 96 93 95 89 8A A5 86 99 94 8D 97 8A B0 8C 98 80 92 9E 95 B5 82 87 81 A5 A6 9B AC A2 AA AF B9 AD B1 8F B1 A3 B5 A5 AB BE 94 BA B3 BB BC A8 8D A0 BC A0 B4 A4 A3 AD 9A 5A 4E 5A 48 40 4B 63 4F 48 46 43 55 76 55 4B 55 5F 49 4C 40 6D 5A 50 58 51 47 5F 43 65 43 55 47 7E 2B 7A 6C 7D 7B 63 7F 67 23 72 64 60 75 61 76 72 3B 6C 76 75 7A 72 5B 73 7A 7C 74 72 37 60 7A 4A 19 0D 1A 1A 00 1E 08 42 13 12 04 10 0E 0B 10 09 5B 0B 1C 0D 0C 15 12 1C 5D 4C 33 24 49 24 19 2F 2A 3B 2C 6E 23 23 2A 2B 2D 60 20 21 26 2D 2B 74 1D 39 30 32 7F 28 32 72 37 35 32 24 2E 24 21 8A E4 E9 FC FA E7 8C DF C7 D0 D4 CE D4 C2 84 D1 D5 D0 DD D7 FB D1 D8 9D C0 D6 C3 C5 D9 C5 D1 95 F8 EE EE FB EB FC E4 AD F6 EC EB E4 E8 C6 F1 F1 F2 F4 EA F0 EA E6 BC C8 C0 DF B0 F9 F7 E4 B4 FB 85 9F C8 8F 81 9A 82 89 A4 82 89 8D C6 93 8B C5 99 94 96 97 9B 9C 88 DD 86 9C D0 9E B7 82 80 9D EA F1 E8 8F AF A6 A0 ED B6 AC E0 A6 A3 B3 E4 B0 A9 BE AA F9 B7 B1 BA B2 F2 E9 F0 9D BF B4 B1 BB 49 4E 08 5A 4B 5D 5A 44 41 46 00 74 74 6B 04 4D 5B 48 18 57 51 4B 1C 5B 5D 46 5E 55 70 56 5D 59 6F 6F 28 7D 61 2F 6F 62 6C 6D 65 62 72 3D 24 37 2B 2D 29 2B 2B 2C 24 2D 22 23 20 25 22 24 39 40 04 00 06 06 19 01 41 5D 52 57 52 58 4B 5F 54 50 48 49 55 4A 4A 47 4E 44 5F 32 31 41 4E 41 46 47 7A 79 7D 7A 7D 78 7C 7D 72 73 70 75 75 6A 11 2B 31 35 37 2E 30 72 6C 6D 66 61 69 7C 6E 67 61 67 98 86 9B 9D 96 9D 95 80 E3 E2 90 99 90 E3 C1 C3 DB CE D4 CD 9E CC C8 CF DB DD D7 9C 9C 9A 84 85 B9 B8 B9 A4 BF BF BC BD B2 AE B0 B1 B6 B7 B5 A8 DB DA A9 A0 AC D9 FD F4 FE B3 E4 FE B6 F4 FB FB 84 8E 8B 9D CE 9B 83 CD 8D A2 95 95 8E C7 CC 97 9F 88 8C 96 8C 9A DC 89 9D 98 95 9F DF CD D4 BC AE AE A6 BD A7 BB B5 ED B1 A6 B2 B7 A3 B5 E4 AC A9 FB AD B7 BF A9 BD B4 BE B2 B2 BD B3 F7 BA BA 5D 6D 49 40 42 4A 48 0D 56 4C 00 53 43 54 50 4A 48 5E 18 4A 5B 4C 4F 54 5D 5D 0A 11 5E 43 40 45 79 31 27 26 69 6E 78 68 75 62 79 2F 67 64 67 6A 6F 75 6C 6A 30 6E 69 7C 7C 67 7F 66 73 65 3A 76 05 06 47 08 1E 06 43 1B 53 4C 07 00 12 02 13 04 03 54 11 1D 1B 11 08 14 06 0A 2F 14 18 13 04 1A 23 25 3C 1D 3C 36 6C 39 2D 63 27 24 32 67 2D 21 3F 35 2C 30 2A 26 7C 38 3C 37 20 3E 3F 39 20 75 CC D9 C7 C4 8E C3 C3 CE C3 CF C8 CE D5 D3 C5 D5 D3 94 CE 88 91 D8 DD C9 D7 C4 D1 C8 99 D0 D1 C1 D5 EE E6 ED FE E0 E5 E3 F6 F0 D4 F3 FF A7 F0 EA BA FC FD ED BE FA F2 F9 E2 FC F9 FF E2 E4 B4 F3 98 84 85 C9 82 80 8F 8C 8E 8B 8F 92 92 8B 8D 86 9F 95 9B 9C 9F 8F 95 D2 84 C2 DF 83 83 9B 91 86 9E B9 B1 E9 BA A0 EC AA A7 B7 E0 AD AF A4 A1 AB B9 BE AB F9 B8 AD B3 B0 F2 BF BF B2 B7 BB BC BA 59 5F 40 4C 4F 43 58 45 6B 47 45 4F 52 4E 50 5C 1A 53 5D 58 52 4B 54 07 12 7F 59 52 53 59 57 50 47 6A 66 68 69 6A 7E 2D 77 70 65 73 26 54 6D 62 74 7E 7C 56 6B 6B 3C 7F 6B 33 63 74 64 61 71 67 26 02 0B 0C 00 0C 09 4D 0F 02 0E 00 01 02 16 45 1D 1E 0C 59 0C 0A 10 18 01 53 15 03 04 18 06 4F 6A 07 21 2A 2B 21 2F 28 62 0E 21 2F 27 20 21 37 60 7B 34 30 2D 2B 39 33 37 21 70 21 39 25 20 75 C5 DB CD C7 C7 CB DC DF CD C5 C9 CD C3 C8 C2 C3 D6 D2 D6 DC E1 DE DF DE D7 C0 C3 FD DF D4 D1 DB E9 EE DB EC FC F9 E5 EE E7 D2 F5 E0 E8 F3 EB F2 FF E9 CC FC EC F2 F5 F3 F3 FF A6 F3 F2 F2 A5 A7 89 DA C5 DE 88 D8 8E C0 D6 D3 82 D7 CB 85 81 87 9B D6 CE 9A CE CC 9F 9E C2 91 C9 C0 97 C3 A0 87 B3 EB BC A6 EE A8 A9 B9 E2 AF A9 A2 A3 A9 A7 A0 A9 FB BE AB B1 B2 FC AE B7 A1 A6 B4 A4 F7 A3 BC 5E 43 08 5A 4B 43 4A 0D 51 4A 47 4F 43 43 04 46 5F 49 4C 72 5B 4C 48 4F 57 5F 10 5D 5F 44 40 50 64 62 66 6E 2E 7A 7E 61 38 23 3C 69 37 39 5D 6A 6F 3B 7B 78 70 3F 72 72 65 33 62 74 62 62 66 7B 4A 1F 07 49 1A 07 09 4D 03 13 10 0D 0F 04 05 11 13 14 16 57 42 50 14 4C 4C 34 35 25 39 27 20 3C 05 05 1B 19 01 1C 18 2C 32 33 2C 28 25 26 30 2C 35 35 77 21 73 28 2B 2A 7F 35 3F 23 3B 7A 21 27 C6 CE C6 CA C1 CB C9 C9 CE CC C3 C0 CA CF CB D6 CE F9 CA D6 C9 CC D9 CF 92 C1 D5 C2 C3 DB C0 95 B0 AB CD E4 FE FB F5 AD F0 E6 F3 F1 E9 E9 F7 E0 B4 B5 B8 DC F0 EB F5 E9 EB B3 AD B1 DB F2 F9 F7 8F 99 C8 CE C9 CF 81 84 91 90 89 8F 81 A4 DE B9 BD 92 8C 95 9F 9D D1 AF 87 9D 9E 94 84 AB 96 80 A3 A7 AC BA 92 FD AF 95 F7 81 8E 8D 96 9B F4 99 B9 B7 B1 BC B0 AB 80 A9 B7 A1 BD B8 B8 B6 B8 89 4E 4E 5E 4C 42 40 5C 40 47 4D 54 7D 64 52 57 4C 54 5E 4B 4A 72 5E 45 58 40 6F 64 43 57 53 5D 5B 6D 5B 64 68 7A 69 63 7F 6F 2D 42 74 75 6E 6A 60 69 68 54 78 67 7A 6E 41 56 72 64 70 54 7E 7A 71 03 05 0F 35 2D 00 02 1B 07 11 14 04 14 14 38 36 0E 09 11 17 19 2B 13 31 1D 10 11 1D 1F 0D 11 11 19 3F 3A 20 20 28 0F 22 2C 35 25 33 32 22 36 6B 39 28 3B 36 30 29 39 2F 26 17 35 3D 33 30 35 21 CF FF CD C5 CB C8 DE CC CF E6 CD C0 CF CB E9 C0 C9 C8 DD D7 D9 DA CE CE FF D2 DE D0 D1 D2 C6 8F AA E2 E6 E0 FA E6 ED E1 EB F9 E1 F5 EF E8 EA AB B4 B5 D5 FC ED EC F9 F3 F5 F6 E2 D2 F7 F9 B3 E1 CA 88 9A 8C 8F 9B 89 CD AB AE 85 92 95 82 8A 82 9F 89 D8 9F 8C 90 91 DD 86 8A 80 94 D6 BA 91 86 B9 AE A6 AE AB BD EC BA AB B7 A8 E1 A8 A6 A9 A0 FA FB B9 B5 AC BA BD B9 AB F3 B5 A9 BF A4 A0 A6 04 66 4D 5A 5D 4A 42 4A 47 51 53 6C 47 49 45 42 5F 49 02 19 1E 52 59 4E 41 56 5E 56 53 45 47 15 7D 6E 7A 6C 2E 63 63 6C 66 66 64 2F 4B 62 77 76 7F 75 7F 7C 6C 6C 51 7C 7C 72 77 74 64 2D 34 7C 04 02 1C 00 0F 03 05 17 03 17 09 0E 08 47 02 0C 14 12 0B 11 1B 1B 52 3C 01 00 15 05 05 32 0C 16 22 2A 26 2E 2B 3C 0D 2E 21 2C 35 2F 32 34 17 3C 37 39 37 35 2D 10 2C 29 3B 3C 3E 02 33 25 3D 30 D9 EF C9 D0 EC CE DE DE E1 D1 D9 D1 D2 C8 E5 C6 D9 D4 CD D7 CA CC FD CE C1 D6 C4 F3 D7 DB D5 DB E9 EE FB C6 FE EA E2 C2 F0 E7 E5 F3 F5 CA E1 F6 E9 FA FF FC ED CF F3 EE FB E7 F9 FE F8 DA F1 E6 99 8A 8F 8C 9D A0 9C 88 8C A7 85 8D 8F 91 81 97 9F 9F B9 8A 8D 9A 88 B0 97 80 83 90 91 92 87 A6 AF B8 BB A0 A1 A1 BF 8E AD AD B4 A0 AF A9 A1 B7 A9 88 B6 B8 AE AC B4 B2 A6 97 B1 A5 B7 FB F4 9C 6E 11 08 05 0E 61 4D 40 47 19 00 0D 06 65 45 49 5B 55 5B 5C 04 1F 71 58 41 40 51 56 53 76 57 56 65 7E 66 7D 4F 7C 7F 68 76 4A 64 43 67 6B 65 6B 79 7E 56 7C 6A 6B 75 73 75 47 69 61 73 56 77 76 05 1E 06 1D 2F 0B 08 04 16 0A 0F 0F 07 0B 2D 0B 1C 14 3C 1C 0D 1C 0E 14 02 07 19 1E 18 3A 1D 1B 23 26 3D 24 0D 27 2D 23 25 26 09 12 09 06 27 26 35 2E 36 2D 17 3B 08 32 26 32 3C 13 37 3B 35 3B C9 CE E9 DF CF C6 C0 CC C0 CF C5 E3 C7 CB C5 CB D9 DE EA DC CD DA CE CB D7 D7 F2 D0 DA D6 DA D6 EF DF E7 FD EF E3 C5 E3 D7 D0 C4 D5 E9 F3 E5 E9 D3 F5 DA CD DD DB F9 FF E6 D6 E1 E4 FF E3 ED D0 9B 9E 81 9D 97 A6 82 AF B6 A0 CC C1 A8 86 89 80 DA B6 9D 8A 8D 9E 9B 98 B7 8B 93 99 97 99 93 90 8F B3 AB A1 AF A1 AB A8 8B A7 85 B9 A5 AF A5 AB BD BE 96 B8 B3 BA 8F B8 A1 A0 B9 BE B8 A4 97 BA 44 5F 49 40 40 4A 5E 64 46 6E 45 52 55 46 43 40 75 4B 5D 57 7A 5A 50 54 44 56 42 54 52 76 47 46 6F 7F 5B 70 63 6D 63 61 4B 67 53 75 67 73 71 76 59 69 7D 78 6A 76 73 73 46 7A 7D 74 3A 37 47 6C 07 09 07 05 54 4F 40 4D 32 11 09 02 03 5D 44 49 5A 28 11 1D 1B 45 5C 51 52 27 09 01 13 4D 54 38 2F 38 3B 28 29 2A 03 3D 27 2D 0F 33 22 22 36 0A 28 3F 3D 2B 17 3B 1B 2F 3D 26 20 18 32 07 3B 26 C3 DF C1 C6 C0 E6 C8 F9 CD D7 C1 CD F7 D2 C5 CB CE D2 CC C0 F8 D6 D0 D1 D7 D7 E1 C4 D7 D9 C0 DC FE F2 DB E0 EA EA CF E2 EF EE E5 EF F2 CB E5 F6 EE CE E8 FD FF EB F9 C9 FB FE F5 DE E4 F3 F1 E7 BE 92 98 8C A7 8B B8 84 8F 86 A9 8F A0 88 96 86 9F BE 80 89 97 8D 9D 89 9B 9C 9E A5 9F 9A 91 A1 B8 A2 AF AE AB BD 9C BF AB A0 A5 95 B4 A6 AD A9 95 BD BE AA BB AB 93 AF BB B4 B9 BF B7 BB 87 A1 4B 5F 5D 5A 6F 4B 48 44 56 4A 4F 4F 47 4B 6D 4B 5C 54 71 4D 5B 52 4F 11 12 7C 40 54 58 17 44 47 63 68 6D 33 2E 42 69 7E 71 62 67 64 49 77 61 6B 4A 74 6B 70 6A 76 73 73 5D 63 75 7F 46 65 7D 76 0F 24 18 0C 00 20 1E 09 07 11 29 05 2A 0E 15 10 13 1F 19 0D 17 10 12 2D 00 1A 13 14 25 0E 19 17 25 27 72 69 6E 0A 34 3D 06 22 34 24 7C 67 64 0B 3B 36 3D 63 7E 12 39 2E 21 32 37 34 19 27 20 3C C5 C5 FB CC DC C6 C9 E8 DA D3 C9 D3 C7 D3 CD CA D4 FF D9 CD DB EC D9 CF DB D6 E4 C8 C6 D2 98 95 DC EA E4 FC EB B5 AC C5 ED EF E9 E5 E7 FE F7 D6 FF E8 EB F0 F1 F1 EF CE F7 E7 E3 DC F3 E4 E7 F4 8D 8E BB 8C 9D 9C 85 82 8C 90 A3 8E 88 93 85 8C 94 9E 8A B5 91 8B AF 89 97 83 BD 98 98 BB 9B 81 87 AA B0 85 A1 BB 99 A3 A6 A6 B2 AD AF A2 B6 8B BB B6 BD 98 A8 BE B5 B1 B3 B1 BC B4 90 A2 A0 A0 58 4E 5B 68 58 4E 45 41 43 41 4C 44 69 57 50 4C 55 55 4B 76 4E 4B 55 52 5C 60 55 43 5F 52 7D 51 45 7B 7C 60 61 61 58 74 72 66 53 75 74 6E 6F 60 4A 69 71 7A 7B 53 7D 6E 66 47 62 70 72 7E 7A 72 2E 0A 1C 0C 38 0E 1E 04 03 01 0C 04 32 0E 07 0E 36 12 0B 0D 2A 0D 1D 19 17 49 50 5D 56 26 00 0C 70 6B 64 69 01 3D 28 28 30 63 29 25 7C 67 17 2C 3D 35 39 35 64 7F 11 34 3C 07 22 30 32 32 02 3A C6 DE C5 CC E3 C6 C2 8D D6 D1 C1 C5 C3 87 D2 CA D6 CE D5 DC FD 85 E0 FA DB C7 DC D0 D4 9A E6 C0 E4 E5 ED FB D2 ED F9 E4 EE E7 F3 DD B4 E4 DC B0 D8 D5 D4 C9 C2 AF C0 FE FE FA F5 FF E2 CB E0 F0 98 86 81 87 8F 83 B0 89 87 95 85 8D 89 97 89 80 94 8F A4 BB 8B 8C 95 93 97 80 83 BD 97 8E 91 87 96 9F BA A8 AA A6 A2 AA 92 AF A1 B5 A0 A8 B6 A8 F4 99 AD AA B7 B1 B9 AE A1 9F B1 A8 B3 A5 88 9D 43 58 5C 46 5C 56 70 6C 45 44 52 44 41 46 50 4C 55 55 4B 65 76 56 4F 49 5D 41 49 70 51 50 46 50 6D 6A 7C 60 61 61 5C 62 75 66 72 55 74 66 60 60 69 4B 79 6B 7F 72 79 69 77 61 63 3F 75 64 59 74 12 3F 1A 08 0A 0A 3A 02 0E 16 0D 04 2B 06 1C 45 0E 09 19 1D 1B 5F 0A 12 1E 06 1D 14 22 18 00 14 26 1D 27 25 3B 22 29 19 2D 37 21 2D 66 31 2B 29 2F 36 3D 0D 37 32 39 14 3C 27 35 23 20 36 38 01 C3 C6 CD 89 C7 C1 D8 C8 D0 D5 C1 CD 8A 87 D7 C0 D9 F9 D9 CA D7 CC EA D2 DE C6 DD D4 FF D9 C0 D0 F8 FD E9 E5 CC EE FF E4 F1 A3 F6 EE EA F2 E9 E0 BA F2 F6 ED FB ED EA FC FE BF B0 E2 F3 F4 D0 F0 86 9F 89 AF 87 83 98 88 90 A5 89 8D 92 82 96 C5 98 82 D8 BD 9B 93 88 9C DE D3 D5 B3 97 84 9D 86 98 AA BC A0 A1 89 A5 A1 B6 A6 B2 87 AF AB B0 A0 A8 FB BA A0 FE 9D BD AE BB A0 F0 A3 B7 A3 BD BA 06 0B 0D 64 4F 57 76 42 4C 46 68 44 4F 40 4C 51 77 5A 40 19 44 50 52 58 12 5B 55 58 51 5F 40 19 2A 7F 61 6A 65 7C 41 64 6C 59 6F 6F 63 4F 61 6C 7D 73 6C 54 77 71 3C 67 7D 7D 75 31 7E 72 7D 72 02 1F 44 49 1A 06 0F 06 11 20 15 12 12 08 09 31 13 18 13 2A 17 05 19 3E 07 00 04 1E 1B 57 00 1C 29 20 68 3A 27 35 29 0F 23 31 10 33 2F 24 21 11 23 2B 3D 0A 2A 3B 1F 3C 3E 30 25 3D 37 23 3D 3A C4 FF D1 D9 CB 8F D0 8D F6 CC D4 C0 CA 87 C6 C4 D6 DA D6 DA DB 85 9C E9 DD C7 D1 DD F4 D6 D8 D4 E4 E8 ED A9 FE EA FE EE E7 ED F4 BE AF B8 D7 E0 F6 FE FB ED FB FB BC E9 FB FE F5 B1 FF F9 B4 F3 85 99 8B 8C CE 81 83 99 C2 82 8C 8D 89 90 81 81 DA 9D 97 8B DE DF 93 8F 96 96 82 D1 82 8E 84 90 83 A5 AB A6 BC BD A9 AE B6 E3 93 8D E9 93 94 E5 AA A9 B1 BA BB FF B1 B8 B3 A0 A5 A3 B3 BA B1 BB 5E 11 08 0E 09 0F 41 48 43 50 55 53 43 4A 41 4B 4E 1B 59 55 52 50 4B 58 56 1F 10 53 43 43 14 12 2D 2B 65 6C 6F 7C 79 7F 67 6E 65 6F 72 27 77 60 76 7E 7B 6D 7B 7B 32 3D 42 7F 75 70 65 72 38 35 09 04 1A 1B 0B 0C 18 4D 31 2F 4F 35 36 47 14 04 08 1A 15 1C 0A 1A 0E 0E 31 1C 1E 1F 13 14 00 1C 25 25 07 3B 2A 2A 3E 6D 0B 07 0F 33 22 22 36 65 2E 22 28 3C 0A 16 1A 0E 26 3C 20 71 3A 38 27 26 8A F0 FC DB 80 8F FF E1 82 CC C6 C7 D5 C2 D0 85 E1 E8 CC D6 CE 9F D0 D2 C1 C0 E4 C3 98 97 E7 F9 AA E4 EE EF FD EA F8 D9 E3 E8 E5 A1 F6 F5 EB E3 F3 EF B8 C2 CA FE F7 F8 B2 E3 E2 FE F0 FE E0 D1 8B 9F 8D C6 BA 86 81 88 B1 8C 95 93 85 82 B0 8C 97 9E D8 90 90 DF 9A 92 80 90 95 B2 CC AB B3 9C BE A7 A9 AB E3 9D B9 A3 AC A6 B2 9D A4 B2 AD A9 BE A8 84 EB BD 87 E9 9F 9C 9F 80 8D E6 8B B7 B9 43 4E 46 5D 72 5B 49 5F 4F 4A 4E 40 4A 7B 40 40 4C 5E 54 56 4E 52 59 53 46 6F 72 44 45 5E 5A 50 79 78 44 68 77 6A 7E 51 56 71 61 65 6F 69 63 55 76 7A 6C 7F 71 6D 71 33 50 66 63 78 78 72 67 66 26 0A 11 0C 1C 33 2E 18 11 0A 0E 04 15 14 2B 07 10 1E 1B 0D 0D 23 33 0F 16 16 02 25 0F 07 11 06 16 04 3A 2D 2B 3D 18 34 32 26 6E 22 35 02 3C 35 33 29 39 2D 37 30 32 1F 27 2A 03 34 3A 3B 38 3A DE D8 FA C0 DD C4 80 8D 86 F1 C9 D2 CD 8B 84 80 9F 9B E9 CD C7 85 9C 9D E6 C1 9E C2 C2 D8 C4 8F AA AB DB C5 4C 2F E3 EB E4 F0 E5 F5 BC A7 46 25 EA E9 F1 FA FB A5 BC BD FD F5 F6 E2 F3 E3 AE B5 CA BF B8 C9 9E 9D 85 8E 87 D9 C0 C9 C6 81 8B 97 DA DB D0 B6 BD B0 D5 DD DA BF 9F 92 97 9B DD 9D A3 B8 BC A6 BC B6 9E A8 B3 B6 A5 B2 B2 97 A5 B7 BB B6 BD AD BB AD AF 9B E2 E3 E0 E1 E6 E7 84 E5 6A 0B 5C 46 0E 0F 7F 59 52 19 00 68 55 64 56 5C 4A 4F 57 17 46 52 50 6E 4B 5E 52 5E 5A 63 4D 45 6F 4D 7D 7D 7B 7D 69 7E 41 6C 6E 75 74 66 67 71 4E 62 68 7C 4C 70 73 69 41 6A 7D 73 79 7B 34 62 0B 18 48 07 01 1B 4C 0B 0D 16 0E 05 46 01 0B 17 5A 16 1D 0A 0D 1E 1B 18 52 5E 4E 51 56 04 0D 18 28 24 24 00 2A 6F 71 6D 65 22 33 32 2F 20 2A 28 3F 35 2C 2A 3B 2C 2F 34 3D 3D 38 3E 3A 3E 30 34 D3 D8 CD DA DD C6 C3 C3 E1 CC CE D5 C7 CE CA C0 C8 FF DD D5 CA DE 9C DF D3 C1 C3 F5 D3 DB C0 D4 AA FD E9 E5 FB EA AC E1 ED F7 F3 C0 E1 E0 F6 E0 FD FA EC FC FA BF D8 D2 DF D0 F1 FD F5 E2 F8 F4 9E 82 87 87 CE 8D 8D 9E 8B 90 B0 93 8F 84 81 C5 96 9E 8E 9C 92 8C DC 91 9B 9E 99 85 B8 98 80 D5 B9 BE B8 B9 A1 BD B8 A8 A6 E3 AC A4 B0 A2 A8 B6 9E 94 95 F9 BC A6 FC A9 BB BE B5 95 99 9A F4 B7 53 0B 5C 40 4D 44 5F 0D 41 4C 55 4F 52 73 4D 46 51 48 18 5A 51 4A 52 49 7A 56 59 5A 5F 59 14 74 79 63 61 45 6F 7C 78 40 63 71 6B 43 6F 63 45 76 71 56 71 7D 6E 70 75 73 66 50 2A 4D 51 7E 60 79 0B 09 45 3B 1B 01 02 08 10 3F 02 14 0F 0B 00 16 26 49 1B 21 4B 3D 32 31 22 2F 40 2D 15 1B 1D 10 24 3F 14 3D 2B 3D 21 24 2C 22 2C 1D 22 22 32 20 36 34 28 34 3B 31 28 01 10 26 23 38 38 32 27 26 E6 CA D1 CC DC F3 F8 DF C3 C7 C9 CF C1 F7 C8 C4 CE DD D7 CB D3 91 FE C8 C1 DA DE D4 C5 C4 F8 D4 F3 EE FA D5 C6 E6 FF F9 ED F1 F9 DD C7 E0 E3 F7 FF FC F9 ED F7 F0 F2 EE CE DB F9 E2 E2 F8 E6 EC AB 8C 8F 9B 8B 88 8D 99 8B 8C 8E A9 83 8E 8F 80 94 BA 8B 91 97 D1 9F 8E 81 9C 85 83 95 92 B6 80 A3 A7 AC E9 A8 BD A3 A0 8A AA B3 B5 A9 B5 BD E5 AE A2 A8 BC 92 BA AA B8 BE E1 80 A3 BF B4 B1 F5 49 43 49 47 49 4A 5F 0D 41 4C 55 4F 52 07 46 44 48 48 6A 58 50 58 59 1D 50 52 42 42 62 5E 57 5E 79 59 6D 7F 6B 7D 7F 6C 6E 4F 65 6F 61 73 6C 57 7F 6D 7D 6B 6D 7E 70 3D 5E 76 7E 76 62 7F 57 74 06 08 1D 05 0F 1B 05 02 0C 43 34 18 16 02 27 5F 26 3C 11 0D 12 1E 1E 50 20 06 1E 1F 13 05 28 17 3F 22 24 2D 3D 13 7E 2E 1A 76 02 0F 0A 17 18 75 06 38 34 30 3B 31 28 01 26 36 22 3C 3F 39 35 39 F6 CF CD DF CB C3 C3 DD CF C6 CE D5 FA E5 D1 D6 D3 D5 DD CA CD F3 DD C4 D7 C1 EC E5 C4 D6 D0 DC E4 EC D8 E5 EF FB EA E2 F0 EE AE C3 F3 F4 ED EB FF E8 EB D5 FF E6 F9 EF CE DB F9 E2 E2 F8 E6 EC B6 AA 8F 8E 9C 8A 8B 8C 96 8A 8F 8F 95 BB AC 8C 89 8F 97 8B 87 BE 9B 9A 80 96 97 90 82 9E 9B 9B 98 AE BE AC BC BC AD A1 EC A0 B3 83 AF A3 E4 84 A9 B0 9A B0 BA 9E AF B6 93 B4 B7 A3 B3 B0 B5 A1 4F 4F 08 5D 47 4C 47 5E 02 0B 6C 40 55 53 0D 71 53 56 5D 7D 5B 53 5D 44 66 5A 5D 54 1A 17 59 46 49 31 54 4E 67 7B 60 6C 60 2E 52 74 68 69 61 77 46 79 6D 70 72 7B 6F 41 20 70 48 24 54 59 58 45 36 5B 34 0A 02 06 09 03 16 3F 14 04 14 0A 0D 0B 1B 17 24 1D 1B 09 19 11 1D 03 1D 14 18 03 28 37 3F 38 21 27 2B 3C 3F 01 23 3A 25 33 1A 13 36 24 3E 32 36 3E 0E 33 3D 29 34 3C 22 3C 78 15 21 26 C3 C5 CD DA DD E3 CD D4 C7 D1 FC E9 CF D4 D0 CA C8 C2 E4 F8 D9 D8 CE D8 D5 D2 C4 D8 D9 D9 C7 E9 C2 E2 FB FD E1 FD F5 CC E5 E4 F2 E4 E1 E6 F0 EC F5 F5 CC F0 FD F4 D0 FC E1 E7 D1 F6 F1 E5 F1 F2 8B 9F 8D 8D C0 8C 9F B9 8B 8E 85 B5 8F 8A 81 C5 89 8F 99 8D 97 8C 88 94 91 80 A6 9E 9A 82 99 90 EA BB BA A6 A8 A6 A0 A8 94 AC AC B4 AB A2 E4 B3 BB B7 AD BC 88 88 9D 8D 9B BD A6 B0 BA BE B0 F5 7E 43 41 5A 0E 67 45 5E 56 4C 52 48 45 46 48 61 5B 4F 59 7A 4B 4C 48 52 5F 13 59 42 16 56 40 41 6B 68 60 6C 6A 2F 78 62 22 6A 6E 65 6F 64 65 71 75 69 38 3B 3C 31 3C 4B 73 7F 65 74 65 37 77 7A 1F 05 1C 49 19 06 00 01 42 01 05 41 15 1E 0A 06 12 09 17 17 17 05 19 19 52 04 19 05 1E 57 1D 1B 2E 22 2B 28 3A 20 3E 2D 31 63 23 2E 33 29 30 6B 7A 18 39 35 32 7F 0F 38 26 05 31 3D 23 32 74 3C C4 D8 DC CC CF CB 80 8D CD D1 80 C2 D4 C2 C5 D1 DF 9B D6 DC C9 9F 9C CA DB C7 D8 DE C3 C3 94 D4 FE FF E9 EA E6 E6 E2 EA A2 F7 EF A1 EF E9 E0 EC F9 FA EC F6 EC D6 F2 FE FD E1 E2 F4 F5 E3 B4 FA 8C 8D 9B 8C 9A CF B8 84 81 88 93 C1 DB C7 C4 BE A7 DB B7 D9 D3 DF DC B5 D2 DE D0 D1 BA D7 D9 D5 EA 88 E8 E4 EE 8B A3 BA AC 96 B0 E1 BA E7 88 A4 A9 AF F8 E4 FE FF A0 FD 84 BC BC A4 BB B2 F4 E8 0A 6F 49 50 6C 4E 5E 6C 51 48 73 48 5C 42 66 4C 5E 68 51 43 5B 73 5D 4E 46 60 59 4B 53 78 44 50 64 43 61 6E 66 43 63 7A 52 71 65 77 6F 68 71 76 59 77 77 6A 7B 4B 6E 7C 76 76 63 40 63 78 60 70 2B 18 1B 0C 1A 39 03 01 17 0E 05 20 15 0C 44 27 13 1F 58 55 5E 2C 15 07 17 49 50 5D 56 3E 10 4F 6A 67 68 0A 22 20 3F 28 26 79 60 6D 66 05 2D 21 60 7B 74 79 1F 2C 37 67 72 7F 70 13 3F 33 07 3C D0 CE 92 89 82 8F ED DE C9 F0 C9 DB C3 9D 84 E1 DB CF D9 99 CD DA CE D4 D7 C0 90 92 CD 87 C9 F6 B0 D7 CF E0 FA E3 ED EF AF D1 F5 EF E8 E2 F6 D9 F8 EE F1 F5 FA EC C0 AF F1 CB A5 D3 D8 DB C4 C9 DA B7 8B 85 87 8A 82 99 BE 97 85 93 8B 8E 8A 84 96 A7 9C 9C 88 9A 90 92 82 9E 95 9F 82 AB B6 80 B9 A2 A6 AC BD BC 80 AC BB A6 B2 9D 92 B5 A5 A1 B3 B5 BF 89 B2 BE A8 BB BD A1 BD FF 94 A2 A7 BC 44 4E 5B 5A 62 4E 55 48 50 7F 6D 4E 42 52 48 40 49 67 71 57 5A 56 5F 5C 46 5C 42 42 6A 7E 5A 51 63 68 69 7D 61 7D 22 6E 71 4F 69 6F 63 58 23 7E 2A 66 3F 39 7A 7E 68 7C 32 60 75 63 7F 72 67 35 1A 19 07 19 0B 1D 18 04 07 10 2C 04 10 02 08 45 1E 1A 0C 18 5E 0C 19 0F 1B 16 03 51 55 0C 44 08 06 2E 3E 2C 22 10 03 23 62 37 29 22 2D 08 2A 65 38 3A 2A 79 3D 33 33 2E 37 06 20 35 37 23 31 01 D3 DB CD C5 C7 C1 C9 FE C7 D1 C9 C4 D5 CB CD CB DF F7 DD CF DB D3 F5 D3 D6 DA D3 D0 C2 D8 C6 95 EB E7 FA EC EF EB F5 AD E3 E7 E4 E4 E2 EB ED EB FF D2 F6 FD FB E7 F4 F4 E1 E7 FF E3 FF F4 F5 F9 AE 8A 9C 88 D4 CF A3 83 AB 8D 89 95 DC C7 AB 8B AF 8B 9C 98 8A 9A C6 DD BD 9D B3 9D 93 96 86 CF EA 84 A6 9D BC B6 8B A8 B6 8E A9 AF 8B A6 BC A6 AF A8 AC B6 B3 97 B5 AE A6 BC A2 B8 B5 B6 B8 91 4B 5F 49 6A 5B 5C 58 42 4F 03 48 48 55 53 4B 57 53 58 59 55 1E 5B 5D 49 53 13 51 5D 44 52 55 51 73 2B 69 6D 6A 6A 68 59 6B 6E 65 21 75 6F 6D 63 6E 48 70 76 69 3F 70 74 7C 76 30 7C 77 65 7F 70 18 27 01 07 0B 3C 09 1F 0B 06 13 28 02 08 02 03 09 1E 0C 10 10 0C 08 1C 1C 10 15 3F 17 1A 11 3C 24 38 3C 28 20 2C 29 6D 2C 22 2D 24 05 7D 18 02 33 2F 34 38 3C 72 0E 28 3C 3D 35 23 0A 35 21 3C C6 CF DB F5 9C CC F4 98 E0 ED EC F1 FA 97 F8 C6 D6 D2 DD D7 CA E3 C8 D8 C0 DE D9 DF D7 DB E8 D1 EF FD ED E5 E1 FF E1 E8 EC F7 DC C3 F3 F4 ED EB FF E8 EB D5 FF E6 F9 EF CE C7 E2 F0 F2 FE FA F2 BA 87 89 9D 88 80 9E 80 CC A1 95 92 8F 89 81 96 89 B7 99 80 9B 8D A0 B0 9D 97 85 9D 93 84 A8 A6 BE B9 A9 BD AB A8 A5 A8 B1 9F 93 B5 B4 A6 B0 A0 BD A2 F6 BA AD 98 B9 B3 B7 A1 B1 BD 95 B6 BA F2 5E 0B 4B 41 4F 41 4B 48 02 50 54 53 47 53 41 42 43 1B 4B 5C 4A 4B 55 53 55 40 10 46 5E 5E 58 50 2A 78 7C 7B 6F 7B 69 6A 7B 23 73 75 67 73 61 25 73 68 38 6E 71 6D 77 74 7C 74 7C 7E 71 64 47 61 18 0A 1C 0C 09 16 5D 43 52 22 0E 41 03 1F 07 00 0A 0F 11 16 10 5F 14 1C 01 53 1F 12 15 02 06 07 2F 2F 68 3E 26 26 20 28 62 30 34 33 27 33 21 22 23 7B 3B 2B 3B 3E 28 34 3C 34 7E 71 13 2F 37 30 DA DF C1 C6 C0 95 8C 97 82 EC CE E8 C8 CE D0 CC DB D7 D1 C3 DB F2 D9 C9 C0 DA D3 C2 E5 C3 C6 D4 FE EE EF F0 AE F8 ED FE A2 E0 F2 E4 E7 F3 E1 E1 B4 B5 B6 A3 BE D0 F2 DE E0 F6 F1 E5 F3 F3 C7 E1 98 8A 9C 8C 89 96 CC 9E 96 82 92 95 83 83 CA CB D4 BA 96 D9 9B 87 9F 98 82 87 99 9E 98 D7 9C 94 B9 EB A7 AA AD BA BE BF A7 A7 E0 B6 AE AE A8 A0 FA A8 AC AB BF AB B9 BA AB F3 A2 A4 B8 B9 BD BB 4D 05 08 6C 56 4C 49 5D 56 4A 4F 4F 1C 07 1E 05 68 4E 56 6A 4A 4D 5D 49 57 54 49 11 41 56 47 15 79 7F 67 79 7E 6A 68 23 2C 2D 41 6F 26 62 7C 66 7F 6B 6C 70 71 71 3C 75 73 60 30 7E 75 74 61 67 18 0E 0C 49 19 07 05 01 07 43 13 15 14 06 10 00 1D 02 58 0A 0A 10 0C 0D 1B 1D 17 5F 56 32 0C 16 2F 3B 3C 20 21 21 76 6D 78 63 13 35 29 37 05 2B 7A 3E 20 3A 3B 2F 28 34 3D 3D 70 39 37 24 74 3A C9 C8 DD DB DC CA C8 8D D5 CB C9 CD C3 87 D7 D1 C8 DA CC DC D9 C6 9C D9 D3 C7 D1 91 D2 D2 D8 D0 FE E2 E6 EE A0 AF C9 F5 E1 E6 F0 F5 EF E8 EA BF BA A1 B8 CB FB F2 F3 EB F7 C0 E4 E3 F7 E3 F1 F2 93 CB 9F 88 9D CF 9E 88 8F 8C 96 84 82 C9 CA CB BB 95 D8 9C 86 9C 99 8D 86 9A 9F 9F D6 9F 95 86 EA A4 AB AA BB BD BE A8 A6 E3 B7 A9 AF AB A1 E5 A9 AF AA B8 AA BA BB A4 F2 A1 B5 BC B9 A1 BD BB 4D 05 08 6C 56 4C 49 5D 56 4A 4F 4F 1C 07 1E 05 7D 5E 4C 74 5B 4B 4E 54 51 40 62 44 58 17 70 54 7E 6E 27 5D 67 62 69 5A 6D 71 6B 68 68 60 24 71 73 76 7D 4A 6A 7E 68 78 32 5C 62 75 73 65 2E 35 4A 04 1A 0D 0B 1D 4C 0E 03 0D 03 04 0A 47 16 00 0B 0E 1D 0A 0A 3C 1D 13 11 16 1C 51 19 05 10 10 38 6B 0B 26 20 21 29 2E 36 2A 2F 2F 7C 67 05 26 39 34 2D 37 2A 65 7C 0C 27 32 3E 25 3F 23 2D 6F 8A E4 DA CD CB DD 8C E4 E6 99 80 F2 CF C3 C1 9F 9A F4 CA DD DB CD 9C C9 CB C3 D5 8B 96 E3 C6 DC ED EC ED FB AE FF FE E4 E1 E6 BA A1 D2 F5 E5 EC F6 F2 F6 FE BE F0 FA FB E1 F6 E4 AB B6 C4 E0 FA 9A CB 84 86 9D 9C D6 CD B6 82 8B 84 C6 97 96 8A 9C 92 8C C3 DE BB 9D 89 97 DC A4 98 9B 92 CE D5 99 A4 BD BB AD AA F6 ED 90 A6 B1 B4 A3 B4 B0 8C BE E1 F8 F9 9D B3 B3 AE B7 F3 A1 A5 AF ED F4 85 45 58 41 5D 47 40 42 0D 41 4F 4F 52 43 07 56 40 4B 4E 5D 4A 4A 6F 53 4E 5B 47 59 5E 58 17 7D 71 30 2B 44 60 60 64 2C 42 41 4C 20 73 63 76 71 60 69 6F 54 70 70 74 3C 52 51 5C 3E 31 44 72 65 60 0F 18 1C 20 0A 55 4C 22 10 07 05 13 34 02 15 10 1F 08 0C 29 1F 0D 1D 10 17 07 15 03 05 26 01 14 24 3F 21 3D 37 0B 29 2B 2B 2D 29 35 2F 28 2A 16 3F 2F 2C 30 30 38 12 3C 3F 36 03 3D 3F 27 24 34 CD CE FB DD C1 DF E0 C2 D1 D0 E9 D5 C3 CA D7 F1 DB D0 DD E9 CC D0 DA D4 C6 FA C4 D4 DB C4 F5 D1 EE E2 FC E0 E1 E1 ED E1 D2 E2 F2 E0 EB E2 F0 E0 E8 E8 D7 EB FA FA EE EE B2 F4 E2 FE E3 E7 B4 E5 86 8A 8B 80 80 88 CC 9F 87 92 95 84 95 93 AB 97 9E 9E 8A 8A DE 98 8E 92 87 83 DE D1 A4 92 85 80 AF B8 BC 80 AA F5 EC 99 A7 BB B4 92 A3 B3 B0 AC B4 BC 91 AD BB B2 9D BE B1 BC A5 BF A2 84 B1 A1 5E 42 46 4E 67 5B 49 40 60 4C 4F 4D 43 46 4A 76 5F 4F 4C 50 50 58 75 49 57 5E 79 5F 42 52 53 50 78 58 6D 7D 7A 66 62 6A 4B 77 65 6C 44 68 6B 69 7F 7A 76 4A 69 76 68 7E 7A 76 62 42 73 63 60 7C 04 0C 21 1D 0B 02 38 04 0F 06 3A 0E 08 02 29 04 14 1A 1F 1C 0C 2C 19 09 06 1A 1E 16 3F 03 11 18 1E 22 25 2C 08 3D 2D 20 27 00 2F 2F 20 2E 23 16 3F 2F 2C 30 30 38 15 29 37 3E 14 30 22 32 00 3C C7 CE FB CC DA DB C5 C3 C5 EA D4 C4 CB F7 C5 D6 C9 CC D7 CB DA EC D9 C9 C6 DA DE D6 FF C3 D1 D8 D9 EE E4 EC ED FB E3 FF D1 E6 F4 F5 EF E9 E3 CC EE FE F5 CD F7 F2 F9 C7 FD FD F5 C2 F3 E3 E0 FC 84 8C A1 9D 8B 82 B8 88 9A 97 A1 93 83 86 B7 80 8E 8F 91 97 99 B6 88 98 9F A0 89 9C 94 98 98 A6 AF BF BC A0 A0 A8 85 B9 A7 AE 90 A4 B4 AE AB A1 89 BE AC AD B7 B1 BB 94 A6 B6 BD 82 A2 A5 BD BB 4D 78 4D 5D 5A 46 42 4A 6B 57 45 4C 67 44 50 4C 55 55 6B 5C 4A 4B 55 53 55 5A 44 54 5B 67 5B 5C 64 7F 7B 5A 6B 7B 78 64 6C 64 49 75 63 6A 40 6A 6F 79 74 7C 4D 7A 68 69 7B 7D 77 58 62 72 79 46 06 02 0C 0C 1C 3C 09 19 16 0A 0E 06 2F 13 01 08 29 1E 14 1C 1D 0B 13 0F 3E 1C 13 10 1A 1E 0E 10 2E 18 2D 3D 3A 26 22 2A 0B 37 25 2C 00 2E 28 20 09 3E 2C 2D 37 31 3B 14 26 36 3D 17 39 39 20 06 CF DF DC C0 C0 C8 E5 D9 C7 CE EC CE C8 C0 F7 C0 CE CF D1 D7 D9 F6 C8 D8 DF F4 C2 DE C3 C7 E7 D0 FE FF E1 E7 E9 C6 F8 E8 EF C0 EF ED E9 F5 D7 E0 EE EF F1 F7 F9 D6 E8 F8 FF C0 FF E4 F8 F3 C7 F0 9E 9F 81 87 89 A6 98 88 8F A2 8C 84 94 93 B7 80 8E 8F 91 97 99 B6 88 98 9F BC B1 84 82 9F A7 90 BE BF A1 A7 A9 86 B8 A8 AF 91 A1 A5 AF A8 88 AA B9 BA B4 B0 A4 BA B8 8E B7 A7 A4 B8 B8 B0 9D A1 4F 46 6C 46 5B 4D 40 48 75 4A 54 49 6A 4E 4A 4E 69 5E 4C 4D 57 51 5B 74 46 56 5D 63 45 44 67 50 7E 7F 61 67 69 46 78 68 6F 42 6C 68 61 69 69 60 74 6F 4B 7C 6A 6B 75 73 75 5A 64 74 7B 47 75 7C 18 28 07 05 01 1D 3F 08 16 17 09 0F 01 2E 10 00 17 38 17 17 1A 16 08 14 1D 1D 23 14 02 03 1D 1B 2D 02 3C 2C 23 03 25 23 27 0C 30 35 2F 28 2A 36 09 3E 2C 2D 37 31 3B 14 26 36 3D 13 3F 30 00 30 D2 DF E9 DB CB CE FF C8 D6 D7 C9 CF C1 EE D0 C0 D7 FD D1 DB D1 D1 DD DE D1 DA FC D4 C0 D2 D8 FA FA FF E1 E6 E0 FC DF E8 F6 F7 E9 EF E1 CE F0 E0 F7 D6 F1 F7 F1 EB FD E8 E0 FC D6 F8 F4 F8 FA F4 89 88 81 A5 8B 99 89 81 AD 93 94 88 89 89 97 B6 9F 8F 8C 90 90 98 B5 89 97 9E A2 90 98 90 91 A6 AF A7 AD AA BA A0 BE 9E A7 B7 B4 A8 A8 A0 8D B1 BF B6 9A B6 B1 B3 B9 BC BC 9F BF B2 B7 BB BD AF 4F 4F 7B 4C 5A 5B 45 43 45 6A 54 44 4B 64 48 50 49 4F 5D 4B 7D 50 50 52 40 5A 5E 56 7A 52 42 50 66 58 6D 7D 7A 66 62 6A 4B 77 65 6C 49 75 60 60 68 49 7D 68 6B 7A 6F 69 42 72 62 70 7B 72 60 70 18 18 3B 0C 1A 1B 05 03 05 2A 14 04 0B 2E 07 0A 14 1E 1C 38 1D 0B 15 12 1C 53 26 10 1A 02 11 4F 6A 22 3B 1D 2B 22 3C 22 30 22 32 38 04 26 36 16 32 34 2F 1C 26 2B 39 33 21 3A 3F 3F 05 3F 3B 22 EF D3 DC CC C0 DC C5 C2 CC EF C9 CF C3 F4 CC CA CD F9 D9 CA DB F3 D9 CB D7 DF F5 C9 C2 D2 DA C6 E3 E4 E6 C5 EB F9 E9 E1 C7 FB F4 E4 E8 F4 ED EA F4 D9 F9 FA F5 DC F3 F1 FD E1 D5 E9 E2 F2 FA E6 83 84 86 AB 81 9D 88 88 90 A0 8F 8D 89 95 A1 9D 8E 9E 96 8A 97 90 92 B1 93 91 95 9D B4 96 87 90 86 AE BE AC A2 9B A9 B5 B6 8F AF A2 A7 AB 97 B1 B5 A9 B9 BE BB AC 89 AE B7 A1 84 A3 B7 B3 B1 A6 69 4A 46 0E 5A 0F 4A 44 4C 47 00 40 48 5E 04 56 4E 54 4A 58 59 5A 7F 5C 5C 14 44 11 55 45 51 54 7E 6E 28 7A 7A 60 7E 6C 65 66 20 6E 60 27 70 7C 6A 7E 22 39 51 6D 78 78 60 60 58 78 65 63 7B 67 13 28 1D 1A 1A 00 01 4D 11 17 12 08 08 00 27 0A 14 1F 11 0D 17 10 12 32 02 16 02 10 18 13 37 00 39 3F 27 24 6E 2B 2D 39 27 15 21 2D 33 22 10 3C 2A 3E 1B 2C 2D 2B 33 30 72 20 29 3C 34 38 38 16 DF D8 DC C6 C3 8F CD CE C1 CC D5 CF D2 E4 D1 D6 CE D4 D5 99 CD DA D0 D8 D1 C7 DF C3 E5 D2 D8 D0 E9 FF ED ED C7 FB E9 E0 CD F1 E4 E4 F4 A7 F4 E9 FB F8 F1 F7 F9 BF EF E9 E0 F2 E4 F4 F1 EE B4 E2 98 84 86 8E CE 8C 99 9F 90 86 8E 95 C6 94 90 84 8E 9E AB 8D 8C 9E 88 98 95 8A D0 97 9F 99 9D 86 A2 AE AC F2 E7 EF EC AC B6 E3 A6 AE B4 E7 8D 8B 89 8F 8A 8C 93 9A 92 89 81 8C 83 94 9A 92 97 81 63 64 66 76 67 6B 78 44 4F 46 4F 54 52 07 4B 43 1A 4C 59 50 4A 56 52 5A 12 52 53 52 53 44 47 15 7E 64 63 6C 60 43 63 6E 63 6F 53 75 69 75 65 62 7F 68 44 4F 71 73 69 70 77 52 7E 70 7A 6E 67 7C 19 3B 1A 06 0A 1A 0F 19 2B 27 31 14 09 13 0D 0B 1D 38 0D 0B 0C 1A 12 1E 0B 3A 34 20 03 18 00 10 0E 2E 24 28 37 1E 39 22 36 2A 2E 26 12 3E 34 20 16 34 2C 0A 37 25 39 13 3D 27 39 3E 38 36 38 03 CB C7 DD CC FD DB C9 DD EA CA D3 D5 C9 D5 DD F1 C3 CB DD EF D1 D3 C9 D0 D7 E7 C9 C1 D3 F3 D1 D9 FE EA CB E8 E2 EC F9 E1 E3 F7 E9 EE E8 D3 FD F5 FF D6 F1 F7 C8 F0 F0 E8 FF F6 D1 FF F7 FB ED E6 83 98 BC 80 8D 84 BF 84 98 86 A1 8D 8A 88 93 A6 9B 97 9B 8C 92 9E 88 98 A0 96 91 9D 82 9E 99 90 9E A2 AB A2 BD 8E A0 A1 AD B4 83 A0 AA A4 B1 A9 BB AF BD 8B BB BE B0 A9 BB BE B5 85 A4 B6 B0 B0 59 6A 44 45 41 58 6F 4C 4E 40 55 4D 47 53 41 77 5F 5A 54 4D 57 52 59 6B 5D 5F 45 5C 53 76 58 59 65 7C 4B 68 62 6C 79 61 63 77 65 53 63 66 68 71 73 76 7D 5A 76 7E 72 7A 77 52 7C 7D 79 60 55 77 08 19 0D 1F 07 0E 18 08 32 11 09 02 03 25 1D 31 13 18 13 2A 17 05 19 30 13 07 05 03 1F 03 0D 31 2B 3F 2D 0F 3B 3B 39 3F 27 00 2F 2F 32 35 25 26 2E 0F 21 29 3B 16 32 2E 26 21 25 3C 33 39 20 14 CE CF C1 DD C7 C0 C2 CC CE EA CE C7 C9 E8 C2 C3 97 FE C0 DA D6 DE D2 DA D7 E5 D5 DF D2 D8 C6 95 E2 EA FB A9 E0 E0 F8 AD F1 F6 F0 F1 E9 F5 F0 DC F5 EE EA B9 F2 F6 FF F8 FC E0 F5 B1 F2 F8 F1 E6 CA 85 87 9D CE 8E 80 81 8D 94 C0 95 8E 8E 97 C5 99 94 96 97 9B 9C 88 94 9D 9D A5 82 93 85 B0 90 A7 A4 9A AC AF A3 80 A2 A1 A2 AC 92 B2 A8 B6 A4 BD BE AB 85 96 B6 AF A9 BD A1 A9 81 B9 A4 9D B1 10 0B 04 09 69 5D 43 58 52 6A 44 1B 06 0B 04 66 55 56 55 5C 50 4B 06 1D 62 41 10 0C 16 63 46 1B 7A 79 28 34 2E 5B 7E 23 6D 65 66 72 63 73 24 38 3A 58 6D 6A 6A 70 71 5E 41 47 5C 5C 42 54 2E 49 2D 02 1C 05 0F 0D 41 3F 17 0D 0E 04 14 3B 06 10 13 17 1C 0A 22 4D 1F 25 47 31 3E 3D 26 2B 44 29 29 27 21 2C 20 3B 10 39 27 31 2D 28 28 26 28 19 3E 3E 2E 3C 32 30 2C 30 37 3D 24 0D 14 22 27 3C C4 CE DB DA E2 CE D5 C8 D0 FF F4 D3 C7 C3 CD CB DD EB D4 D8 CA D9 D3 CF DF 9D F2 C4 C5 DE DA D0 F9 F8 C4 E8 F7 EA FE D1 C0 F6 F3 E8 E8 E2 F7 F6 D5 F9 F2 FC FD EB EF C1 DD E1 F4 F4 E4 C3 ED E5 8F 98 B4 A5 87 82 85 99 AD 91 84 84 94 B3 9D 95 9F D5 9B 8A DE DF B1 92 96 9A 96 88 D6 98 86 91 AF B9 E8 EA 9D BB A3 BD E2 AF AF B2 B5 E7 B4 B7 B3 B8 BD F9 AD B7 B3 A8 BE B7 F0 B3 B3 F7 B8 B0 59 58 08 5D 46 4E 42 0D 4E 4A 4D 48 52 07 54 57 53 58 5D 6D 5F 54 59 1D 42 41 5F 57 5F 43 14 45 78 62 6B 6C 2E 7C 64 62 77 6F 64 21 64 62 24 68 75 69 7D 39 6A 77 7D 73 32 7F 79 7C 7F 63 34 65 18 02 0B 0C 3D 1B 03 1D 42 0F 0F 12 15 47 14 17 13 18 1D 59 0D 17 13 08 1E 17 50 13 13 57 19 1A 38 2E 68 3D 26 2E 22 6D 2E 2A 2D 28 32 67 34 37 33 38 3D 0D 3F 34 39 7D 22 21 3F 37 3F 23 74 25 D8 C2 CB CC 8E DC C4 C2 D7 CF C4 81 C4 C2 84 C9 DF C8 CB 99 CA D7 DD D3 92 DF D9 DC DF C3 94 C5 F8 E2 EB EC C3 C4 D8 DE F6 EC F0 A1 EA E8 F7 F6 BA EB EA F0 FD FA BC EE FA FC E5 FD F2 B7 F6 F0 CA 87 8D 9A 9D CF 98 85 83 8D C0 8C 87 95 8F 80 8E DB 99 8A 95 DF 8C 8F 9B 90 95 B2 CC AB B3 9C BE A7 A9 AB E3 9D B9 A3 AC A6 B2 9D A4 B2 AD A9 BE A8 84 EB BD 87 E9 9F 9C 9F 80 8D E6 8B B7 B9 43 4E 46 5D 72 5B 49 5F 4F 4A 4E 40 4A 7B 40 40 4C 5E 54 56 4E 52 59 53 46 6F 72 44 45 5E 5A 50 79 78 44 68 77 6A 7E 51 56 71 61 65 6F 69 63 55 76 7A 6C 7F 71 6D 71 33 50 66 63 78 78 72 67 66 26 0A 11 0C 1C 33 2E 18 11 0A 0E 04 15 14 2B 07 10 1E 1B 0D 0D 23 33 0F 16 16 02 25 0F 07 11 06 16 06 29 3B 25 2A 38 02 30 27 25 33 12 3E 34 20 74 38 2B 0D 3F 34 39 7D 22 21 3F 37 3F 23 74 25 D8 C2 CB CC 8E DC C4 C2 D7 CF C4 81 C4 C2 84 C8 D5 C9 DD 99 CA D7 DD D3 92 DE D1 C3 DD D2 C0 95 EB F8 E3 A9 FE FD E5 EE E7 D0 F4 EE F6 A7 E8 EA E9 E8 B8 E9 EC F6 FF F8 B2 E0 F8 FE E3 FB F0 B5 88 8E C8 84 81 9D 89 CD 96 8B 81 8F C6 8A 85 97 91 9E 8C D9 9C 96 98 DD 82 81 99 92 93 A3 95 9E AF EB B8 BB A1 A9 A5 B9 E2 B3 B2 A8 A5 A2 E4 B6 B2 B4 AD B5 BA FF BE B8 F2 BF B5 A2 A5 F7 A0 BD 4B 45 08 44 4F 5D 47 48 56 03 42 48 42 07 54 57 53 58 5D 6A 6A 6F 68 4F 5B 54 57 54 44 17 44 47 63 68 6D 4A 34 53 4B 64 76 6F 61 63 2B 55 71 6B 74 7E 6A 45 7C 6A 75 71 76 60 4C 23 75 4F 21 57 24 27 38 35 5E 33 0F 01 0B 06 0E 15 3A 13 01 17 17 12 16 18 12 23 18 18 04 16 1C 1E 06 1A 11 1B 3E 17 0A 3C 3D 26 22 28 31 30 0C 20 3F 22 36 19 0E 29 39 3D 37 31 3B 0D 3E 32 24 37 39 25 39 7B E8 DE DB C0 C0 CA DF DE EE C2 D9 C4 D4 FB E6 D0 C9 D2 D6 DC CD CC F3 DF D8 D6 D3 C5 C5 EB FB C7 EE EE FA DD F7 FF E9 FE DE D0 F4 EE F6 C8 F6 E1 FF E9 CC E0 EE FA B2 FE E1 C0 E4 FE E6 B7 F8 FA 99 98 C8 99 9C 86 8F 88 C2 90 88 8E 93 8B 80 C5 98 9E D8 95 9B 8C 8F DD 86 9B 91 9F D6 83 86 9C AD AC AD BB EE BF BE A4 A1 A6 94 A0 AD A2 E4 B5 A8 B4 BE B0 AA FF AC AF BB B0 B5 F1 A5 BF BB A0 46 4F 08 4B 4B 0F 41 42 50 46 00 55 4E 46 4A 05 4E 49 51 5E 59 5A 4E 1D 42 41 59 52 53 64 40 5A 7A 2B 64 66 7D 7C 2C 7D 70 6A 63 64 26 74 6C 6A 6F 77 7C 39 7C 7A 3C 70 7D 61 75 31 62 7F 75 7B 4A 1F 1A 00 09 08 09 1F 42 13 12 08 05 02 30 04 11 1E 58 09 0C 10 1A 14 06 53 00 03 1F 14 11 55 39 23 27 3C 22 2B 6C 2F 27 63 2C 24 35 34 64 31 32 3A 36 79 2A 2D 35 3A 35 36 22 71 26 25 3D 36 CF FF DA C8 C7 C3 C5 C3 C5 83 F3 D5 C9 D7 F0 D7 97 E8 EC CB DF D6 D0 D4 DC D4 90 DE D0 D1 C7 D0 FE C8 B2 D5 C9 E6 F8 E1 E3 E1 AD D3 F3 E9 EA E0 E8 C7 FA EC F7 F3 F8 EE CE A1 F3 C9 A3 D5 DA D9 BA B7 D8 B5 8D 83 85 88 8C 97 BC 95 83 95 89 8C 94 9A 94 A5 9A 9A 8A 98 9E 9C 80 9C 93 99 80 A9 88 BE BB A0 A0 AA BF BE 8E A2 B9 A4 B4 9B 90 B7 BB BF B1 B7 B9 8F B0 BC A6 B5 BF A3 BB F9 96 A0 59 42 46 4C 5D 5C 60 4C 5B 46 52 7D 64 52 57 4C 54 5E 4B 4A 71 5D 56 58 51 47 43 6D 79 45 50 50 78 5F 71 79 6B 7C 50 59 70 62 69 6D 6F 69 63 56 6E 74 68 56 6C 7B 79 6F 46 6A 60 74 38 74 67 3C 43 45 48 20 0A 4F 51 4D 29 02 07 08 2D 00 48 45 36 12 16 1C 5E 3D 0E 18 13 18 3C 18 18 12 54 17 38 2E 29 22 6E 23 25 23 27 30 6C 61 16 28 2D 2B 2E 28 78 7F 7E 19 35 3A 27 21 35 22 15 6D 08 12 C3 DF C4 C8 CC 82 FE D8 CC CD C5 D3 FA C5 D1 CC D6 DF CB E5 8C DC E4 88 F0 FD FC E1 EA 87 E8 D6 E6 E2 ED E7 FA D3 F8 E8 F0 EE E9 EF E7 EB D8 E1 FF ED FD F5 F1 EF F1 F8 FC E7 CC D3 E3 E4 FD FB 8F 98 9B A5 8F 96 89 9F BE B7 92 80 82 8E 8A 82 AA 97 99 8D 98 90 8E 90 DC B1 85 82 9F 99 91 86 B9 87 A9 B0 AB BD 90 85 AB B0 B4 AE B4 BE 98 84 BD BC AA BC B9 BE A8 B4 BD BD A3 8D 9E BE A7 A1 45 59 51 68 49 48 5E 48 45 42 54 48 49 49 74 4A 53 55 4C 4A 7F 51 58 7B 5B 54 45 43 53 44 1A 56 79 49 67 71 5D 66 76 68 40 6C 78 21 75 6E 7E 60 4A 3D 5E 39 33 3F 36 55 5E 50 42 74 78 7C 7B 5D 03 0C 00 46 22 00 1B 2C 06 15 4E 41 25 0B 05 16 09 12 1B 38 1A 09 52 5D 3A 1A 17 19 59 3B 1B 02 08 39 21 2A 25 6F 3F 24 38 26 01 26 21 35 21 22 3B 2F 31 36 30 7F 2F 29 2B 3F 35 14 2E 23 31 3B D9 C2 C7 C7 82 8F 89 E4 CC D5 C5 D3 D5 CE CB CB 96 9B 9D EA D6 D0 CB 9D C5 DA D3 DA C5 F5 C1 DC E6 EF A8 EA FB FD FE E8 EC F7 A0 E3 E7 F5 C5 C6 DB D3 D4 BF C9 DD F9 FA FB FD AA B1 B6 EB B4 D0 84 8F D2 C9 CE 80 9E 89 87 91 C0 8C 89 83 8D 83 83 DB 8A 9C 8F 8A 99 8E 86 D3 9F 83 92 92 86 D5 BA A7 A9 AA A7 A1 AB ED B0 A6 B1 B4 A3 B4 B0 87 BB A8 BD 94 BF A7 88 AF B3 B7 B9 BF B1 86 A1 B4 44 5F 41 5D 57 7E 59 42 56 4A 4E 46 6B 46 5C 71 48 5A 5C 50 50 58 6D 48 53 5D 44 58 42 4E 75 47 68 62 7C 7B 6F 68 69 5E 7B 6E 62 6E 6A 74 47 6D 7F 78 73 7C 7A 5E 70 71 7D 64 54 78 65 76 76 79 0F 28 07 05 01 1D 2A 02 10 0E 01 15 2D 0E 0A 01 0F 0F 1B 3F 17 1D 13 13 13 10 13 18 3A 12 02 10 26 38 0A 28 3D 2A 1C 28 30 2A 2F 25 66 24 2B 2B 2E 3A 31 37 2D 7F 35 33 72 16 28 32 3A 22 30 30 CE F8 DC D0 C2 CA DF E0 C3 DB C9 CC D3 CA E9 CC D4 D2 D5 CC D3 F6 D2 DE C0 D6 DD D4 D8 C3 F0 DC E7 EE E6 FA E7 E0 E2 CC EE EF EF F6 C2 EE F7 E4 F8 F7 FD DA F1 F3 F3 EF A3 D2 FC FD F9 E0 D0 FC 99 8A 8A 85 8B AC 83 81 8D 91 D2 B1 83 95 8D 8A 9E B6 8D 95 8A 96 8C 91 9B 96 82 D1 9F 84 D4 99 AF B8 BB E9 BA A7 AD A3 E2 8E B5 AD B2 AE B4 A9 B3 BE AA 94 B7 B1 B5 B0 A7 BE F0 B8 A5 F7 B9 BA 58 4E 08 5D 46 4E 42 0D 6F 56 4C 55 4F 57 48 4C 5F 49 75 58 46 56 51 48 5F 71 51 42 53 67 51 47 63 64 6C 29 6D 60 62 79 63 6A 6E 72 26 6E 6A 25 5F 63 7B 75 6B 7B 79 79 42 76 62 78 79 73 67 45 04 07 29 05 0B 1D 18 1E 21 0C 0E 15 07 0E 0A 00 08 2B 16 15 3F 13 19 0F 06 27 11 03 11 12 00 23 2B 27 3D 2C 18 2E 20 38 27 30 16 20 2A 32 21 0C 2E 3E 35 2A 08 3E 30 28 37 1A 24 34 3B 1E 20 30 C7 D8 FB DD CB DF DF EE CD D6 CE D5 E3 C9 C5 C7 D6 DE EB D6 CB D1 D8 CE E6 DA DD D4 FF D9 E0 C7 EB EF ED CA E1 E1 F8 EC EB ED E5 F3 D2 EE E9 E0 D3 F5 CC EB FF FB F9 C9 FB FE F5 D8 F8 C4 F1 F6 85 85 8C 9A BE A3 A8 84 90 86 83 95 8F 88 8A B1 93 96 9D A3 91 91 99 B4 9C 95 9F B8 92 B5 95 86 AF 9E BC AA 81 A9 AA BE A7 B7 84 A8 B5 B7 A8 A4 A3 95 B9 B4 BB 8C A8 BC BC B7 B1 A3 B2 93 BD A6 5A 47 49 50 60 4E 41 48 71 42 56 44 06 55 41 44 56 4F 51 54 5B 1F 48 4F 53 57 55 11 41 5E 40 5D 2A 78 7C 7B 6F 61 6B 68 22 77 69 6C 63 3D 24 51 68 7A 7C 7C 57 7B 3C 20 32 33 44 78 7B 72 34 28 4A 12 11 10 17 42 21 20 4F 07 04 41 2E 2F 5E 08 17 41 0B 0A 50 19 1A 1B 52 1F 11 02 02 23 06 14 2E 2E 0C 28 3A 2A 6C 70 62 10 21 37 23 67 36 20 3B 37 2C 30 33 3A 7C 29 20 32 34 34 76 20 3D 21 C2 8B DB DD DC CE C2 CA C7 83 D4 C8 CB C2 9E 85 DF C3 D1 CA CA DA D8 E9 C0 D2 D4 D4 C5 F4 DB C0 E4 FF A8 A9 FA FD ED E9 E7 F0 D4 EE D5 E6 F2 E0 BA CF F0 FC EC FA BC F4 E1 B3 FE FE B6 F8 FA F0 CA 88 80 80 82 8B CC 9B 87 8D 84 8E 94 AA 91 89 8E 92 D8 8F 9B 91 98 92 80 DD D0 B2 9E 9E 98 91 EA BD AD A7 AA A0 BE ED B5 AA B4 A9 E6 AC A1 BC FA E6 F8 F9 AC BA A8 A8 A0 BD F0 B5 BF A4 B7 BA 44 45 4D 4A 5A 4A 48 0D 52 4A 4E 46 06 55 41 56 4F 57 4C 6D 4C 5E 58 54 5C 54 10 47 53 59 50 5A 78 2B 69 65 7C 6A 6D 69 7B 23 72 64 61 6E 77 71 7F 69 7D 7D 30 3F 53 73 7E 6A 30 7E 78 72 34 61 18 0A 0C 00 00 08 4C 1B 07 0D 04 0E 14 47 07 04 14 5B 1A 1C 5E 0D 19 1A 1B 00 04 14 04 12 10 5B 3E 39 29 2D 27 21 2B 1B 27 2D 24 2E 34 31 21 2B 3E 34 2A 1A 32 30 2F 38 36 73 20 3E 25 3E 20 3C C5 C5 88 CA CF C1 8B D9 82 C1 C5 81 C5 CB CB D6 DF DF 98 D8 D9 DE D5 D3 FD D5 D6 91 9B 97 F1 CD E9 E3 E9 E7 E9 EA DC EC F6 EB D4 EE C2 E6 F0 E4 D8 FA EB FC CE ED F3 F9 E7 F0 E4 D0 E5 E4 F1 E1 BB 9E 87 9D 87 81 8B AC 91 90 85 95 AB 82 97 96 9B 9C 9D AA 87 92 9E 92 9E 9D 95 86 B8 96 99 90 EA A2 BB E9 A0 BA A0 A1 E2 AC B2 E1 A3 AA B4 B1 A3 B5 BD AE 97 AB B9 B0 A1 88 F0 FA F6 98 BA B9 53 0B 65 48 5C 44 49 59 02 4C 52 45 43 55 04 51 43 4B 5D 19 57 4C 1C 5C 5E 5F 5F 46 53 53 44 47 63 68 6D 44 61 6B 65 6B 6B 60 61 75 69 75 50 7C 6A 7E 7E 76 6C 7C 79 48 61 76 44 78 75 7C 67 53 05 19 20 00 1D 1B 03 1F 1B 24 12 0E 13 17 37 00 0E 0F 11 17 19 0C 2F 04 1C 07 18 14 02 1E 17 3C 3E 2E 25 05 27 22 25 39 0B 25 14 2E 33 24 2C 20 3E 17 31 34 37 2B 7C 34 34 73 24 3E 23 34 3C 30 CE E7 E5 FD FA EC 96 F1 E5 CA D4 CD C7 C5 89 F7 CF D5 D6 DC CC E3 DE C8 DB DF D4 C2 EA 85 D7 ED BF C9 C6 C5 DE D3 BC D1 E1 EF E9 E4 E8 F3 D8 F1 FF E9 F5 F0 F0 FE F0 C1 F6 F6 E6 F4 FA F8 E4 F8 8F 85 9C B5 AC 9A 9F 84 8C 86 93 92 AA 86 9D 80 88 A7 AC 8B 9F 9B 95 93 95 A3 9C 90 82 91 9B 87 A7 E5 8A BC BD A6 A2 A8 B1 B0 8C A0 BF A2 B6 99 98 AE AB B0 B0 BA AF AE 9D B1 BA B4 B5 A3 A7 89 65 59 4C 4C 5C 7B 55 5D 47 50 7C 6D 4F 4A 4D 51 73 5D 6C 56 4B 5C 54 58 56 7C 42 55 53 45 60 4C 7A 6E 26 6A 7D 78 65 79 6A 23 74 73 6F 60 63 60 68 3B 68 6B 77 7C 79 3D 73 67 30 5C 77 65 7F 70 1E 22 0E 3D 01 1A 0F 05 07 07 2D 00 14 0C 01 11 5A 12 1E 59 0A 10 09 1E 1A 16 14 3C 3D 23 20 26 3E 24 38 69 22 26 21 24 36 10 14 0D 05 7D 18 02 33 2F 34 38 3C 72 0E 28 3C 3D 35 23 0A 35 21 3C C6 CF DB F5 9C CC F4 98 E0 ED EC F1 FA 97 F8 C6 D6 D2 DD D7 CA E3 C8 D8 C0 DE D9 DF D7 DB E8 D1 EF FD ED E5 E1 FF E1 E8 EC F7 DC C3 F3 F4 ED EB FF E8 EB D5 FF E6 F9 EF CE C7 E2 F0 F2 FE FA F2 BA 87 89 9D 88 80 9E 80 CC A1 95 92 8F 89 81 96 89 B7 99 80 9B 8D A0 BF 87 80 99 9F 93 84 87 BA A8 A1 AD AA BA BC 90 82 B0 A7 A5 B3 92 BE B4 A0 A9 87 8B AD B1 AF 90 B4 BF BA A4 9E A4 B3 B1 A7 7E 52 58 4C 00 4C 5F 5E 52 4C 54 72 5F 4A 46 4A 56 72 5C) */; + + internal static byte[] 4 = new byte[39059] + { + 249, 223, 201, 219, 218, 202, 222, 131, 199, 219, + 197, 154, 134, 135, 153, 133, 239, 213, 203, 204, + 206, 207, 211, 207, 198, 214, 212, 145, 196, 194, + 216, 208, 170, 253, 233, 229, 251, 234, 172, 249, + 251, 243, 229, 192, 234, 235, 235, 242, 186, 239, + 234, 248, 250, 246, 242, 250, 211, 255, 252, 254, + 225, 183, 199, 217, 171, 135, 132, 134, 153, 207, + 184, 189, 163, 143, 140, 142, 145, 199, 183, 169, + 218, 175, 138, 152, 151, 147, 149, 147, 149, 178, + 156, 157, 153, 128, 212, 152, 165, 175, 161, 175, + 183, 239, 163, 191, 166, 166, 178, 128, 170, 171, + 171, 178, 250, 182, 183, 189, 183, 185, 165, 253, + 179, 190, 191, 164, 184, 163, 149, 185, 70, 68, + 95, 9, 67, 64, 72, 68, 68, 90, 0, 81, + 84, 78, 71, 64, 123, 87, 84, 86, 73, 31, + 81, 82, 86, 90, 86, 72, 22, 67, 93, 83, + 70, 78, 94, 76, 66, 61, 83, 68, 81, 92, + 65, 70, 65, 85, 65, 66, 91, 79, 93, 93, + 95, 115, 112, 114, 101, 51, 96, 112, 100, 99, + 125, 116, 6, 75, 11, 5, 1, 28, 9, 77, + 18, 12, 19, 8, 18, 14, 11, 11, 59, 23, + 20, 22, 9, 95, 25, 5, 2, 28, 2, 5, + 55, 59, 56, 58, 29, 20, 30, 6, 2, 26, + 1, 8, 29, 2, 14, 0, 10, 30, 23, 12, + 9, 4, 30, 11, 17, 18, 3, 9, 27, 16, + 27, 14, 30, 30, 7, 1, 229, 249, 241, 232, + 226, 227, 229, 227, 237, 237, 229, 254, 246, 230, + 231, 238, 251, 252, 253, 247, 145, 254, 206, 200, + 222, 214, 254, 208, 219, 210, 213, 214, 233, 228, + 253, 231, 250, 252, 245, 224, 224, 236, 236, 192, + 229, 228, 235, 240, 244, 239, 184, 248, 240, 251, + 188, 238, 235, 254, 242, 254, 250, 183, 249, 224, + 153, 159, 200, 139, 139, 207, 138, 159, 141, 142, + 192, 146, 135, 138, 129, 197, 153, 148, 150, 151, + 155, 156, 136, 148, 157, 157, 159, 131, 146, 146, + 134, 161, 179, 187, 173, 136, 173, 172, 163, 184, + 172, 183, 224, 160, 168, 163, 228, 170, 168, 191, + 189, 171, 254, 171, 165, 173, 183, 243, 189, 164, + 165, 163, 244, 183, 79, 11, 78, 91, 65, 66, + 12, 94, 67, 78, 69, 1, 69, 72, 74, 75, + 95, 88, 76, 80, 81, 81, 108, 79, 91, 80, + 85, 11, 22, 23, 103, 92, 112, 110, 50, 41, + 52, 47, 36, 36, 34, 57, 58, 33, 78, 110, + 119, 113, 117, 105, 97, 88, 121, 120, 110, 120, + 117, 114, 100, 120, 121, 121, 89, 116, 4, 10, + 15, 12, 28, 85, 76, 4, 12, 10, 20, 8, + 7, 11, 13, 31, 27, 15, 17, 22, 16, 81, + 82, 83, 58, 26, 3, 5, 25, 5, 13, 37, + 56, 36, 43, 44, 61, 60, 35, 63, 49, 11, + 41, 50, 50, 40, 54, 60, 10, 41, 55, 58, + 59, 44, 47, 50, 32, 20, 53, 37, 31, 57, + 50, 58, 138, 134, 136, 207, 207, 198, 192, 141, + 214, 204, 128, 211, 195, 211, 214, 204, 223, 205, + 221, 153, 215, 209, 218, 210, 146, 210, 210, 222, + 195, 195, 148, 212, 237, 236, 250, 236, 233, 238, + 248, 228, 237, 237, 160, 172, 166, 225, 229, 236, + 246, 187, 236, 246, 190, 252, 238, 248, 243, 231, + 245, 177, 247, 240, 243, 231, 143, 140, 137, 157, + 135, 128, 130, 205, 141, 129, 138, 132, 133, 147, + 196, 200, 218, 154, 216, 159, 155, 136, 220, 137, + 139, 131, 149, 130, 214, 128, 157, 129, 162, 235, + 188, 161, 171, 239, 191, 172, 175, 166, 224, 175, + 167, 170, 161, 141, 179, 168, 172, 182, 172, 166, + 157, 186, 181, 161, 181, 182, 183, 163, 189, 186, + 68, 102, 73, 71, 79, 72, 73, 95, 24, 3, + 73, 79, 79, 83, 77, 68, 86, 82, 66, 92, + 90, 31, 79, 72, 81, 80, 85, 66, 69, 81, + 65, 89, 102, 114, 120, 104, 124, 110, 97, 104, + 118, 102, 114, 64, 97, 96, 118, 96, 125, 122, + 108, 112, 113, 113, 95, 124, 124, 115, 100, 49, + 112, 126, 122, 113, 74, 10, 15, 14, 28, 10, + 11, 12, 22, 12, 18, 65, 17, 14, 16, 13, + 90, 8, 8, 28, 29, 22, 26, 20, 23, 23, + 80, 31, 23, 26, 17, 85, 26, 121, 13, 49, + 62, 32, 34, 40, 44, 55, 41, 32, 42, 103, + 9, 42, 44, 50, 54, 62, 126, 30, 42, 56, + 32, 50, 55, 52, 27, 56, 34, 60, 196, 204, + 136, 200, 216, 202, 222, 204, 197, 198, 211, 241, + 195, 213, 205, 202, 222, 155, 215, 223, 158, 250, + 196, 205, 221, 221, 213, 223, 194, 222, 213, 217, + 170, 198, 231, 255, 231, 225, 235, 173, 195, 245, + 229, 243, 231, 224, 225, 214, 245, 238, 234, 250, + 251, 236, 188, 237, 224, 250, 243, 244, 229, 183, + 242, 250, 152, 203, 165, 168, 173, 142, 128, 142, + 151, 143, 129, 149, 143, 136, 138, 197, 142, 130, + 136, 156, 178, 150, 146, 152, 147, 129, 156, 136, + 214, 160, 145, 156, 173, 163, 188, 172, 170, 239, + 129, 162, 180, 170, 174, 166, 230, 134, 178, 160, + 168, 186, 191, 188, 142, 186, 174, 180, 189, 183, + 240, 190, 176, 247, 152, 130, 103, 106, 123, 70, + 91, 93, 79, 72, 81, 3, 80, 83, 79, 68, + 65, 86, 26, 93, 87, 75, 30, 115, 107, 112, + 115, 96, 89, 92, 70, 91, 81, 21, 71, 100, + 126, 96, 96, 104, 44, 76, 116, 102, 114, 96, + 97, 98, 84, 96, 104, 114, 119, 125, 62, 112, + 122, 61, 65, 122, 125, 97, 122, 114, 52, 88, + 5, 29, 1, 7, 9, 79, 45, 27, 7, 17, + 1, 6, 3, 52, 9, 10, 21, 15, 16, 28, + 26, 95, 49, 18, 4, 26, 30, 22, 86, 54, + 2, 16, 56, 42, 47, 44, 30, 42, 62, 36, + 45, 39, 96, 46, 32, 103, 23, 40, 53, 52, + 44, 49, 59, 59, 124, 16, 61, 37, 57, 63, + 49, 119, 21, 35, 207, 217, 201, 206, 203, 255, + 197, 219, 205, 215, 128, 241, 201, 206, 202, 209, + 154, 246, 215, 207, 215, 209, 219, 157, 243, 197, + 213, 195, 215, 208, 209, 229, 239, 249, 225, 230, + 234, 175, 227, 235, 162, 211, 208, 204, 199, 180, + 201, 196, 201, 242, 255, 247, 255, 243, 207, 245, + 253, 225, 228, 177, 219, 248, 226, 252, 132, 140, + 200, 168, 152, 138, 158, 140, 133, 134, 192, 177, + 131, 149, 141, 138, 158, 182, 145, 157, 154, 147, + 153, 221, 191, 156, 134, 152, 152, 144, 212, 180, + 188, 174, 186, 168, 169, 170, 236, 157, 167, 177, + 169, 174, 162, 139, 171, 171, 189, 251, 149, 182, + 168, 182, 178, 186, 242, 146, 166, 180, 164, 182, + 179, 176, 10, 123, 77, 91, 71, 64, 72, 108, + 79, 76, 85, 79, 82, 7, 75, 67, 26, 89, + 89, 75, 77, 31, 76, 92, 65, 64, 85, 85, + 22, 85, 81, 83, 101, 121, 109, 41, 97, 127, + 105, 99, 107, 109, 103, 33, 118, 104, 119, 108, + 110, 114, 119, 119, 92, 112, 112, 113, 123, 125, + 119, 116, 100, 55, 86, 116, 4, 15, 27, 42, + 6, 14, 2, 3, 7, 15, 19, 49, 3, 21, + 13, 10, 30, 91, 23, 31, 94, 50, 61, 93, + 20, 28, 2, 81, 19, 25, 2, 16, 38, 36, + 56, 44, 61, 25, 45, 33, 55, 38, 96, 46, + 32, 103, 39, 42, 52, 61, 49, 61, 59, 49, + 63, 56, 114, 58, 62, 37, 51, 37, 34, 52, + 198, 255, 209, 217, 203, 143, 195, 203, 130, 206, + 207, 215, 207, 201, 195, 133, 219, 205, 221, 203, + 223, 216, 217, 254, 221, 222, 221, 222, 210, 222, + 192, 204, 170, 200, 224, 232, 224, 225, 233, 225, + 162, 202, 238, 229, 227, 255, 203, 246, 249, 242, + 244, 245, 255, 235, 243, 239, 225, 195, 245, 227, + 255, 248, 240, 193, 147, 155, 141, 201, 129, 137, + 204, 160, 141, 149, 137, 143, 129, 199, 165, 147, + 159, 137, 153, 158, 155, 178, 147, 153, 155, 149, + 153, 148, 146, 215, 185, 154, 188, 162, 166, 174, + 238, 142, 186, 168, 176, 162, 167, 164, 150, 162, + 182, 172, 181, 191, 248, 182, 184, 255, 145, 178, + 182, 186, 182, 184, 179, 179, 244, 152, 69, 93, + 65, 71, 73, 15, 109, 91, 71, 81, 65, 70, + 67, 117, 65, 66, 72, 94, 75, 74, 87, 80, + 82, 29, 126, 90, 94, 84, 102, 82, 70, 92, + 101, 111, 40, 102, 104, 47, 64, 100, 108, 102, + 97, 115, 38, 85, 97, 98, 104, 126, 107, 106, + 119, 112, 114, 78, 125, 102, 98, 114, 115, 100, + 52, 101, 24, 2, 11, 12, 29, 79, 10, 2, + 16, 67, 20, 9, 3, 71, 22, 0, 29, 9, + 29, 10, 13, 22, 19, 19, 82, 31, 25, 31, + 19, 39, 6, 28, 41, 46, 104, 10, 38, 46, + 34, 35, 39, 47, 16, 36, 52, 46, 43, 33, + 122, 52, 62, 121, 46, 45, 53, 62, 55, 115, + 51, 57, 55, 57, 58, 48, 198, 234, 221, 221, + 193, 221, 201, 202, 208, 198, 211, 210, 207, 209, + 193, 133, 252, 210, 214, 208, 202, 218, 156, 244, + 223, 195, 197, 221, 197, 210, 148, 231, 239, 248, + 248, 230, 224, 252, 233, 173, 207, 236, 246, 232, + 232, 224, 164, 196, 236, 254, 234, 248, 249, 250, + 212, 244, 246, 247, 245, 255, 193, 254, 250, 241, + 133, 156, 200, 185, 139, 157, 133, 130, 134, 176, + 143, 148, 148, 132, 129, 150, 218, 139, 138, 144, + 157, 154, 143, 221, 148, 156, 130, 209, 130, 159, + 145, 213, 139, 173, 161, 187, 163, 174, 236, 161, + 171, 173, 165, 150, 175, 169, 160, 170, 173, 178, + 182, 190, 254, 185, 169, 179, 177, 167, 185, 190, + 184, 155, 177, 180, 89, 95, 5, 90, 95, 90, + 77, 95, 71, 80, 0, 76, 67, 83, 76, 74, + 94, 105, 93, 85, 95, 75, 85, 75, 87, 19, + 99, 69, 68, 82, 90, 82, 126, 99, 40, 64, + 96, 107, 105, 117, 80, 80, 73, 33, 118, 98, + 118, 108, 117, 127, 75, 118, 107, 109, 127, 120, + 97, 51, 96, 99, 127, 116, 113, 102, 74, 13, + 7, 27, 78, 27, 4, 8, 66, 49, 51, 40, + 70, 11, 13, 11, 31, 54, 23, 29, 27, 95, + 26, 18, 0, 83, 4, 25, 19, 87, 38, 38, + 3, 107, 36, 32, 32, 42, 31, 32, 45, 44, + 52, 41, 47, 41, 35, 101, 42, 62, 42, 48, + 49, 59, 17, 62, 21, 58, 62, 61, 51, 46, + 116, 17, 211, 197, 201, 196, 199, 204, 232, 212, + 204, 194, 205, 200, 197, 135, 208, 215, 219, 216, + 211, 208, 208, 216, 156, 219, 211, 208, 196, 222, + 196, 228, 219, 192, 248, 232, 237, 169, 254, 253, + 229, 238, 231, 206, 239, 247, 239, 233, 227, 165, + 219, 237, 253, 235, 255, 248, 249, 189, 215, 253, + 230, 244, 250, 248, 228, 240, 191, 155, 138, 136, + 128, 139, 204, 137, 135, 149, 137, 128, 146, 142, + 139, 139, 218, 146, 150, 217, 219, 187, 147, 138, + 156, 145, 145, 159, 146, 215, 144, 144, 188, 162, + 169, 189, 167, 160, 162, 237, 171, 173, 224, 228, + 150, 166, 182, 164, 184, 180, 180, 176, 189, 255, + 143, 156, 128, 135, 162, 180, 184, 179, 135, 161, + 79, 91, 8, 70, 72, 15, 92, 76, 80, 66, + 66, 78, 74, 78, 71, 5, 105, 122, 106, 25, + 77, 70, 79, 73, 87, 94, 125, 80, 78, 94, + 89, 64, 103, 43, 126, 104, 98, 122, 105, 45, + 100, 108, 114, 33, 114, 111, 97, 37, 123, 120, + 123, 124, 114, 122, 110, 124, 102, 122, 127, 127, + 54, 113, 117, 118, 30, 4, 26, 40, 25, 10, + 31, 2, 15, 6, 64, 46, 21, 4, 13, 9, + 22, 26, 12, 22, 12, 60, 20, 28, 28, 23, + 21, 81, 59, 24, 25, 16, 36, 63, 61, 36, + 110, 0, 63, 46, 43, 47, 44, 32, 50, 40, + 54, 19, 53, 55, 57, 45, 55, 51, 53, 41, + 43, 9, 57, 54, 12, 54, 51, 5, 207, 217, + 203, 204, 192, 219, 140, 233, 199, 213, 201, 192, + 210, 206, 203, 203, 251, 201, 215, 214, 208, 254, + 238, 242, 253, 253, 144, 225, 211, 197, 221, 218, + 238, 216, 252, 232, 224, 235, 237, 255, 230, 163, + 196, 228, 240, 238, 229, 241, 243, 244, 246, 212, + 241, 233, 245, 243, 245, 179, 209, 231, 243, 229, + 245, 242, 143, 203, 171, 134, 128, 153, 137, 159, + 133, 134, 142, 130, 131, 200, 160, 140, 140, 158, + 138, 158, 155, 145, 159, 152, 162, 150, 130, 152, + 153, 147, 212, 154, 172, 235, 174, 168, 189, 187, + 236, 136, 143, 130, 144, 164, 180, 174, 171, 161, + 250, 180, 190, 249, 173, 179, 179, 170, 242, 150, + 157, 144, 134, 178, 166, 188, 69, 79, 8, 70, + 72, 15, 95, 68, 69, 77, 65, 77, 6, 98, + 105, 100, 113, 90, 81, 75, 87, 31, 110, 88, + 94, 82, 68, 88, 64, 82, 20, 124, 100, 111, + 109, 113, 76, 96, 96, 97, 107, 109, 103, 100, + 116, 39, 70, 100, 116, 127, 107, 57, 88, 115, + 125, 105, 86, 118, 102, 120, 119, 99, 125, 122, + 4, 57, 9, 29, 11, 79, 3, 11, 66, 32, + 8, 0, 8, 0, 1, 53, 31, 9, 17, 22, + 26, 95, 19, 27, 82, 30, 31, 28, 19, 25, + 0, 0, 39, 6, 39, 36, 43, 33, 56, 56, + 47, 19, 37, 51, 47, 40, 32, 101, 60, 52, + 42, 121, 19, 48, 49, 56, 60, 39, 37, 60, + 5, 56, 33, 39, 201, 206, 219, 137, 222, 221, + 197, 206, 199, 208, 128, 199, 201, 213, 132, 232, + 213, 214, 221, 215, 202, 202, 209, 152, 224, 147, + 252, 208, 196, 197, 205, 149, 221, 226, 228, 229, + 231, 238, 225, 254, 210, 241, 233, 226, 227, 167, + 203, 246, 249, 242, 244, 245, 255, 235, 243, 239, + 194, 246, 226, 248, 249, 243, 180, 250, 140, 203, + 165, 168, 223, 191, 137, 159, 139, 140, 132, 193, + 137, 129, 196, 168, 187, 201, 181, 150, 136, 150, + 146, 154, 210, 178, 134, 148, 132, 150, 147, 144, + 234, 164, 174, 233, 129, 188, 175, 164, 174, 175, + 161, 181, 169, 181, 139, 171, 250, 153, 185, 181, + 191, 177, 191, 184, 242, 133, 191, 189, 163, 186, + 177, 131, 69, 71, 93, 68, 75, 127, 67, 94, + 75, 87, 73, 87, 67, 7, 114, 74, 86, 78, + 85, 92, 30, 118, 82, 89, 87, 75, 125, 94, + 88, 82, 77, 21, 76, 103, 103, 126, 46, 70, + 98, 105, 103, 123, 77, 71, 79, 39, 84, 96, + 104, 114, 119, 125, 95, 124, 127, 120, 126, 118, + 98, 112, 98, 126, 123, 123, 74, 36, 27, 10, + 7, 3, 0, 12, 22, 12, 18, 32, 16, 2, + 22, 4, 29, 30, 88, 45, 12, 10, 25, 93, + 32, 18, 30, 22, 19, 39, 17, 7, 35, 36, + 44, 105, 33, 41, 108, 0, 45, 53, 41, 47, + 33, 103, 5, 51, 63, 41, 57, 62, 59, 20, + 61, 40, 52, 62, 49, 63, 118, 22, 48, 52, + 218, 223, 193, 223, 203, 143, 225, 194, 212, 202, + 206, 198, 134, 230, 210, 192, 200, 218, 223, 220, + 157, 249, 221, 206, 198, 144, 227, 221, 217, 192, + 229, 198, 254, 226, 235, 226, 221, 248, 229, 227, + 229, 163, 201, 239, 226, 226, 252, 193, 243, 237, + 241, 253, 251, 237, 200, 239, 231, 246, 176, 194, + 226, 229, 241, 251, 141, 159, 128, 201, 167, 129, + 136, 136, 154, 165, 137, 147, 149, 147, 196, 168, + 187, 219, 136, 156, 140, 150, 147, 153, 161, 150, + 147, 158, 152, 147, 212, 184, 139, 235, 184, 172, + 188, 166, 163, 169, 131, 181, 165, 179, 167, 160, + 161, 229, 158, 178, 170, 188, 189, 171, 181, 178, + 188, 178, 188, 241, 159, 185, 176, 176, 82, 96, + 77, 69, 90, 65, 73, 95, 2, 96, 72, 64, + 72, 73, 65, 73, 106, 94, 74, 80, 81, 91, + 28, 82, 84, 19, 125, 112, 22, 81, 91, 71, + 42, 64, 109, 101, 122, 97, 105, 127, 37, 112, + 32, 66, 110, 102, 106, 107, 127, 119, 91, 118, + 123, 121, 122, 116, 113, 122, 117, 127, 98, 55, + 123, 115, 74, 8, 0, 8, 0, 1, 9, 1, + 69, 16, 64, 22, 15, 3, 16, 13, 42, 30, + 10, 26, 27, 17, 8, 28, 21, 22, 80, 33, + 4, 30, 23, 16, 106, 4, 59, 42, 39, 35, + 32, 44, 54, 44, 50, 7, 39, 52, 48, 101, + 31, 22, 25, 121, 14, 58, 46, 52, 61, 55, + 3, 61, 57, 32, 116, 16, 231, 234, 136, 249, + 203, 221, 197, 194, 198, 240, 201, 198, 200, 198, + 200, 133, 255, 246, 249, 153, 238, 218, 206, 212, + 221, 215, 227, 197, 217, 212, 220, 212, 249, 255, + 225, 234, 174, 220, 224, 226, 245, 208, 237, 238, + 233, 243, 236, 236, 244, 252, 220, 246, 235, 253, + 240, 248, 178, 224, 253, 254, 249, 227, 252, 252, + 132, 140, 188, 144, 158, 138, 204, 130, 132, 195, + 147, 140, 137, 136, 144, 141, 147, 149, 159, 217, + 173, 139, 147, 158, 154, 146, 131, 133, 159, 148, + 167, 129, 165, 168, 160, 168, 189, 187, 165, 174, + 226, 187, 224, 147, 163, 171, 165, 177, 179, 173, + 189, 249, 141, 171, 174, 184, 188, 180, 164, 185, + 246, 158, 186, 177, 79, 83, 122, 122, 103, 15, + 124, 72, 80, 74, 79, 69, 3, 108, 4, 117, + 95, 73, 81, 86, 90, 26, 120, 29, 98, 86, + 66, 88, 89, 83, 125, 86, 98, 98, 101, 102, + 101, 122, 88, 104, 108, 104, 97, 111, 38, 84, + 97, 107, 81, 114, 114, 108, 112, 63, 79, 120, + 124, 64, 117, 127, 125, 120, 97, 53, 57, 27, + 9, 7, 78, 45, 40, 4, 16, 6, 3, 21, + 15, 8, 10, 4, 22, 91, 53, 22, 8, 26, + 17, 24, 28, 7, 80, 56, 24, 19, 17, 13, + 11, 39, 36, 32, 41, 46, 56, 34, 48, 23, + 57, 49, 35, 103, 43, 35, 122, 17, 57, 46, + 126, 18, 51, 43, 59, 61, 55, 113, 23, 33, + 49, 39, 203, 204, 205, 250, 193, 218, 222, 206, + 199, 131, 208, 211, 207, 196, 193, 133, 220, 212, + 202, 153, 244, 222, 203, 157, 255, 220, 198, 216, + 216, 208, 148, 244, 252, 238, 250, 232, 233, 234, + 220, 232, 240, 234, 239, 229, 166, 232, 226, 165, + 208, 250, 239, 185, 211, 240, 234, 244, 252, 244, + 176, 208, 224, 242, 230, 244, 141, 142, 187, 129, + 135, 137, 152, 205, 141, 133, 192, 171, 135, 144, + 196, 168, 149, 141, 145, 151, 153, 223, 189, 139, + 151, 129, 145, 150, 147, 163, 141, 133, 175, 235, + 167, 175, 238, 155, 169, 168, 182, 171, 224, 140, + 169, 177, 173, 171, 189, 251, 153, 175, 187, 173, + 189, 186, 183, 128, 191, 164, 164, 180, 177, 245, + 90, 89, 65, 74, 75, 15, 74, 66, 80, 3, + 116, 68, 67, 83, 76, 5, 119, 84, 78, 80, + 80, 88, 28, 124, 68, 86, 66, 80, 81, 82, + 100, 80, 120, 98, 103, 109, 46, 96, 106, 45, + 86, 102, 101, 117, 110, 39, 73, 106, 108, 114, + 118, 126, 62, 94, 106, 120, 96, 114, 119, 116, + 69, 127, 125, 115, 30, 75, 7, 15, 78, 59, + 9, 8, 22, 11, 64, 44, 9, 17, 13, 11, + 29, 91, 57, 15, 27, 13, 29, 26, 23, 39, + 9, 1, 19, 87, 27, 19, 106, 7, 33, 57, + 61, 111, 1, 34, 52, 42, 46, 38, 102, 6, + 50, 32, 40, 58, 63, 60, 13, 48, 41, 47, + 49, 54, 112, 33, 36, 62, 55, 48, 138, 205, + 199, 219, 142, 227, 197, 221, 209, 131, 237, 206, + 208, 206, 202, 194, 154, 250, 206, 220, 204, 222, + 219, 216, 226, 214, 194, 216, 217, 211, 148, 218, + 236, 171, 196, 224, 254, 252, 172, 192, 237, 245, + 233, 239, 225, 167, 197, 243, 255, 233, 249, 254, + 251, 204, 244, 244, 244, 231, 176, 254, 240, 183, + 216, 252, 154, 152, 200, 164, 129, 153, 133, 131, + 133, 195, 161, 151, 131, 149, 133, 130, 159, 179, + 145, 138, 138, 144, 142, 148, 145, 146, 156, 209, + 160, 152, 152, 148, 190, 162, 164, 160, 186, 182, + 159, 153, 134, 147, 165, 179, 175, 168, 160, 147, + 181, 183, 185, 173, 183, 179, 181, 169, 171, 131, + 181, 163, 191, 184, 176, 134, 69, 94, 90, 74, + 75, 92, 12, 93, 80, 74, 67, 68, 85, 7, + 66, 74, 72, 27, 112, 111, 127, 83, 80, 29, + 90, 90, 67, 69, 89, 69, 77, 125, 99, 120, + 124, 102, 124, 118, 44, 125, 103, 113, 105, 110, + 98, 67, 109, 118, 106, 119, 121, 96, 62, 114, + 115, 121, 119, 51, 61, 49, 54, 107, 52, 86, + 5, 7, 7, 27, 78, 82, 76, 36, 12, 7, + 9, 2, 7, 19, 11, 23, 55, 26, 22, 24, + 25, 26, 14, 71, 82, 26, 30, 24, 2, 30, + 21, 25, 35, 49, 41, 61, 39, 32, 34, 99, + 108, 109, 9, 47, 34, 46, 39, 36, 46, 52, + 42, 20, 63, 49, 61, 58, 55, 33, 106, 113, + 63, 57, 61, 33, 195, 202, 196, 192, 212, 202, + 200, 141, 209, 214, 195, 194, 195, 212, 215, 195, + 207, 215, 212, 192, 215, 209, 216, 212, 209, 210, + 196, 222, 196, 249, 213, 216, 239, 219, 228, 232, + 237, 234, 195, 255, 230, 230, 242, 210, 242, 245, + 229, 241, 255, 252, 225, 212, 255, 241, 253, 250, + 247, 225, 170, 177, 255, 249, 253, 225, 131, 138, + 132, 128, 148, 142, 152, 132, 141, 141, 206, 207, + 200, 183, 136, 132, 153, 158, 183, 139, 154, 154, + 142, 174, 134, 129, 145, 133, 147, 144, 141, 184, + 171, 165, 169, 174, 171, 189, 246, 237, 171, 173, + 169, 181, 175, 166, 168, 172, 160, 190, 188, 249, + 173, 170, 191, 190, 183, 160, 163, 183, 163, 187, + 184, 172, 108, 74, 65, 69, 75, 75, 12, 89, + 77, 3, 73, 79, 79, 83, 77, 68, 86, 82, + 66, 92, 30, 76, 95, 79, 91, 67, 68, 17, + 17, 16, 72, 105, 36, 111, 100, 101, 104, 125, + 99, 96, 82, 98, 116, 105, 114, 104, 84, 100, + 110, 115, 126, 112, 114, 122, 79, 105, 96, 114, + 100, 116, 113, 110, 89, 116, 4, 10, 15, 12, + 28, 85, 76, 4, 12, 10, 20, 8, 7, 11, + 13, 31, 27, 15, 17, 22, 16, 81, 82, 83, + 33, 7, 2, 16, 2, 18, 19, 12, 7, 42, + 38, 40, 41, 42, 62, 119, 98, 42, 46, 40, + 50, 46, 37, 41, 51, 33, 61, 61, 126, 44, + 41, 62, 49, 54, 35, 34, 48, 34, 56, 57, + 211, 216, 220, 219, 207, 219, 201, 202, 219, 237, + 193, 204, 195, 212, 208, 215, 219, 207, 221, 222, + 199, 214, 210, 219, 221, 157, 200, 220, 218, 252, + 209, 204, 170, 249, 237, 248, 251, 234, 255, 249, + 172, 163, 210, 228, 247, 242, 225, 246, 238, 210, + 252, 185, 163, 191, 167, 189, 193, 246, 254, 245, + 255, 249, 243, 181, 153, 132, 157, 155, 141, 138, + 204, 208, 194, 183, 136, 132, 148, 130, 196, 140, + 137, 219, 150, 150, 222, 143, 157, 143, 151, 157, + 132, 209, 152, 150, 153, 144, 174, 174, 184, 172, + 160, 171, 169, 163, 182, 138, 180, 164, 171, 183, + 165, 183, 191, 181, 172, 144, 170, 186, 177, 174, + 242, 178, 162, 182, 163, 186, 177, 187, 94, 11, + 69, 92, 93, 91, 12, 78, 77, 77, 84, 64, + 79, 73, 87, 5, 91, 79, 24, 85, 91, 94, + 79, 73, 18, 92, 94, 84, 22, 82, 88, 80, + 103, 110, 102, 125, 74, 106, 111, 100, 111, 98, + 108, 81, 106, 102, 103, 96, 105, 77, 121, 117, + 107, 122, 72, 111, 115, 119, 121, 127, 113, 55, + 91, 101, 15, 25, 9, 29, 7, 0, 2, 87, + 66, 32, 1, 15, 5, 2, 8, 69, 21, 9, + 28, 28, 12, 12, 82, 93, 33, 22, 30, 21, + 31, 25, 19, 85, 57, 36, 61, 59, 45, 42, + 108, 112, 98, 23, 50, 32, 34, 46, 42, 34, + 122, 20, 40, 60, 44, 62, 40, 52, 61, 61, + 106, 113, 21, 54, 58, 54, 207, 199, 136, 198, + 220, 203, 201, 223, 209, 141, 128, 238, 212, 195, + 193, 215, 201, 155, 219, 214, 203, 209, 200, 157, + 143, 147, 144, 226, 211, 217, 208, 220, 228, 236, + 168, 250, 225, 250, 254, 238, 231, 163, 189, 161, + 210, 245, 229, 225, 243, 245, 255, 185, 209, 239, + 249, 239, 243, 231, 249, 254, 248, 173, 180, 214, + 139, 133, 139, 140, 130, 207, 131, 159, 134, 134, + 146, 146, 200, 199, 183, 156, 151, 153, 151, 149, + 222, 194, 220, 169, 128, 146, 148, 152, 152, 144, + 212, 186, 186, 174, 186, 168, 186, 166, 163, 163, + 248, 227, 131, 160, 168, 164, 161, 169, 250, 180, + 170, 189, 187, 173, 175, 243, 242, 146, 179, 178, + 185, 162, 186, 161, 10, 22, 8, 18, 14, 110, + 79, 78, 77, 86, 78, 85, 6, 26, 4, 30, + 26, 104, 81, 93, 91, 31, 1, 29, 102, 65, + 81, 85, 95, 89, 83, 21, 69, 123, 109, 123, + 111, 123, 101, 98, 108, 57, 32, 66, 103, 105, + 103, 96, 118, 59, 119, 107, 122, 122, 110, 110, + 60, 51, 67, 120, 114, 114, 52, 40, 74, 80, + 72, 61, 7, 2, 9, 77, 11, 13, 64, 7, + 9, 21, 7, 0, 90, 70, 88, 45, 12, 30, + 24, 20, 28, 20, 80, 62, 6, 18, 6, 20, + 62, 34, 39, 39, 116, 111, 15, 44, 44, 32, + 37, 45, 102, 40, 54, 33, 63, 41, 43, 119, + 126, 11, 53, 48, 55, 115, 57, 63, 118, 49, + 59, 39, 201, 206, 136, 148, 142, 148, 140, 226, + 208, 199, 197, 211, 134, 211, 221, 213, 223, 155, + 133, 153, 133, 159, 243, 207, 214, 214, 194, 145, + 194, 206, 196, 208, 170, 233, 237, 225, 239, 249, + 229, 226, 240, 163, 189, 161, 210, 245, 229, 225, + 243, 245, 255, 185, 209, 239, 249, 239, 243, 231, + 249, 254, 248, 173, 180, 214, 139, 133, 139, 140, + 130, 207, 131, 159, 134, 134, 146, 146, 200, 199, + 171, 151, 158, 158, 138, 217, 138, 134, 140, 152, + 210, 145, 149, 153, 151, 129, 157, 154, 184, 235, + 245, 233, 143, 163, 160, 162, 181, 227, 131, 160, + 168, 164, 161, 169, 155, 183, 180, 150, 174, 186, + 178, 146, 160, 183, 181, 163, 165, 152, 186, 134, + 83, 70, 74, 70, 66, 110, 64, 65, 77, 84, + 0, 98, 71, 73, 71, 64, 86, 122, 84, 85, + 113, 79, 89, 83, 125, 65, 84, 84, 68, 68, + 123, 91, 75, 104, 107, 102, 123, 97, 120, 76, + 110, 111, 111, 118, 38, 68, 101, 107, 121, 126, + 116, 88, 114, 115, 83, 109, 119, 125, 95, 99, + 114, 114, 102, 102, 37, 5, 59, 16, 3, 13, + 3, 1, 35, 13, 4, 32, 5, 4, 11, 16, + 20, 15, 44, 11, 31, 27, 21, 19, 21, 83, + 63, 1, 19, 5, 21, 1, 35, 36, 38, 115, + 110, 12, 32, 34, 49, 38, 96, 49, 41, 52, + 45, 49, 51, 52, 54, 42, 112, 127, 15, 56, + 60, 55, 57, 63, 49, 119, 39, 58, 223, 217, + 203, 204, 142, 146, 140, 249, 208, 194, 196, 200, + 200, 192, 132, 234, 202, 222, 202, 216, 202, 214, + 211, 211, 136, 147, 243, 221, 217, 196, 209, 149, + 250, 228, 251, 224, 250, 230, 227, 227, 241, 173, + 160, 210, 255, 234, 230, 234, 246, 187, 165, 185, + 202, 237, 253, 249, 251, 253, 247, 177, 217, 231, + 241, 231, 139, 159, 129, 134, 128, 213, 204, 174, + 142, 140, 147, 132, 198, 151, 139, 150, 147, 143, + 145, 150, 144, 140, 210, 221, 179, 144, 147, 158, + 131, 153, 128, 213, 247, 235, 156, 187, 175, 171, + 165, 163, 165, 227, 143, 177, 163, 181, 165, 177, + 179, 180, 182, 227, 254, 156, 176, 178, 161, 182, + 240, 161, 185, 164, 189, 161, 67, 68, 70, 90, + 0, 15, 127, 68, 70, 70, 0, 28, 6, 115, + 86, 68, 94, 82, 86, 94, 30, 112, 76, 88, + 64, 82, 68, 88, 89, 89, 14, 21, 73, 103, + 103, 122, 107, 47, 124, 98, 113, 106, 116, 104, + 112, 98, 36, 117, 117, 104, 113, 109, 119, 112, + 114, 110, 60, 51, 67, 116, 120, 115, 125, 123, + 13, 75, 27, 6, 27, 29, 15, 8, 66, 94, + 64, 53, 20, 6, 0, 12, 20, 28, 88, 54, + 14, 26, 14, 28, 6, 26, 31, 31, 76, 87, + 55, 25, 37, 56, 45, 105, 62, 32, 63, 36, + 54, 42, 54, 36, 102, 55, 43, 54, 51, 47, + 49, 54, 48, 44, 114, 125, 1, 42, 61, 51, + 57, 59, 116, 104, 138, 255, 218, 200, 202, 198, + 194, 202, 130, 236, 208, 196, 212, 198, 208, 204, + 213, 213, 130, 153, 253, 211, 211, 206, 215, 147, + 222, 212, 209, 214, 192, 220, 252, 238, 168, 249, + 225, 252, 229, 249, 235, 236, 238, 242, 168, 167, + 215, 224, 244, 255, 241, 247, 249, 191, 239, 242, + 231, 225, 243, 244, 182, 170, 180, 193, 152, 138, + 140, 128, 128, 136, 204, 162, 146, 134, 146, 128, + 146, 142, 139, 139, 192, 219, 187, 149, 145, 140, + 153, 221, 156, 150, 151, 144, 130, 158, 130, 144, + 234, 187, 167, 186, 167, 187, 165, 162, 172, 176, + 238, 225, 149, 190, 169, 167, 181, 183, 248, 228, + 254, 139, 174, 188, 182, 186, 190, 182, 246, 152, + 164, 176, 88, 74, 92, 64, 65, 65, 22, 13, + 112, 70, 86, 68, 84, 84, 65, 5, 74, 84, + 75, 80, 74, 86, 83, 83, 65, 29, 16, 98, + 83, 89, 80, 92, 100, 108, 40, 122, 97, 122, + 126, 110, 103, 35, 61, 33, 82, 117, 101, 97, + 115, 117, 127, 57, 81, 111, 121, 111, 115, 103, + 121, 126, 120, 45, 52, 71, 15, 29, 13, 27, + 29, 10, 76, 29, 13, 16, 9, 21, 15, 8, + 10, 22, 84, 91, 43, 0, 19, 29, 19, 17, + 82, 78, 80, 37, 4, 22, 16, 28, 36, 44, + 104, 6, 62, 42, 62, 44, 54, 42, 47, 47, + 124, 103, 22, 32, 44, 62, 42, 42, 59, 127, + 44, 50, 33, 58, 36, 56, 57, 57, 39, 123, + 138, 234, 203, 202, 193, 218, 194, 217, 130, 158, + 128, 245, 212, 198, 192, 204, 212, 220, 152, 246, + 206, 218, 206, 220, 198, 218, 223, 223, 140, 151, + 242, 217, 235, 255, 252, 236, 224, 161, 172, 222, + 231, 237, 228, 232, 232, 224, 164, 246, 245, 238, + 234, 250, 251, 191, 161, 189, 198, 225, 241, 245, + 255, 249, 243, 181, 165, 155, 141, 155, 143, 155, + 133, 130, 140, 217, 192, 167, 138, 134, 144, 145, + 159, 149, 214, 217, 173, 134, 145, 159, 157, 159, + 208, 204, 214, 177, 152, 148, 190, 191, 173, 167, + 244, 239, 163, 191, 166, 166, 178, 178, 230, 176, + 161, 183, 191, 251, 182, 182, 170, 255, 191, 188, + 188, 176, 181, 189, 186, 178, 176, 245, 75, 77, + 92, 76, 92, 15, 25, 13, 81, 70, 67, 78, + 72, 67, 87, 9, 26, 93, 87, 75, 93, 90, + 28, 77, 93, 64, 89, 69, 95, 88, 90, 21, + 105, 103, 103, 122, 103, 97, 107, 35, 86, 113, + 97, 101, 111, 105, 99, 37, 85, 107, 125, 107, + 127, 107, 117, 114, 124, 41, 48, 83, 100, 114, + 117, 126, 15, 29, 13, 7, 64, 79, 60, 2, + 17, 10, 20, 8, 9, 9, 68, 88, 90, 64, + 88, 54, 24, 25, 15, 24, 6, 83, 77, 81, + 77, 87, 53, 17, 46, 34, 60, 32, 33, 33, + 45, 33, 98, 51, 33, 51, 39, 42, 33, 49, + 63, 41, 43, 121, 61, 48, 41, 51, 38, 115, + 109, 113, 38, 56, 39, 60, 222, 194, 199, 199, + 237, 206, 194, 138, 214, 131, 198, 200, 200, 195, + 132, 246, 246, 155, 215, 203, 218, 218, 206, 242, + 220, 214, 144, 193, 217, 196, 221, 193, 227, 228, + 230, 169, 224, 234, 248, 249, 235, 237, 231, 161, + 242, 254, 244, 224, 186, 233, 253, 232, 235, 246, + 238, 248, 246, 192, 228, 254, 230, 183, 251, 231, + 142, 142, 154, 201, 154, 150, 156, 136, 194, 145, + 133, 144, 147, 142, 150, 128, 158, 180, 136, 156, + 144, 154, 152, 221, 130, 156, 131, 152, 130, 158, + 155, 155, 234, 185, 173, 184, 187, 166, 190, 168, + 166, 151, 169, 172, 163, 168, 177, 177, 136, 190, + 190, 172, 173, 186, 159, 188, 188, 244, 164, 241, + 176, 190, 186, 177, 10, 74, 70, 80, 14, 92, + 88, 66, 82, 11, 83, 8, 6, 70, 74, 65, + 26, 79, 89, 82, 91, 23, 79, 20, 18, 92, + 66, 85, 83, 69, 71, 97, 120, 106, 108, 96, + 96, 104, 44, 66, 114, 102, 114, 96, 114, 110, + 107, 107, 32, 59, 89, 125, 116, 106, 111, 105, + 50, 64, 92, 62, 66, 71, 58, 53, 58, 4, + 27, 0, 26, 6, 3, 3, 66, 94, 64, 40, + 8, 17, 5, 9, 19, 31, 88, 10, 10, 16, + 12, 93, 30, 28, 3, 2, 86, 22, 16, 31, + 63, 56, 60, 36, 43, 33, 56, 109, 48, 38, + 51, 52, 42, 51, 13, 43, 44, 58, 52, 48, + 58, 127, 40, 60, 57, 54, 112, 33, 36, 56, + 50, 60, 222, 139, 201, 205, 196, 218, 223, 217, + 207, 198, 206, 213, 134, 213, 193, 214, 207, 215, + 204, 248, 210, 211, 211, 202, 146, 255, 217, 223, + 221, 151, 251, 246, 197, 223, 250, 232, 234, 230, + 226, 234, 162, 204, 240, 228, 244, 230, 240, 236, + 245, 245, 162, 185, 223, 251, 246, 232, 225, 231, + 176, 226, 226, 248, 228, 181, 134, 132, 155, 154, + 192, 207, 188, 130, 145, 138, 148, 136, 137, 137, + 196, 216, 218, 192, 216, 170, 138, 144, 140, 142, + 200, 211, 203, 209, 191, 153, 157, 129, 163, 170, + 164, 233, 189, 187, 163, 189, 226, 175, 175, 178, + 181, 253, 228, 145, 168, 186, 188, 176, 176, 184, + 252, 146, 162, 182, 162, 176, 162, 190, 187, 187, + 16, 11, 105, 77, 68, 90, 95, 89, 2, 87, + 65, 74, 67, 7, 84, 87, 85, 93, 81, 77, + 16, 31, 108, 82, 65, 90, 68, 88, 89, 89, + 20, 8, 42, 48, 40, 93, 111, 100, 105, 126, + 56, 35, 59, 33, 79, 105, 109, 113, 115, 122, + 116, 57, 106, 126, 119, 120, 50, 99, 98, 126, + 112, 126, 96, 47, 74, 34, 6, 10, 1, 29, + 30, 8, 1, 23, 64, 21, 7, 21, 3, 0, + 14, 91, 12, 24, 21, 26, 92, 13, 0, 26, + 19, 20, 49, 5, 27, 0, 58, 31, 58, 40, + 42, 38, 34, 42, 13, 51, 37, 51, 39, 51, + 45, 42, 52, 123, 35, 121, 10, 38, 44, 56, + 114, 110, 112, 125, 118, 17, 61, 57, 222, 206, + 218, 218, 142, 146, 140, 221, 195, 209, 193, 204, + 195, 211, 193, 215, 201, 239, 202, 216, 218, 214, + 210, 218, 146, 220, 192, 212, 196, 214, 192, 220, + 229, 229, 251, 169, 231, 252, 172, 225, 237, 224, + 235, 228, 226, 211, 246, 228, 254, 242, 246, 254, + 190, 240, 236, 248, 224, 242, 228, 248, 249, 249, + 231, 181, 131, 152, 200, 133, 129, 140, 135, 136, + 134, 195, 134, 142, 148, 199, 133, 134, 153, 148, + 141, 151, 138, 170, 146, 150, 156, 156, 135, 159, + 214, 131, 134, 148, 174, 162, 166, 174, 238, 160, + 188, 168, 176, 162, 180, 168, 169, 169, 180, 164, + 168, 186, 181, 188, 170, 186, 174, 174, 158, 186, + 163, 165, 134, 182, 166, 176, 68, 95, 8, 70, + 92, 75, 73, 95, 2, 76, 82, 1, 86, 72, + 87, 76, 78, 82, 87, 87, 30, 86, 79, 29, + 92, 70, 92, 93, 120, 88, 20, 90, 120, 111, + 109, 123, 46, 123, 117, 125, 103, 112, 32, 103, + 105, 117, 36, 102, 118, 116, 107, 112, 112, 120, + 60, 114, 96, 119, 117, 99, 101, 68, 109, 120, + 8, 4, 4, 73, 15, 1, 8, 77, 3, 0, + 3, 14, 19, 9, 16, 69, 27, 9, 29, 89, + 16, 10, 16, 17, 61, 1, 20, 20, 4, 87, + 28, 20, 57, 107, 38, 38, 58, 111, 41, 53, + 43, 48, 52, 17, 41, 52, 45, 49, 51, 52, + 54, 121, 54, 62, 47, 125, 60, 60, 36, 113, + 51, 47, 61, 38, 222, 198, 219, 202, 193, 221, + 192, 196, 192, 247, 210, 192, 194, 206, 202, 194, + 234, 215, 217, 205, 216, 208, 206, 208, 156, 241, + 197, 194, 223, 217, 209, 198, 249, 199, 233, 240, + 235, 253, 206, 228, 236, 231, 233, 239, 225, 213, + 225, 225, 243, 233, 253, 250, 234, 177, 228, 240, + 254, 221, 241, 252, 243, 197, 241, 241, 131, 153, + 141, 138, 154, 191, 141, 153, 138, 165, 129, 136, + 138, 199, 144, 138, 218, 139, 138, 150, 157, 154, + 143, 142, 210, 177, 153, 159, 146, 158, 154, 146, + 152, 174, 172, 160, 188, 170, 175, 185, 236, 187, + 173, 173, 230, 161, 173, 169, 191, 241, 246, 189, + 178, 179, 143, 164, 161, 167, 181, 188, 149, 162, + 167, 161, 69, 70, 102, 72, 67, 74, 96, 66, + 65, 72, 69, 69, 104, 115, 102, 104, 81, 27, + 27, 21, 14, 17, 31, 30, 17, 16, 19, 18, + 21, 20, 23, 22, 41, 39, 56, 39, 62, 44, + 44, 68, 108, 109, 101, 115, 38, 98, 124, 102, + 127, 107, 108, 112, 113, 113, 38, 61, 123, 103, + 117, 124, 101, 94, 122, 118, 5, 25, 26, 12, + 13, 27, 76, 15, 16, 2, 3, 10, 3, 19, + 23, 69, 10, 26, 10, 24, 19, 26, 8, 24, + 0, 0, 94, 81, 34, 24, 0, 20, 38, 107, + 43, 40, 34, 44, 57, 33, 35, 55, 37, 37, + 102, 54, 49, 36, 52, 47, 49, 45, 39, 127, + 116, 116, 114, 55, 63, 52, 37, 119, 58, 58, + 222, 139, 197, 200, 218, 204, 196, 141, 205, 209, + 196, 196, 212, 135, 213, 208, 219, 213, 204, 208, + 202, 198, 156, 149, 155, 157, 249, 223, 213, 216, + 198, 199, 239, 232, 252, 169, 236, 253, 237, 238, + 233, 230, 244, 242, 166, 247, 229, 247, 251, 246, + 253, 237, 251, 237, 239, 179, 178, 209, 226, 240, + 245, 252, 241, 225, 202, 154, 157, 136, 128, 155, + 133, 153, 155, 195, 131, 128, 136, 199, 138, 138, + 142, 219, 154, 156, 222, 207, 210, 141, 147, 135, + 152, 189, 147, 129, 145, 153, 185, 159, 141, 167, + 187, 162, 236, 160, 183, 176, 180, 225, 164, 162, + 228, 164, 180, 251, 189, 183, 171, 178, 185, 175, + 179, 167, 181, 181, 246, 163, 173, 165, 79, 127, + 90, 72, 74, 70, 66, 74, 113, 90, 77, 67, + 73, 75, 67, 9, 118, 84, 95, 94, 91, 77, + 127, 82, 92, 85, 89, 86, 122, 88, 83, 82, + 111, 121, 70, 104, 99, 106, 44, 48, 34, 47, + 32, 78, 115, 115, 116, 112, 110, 93, 119, 117, + 122, 122, 110, 77, 115, 103, 120, 49, 43, 55, + 56, 53, 57, 8, 7, 25, 11, 79, 81, 77, + 46, 12, 7, 6, 3, 21, 23, 41, 21, 28, + 31, 28, 12, 62, 12, 13, 30, 26, 19, 16, + 2, 30, 27, 27, 100, 101, 20, 103, 96, 19, + 0, 34, 37, 48, 19, 36, 52, 46, 40, 42, + 61, 55, 55, 62, 57, 62, 62, 49, 55, 0, + 36, 48, 36, 35, 116, 49, 207, 199, 205, 221, + 199, 193, 203, 141, 205, 207, 196, 129, 202, 200, + 195, 133, 220, 210, 212, 220, 205, 145, 146, 147, + 246, 214, 220, 212, 194, 222, 218, 210, 170, 237, + 225, 231, 231, 252, 228, 232, 230, 173, 204, 238, + 225, 224, 225, 247, 160, 187, 220, 252, 242, 250, + 232, 248, 178, 255, 255, 246, 182, 241, 253, 249, + 143, 152, 198, 166, 163, 138, 159, 158, 131, 132, + 133, 219, 198, 162, 156, 134, 159, 139, 140, 144, + 145, 145, 198, 221, 209, 155, 153, 149, 146, 146, + 154, 214, 137, 164, 186, 172, 130, 160, 175, 172, + 176, 170, 186, 164, 180, 171, 171, 166, 187, 183, + 189, 247, 179, 176, 185, 179, 255, 134, 131, 157, + 185, 180, 181, 185, 67, 81, 77, 91, 0, 102, + 66, 68, 86, 102, 110, 98, 71, 83, 69, 73, + 85, 92, 23, 23, 74, 75, 116, 117, 8, 94, + 93, 89, 94, 13, 89, 88, 42, 127, 124, 65, + 70, 53, 97, 96, 56, 112, 115, 105, 110, 61, + 105, 104, 32, 104, 107, 57, 106, 107, 72, 116, + 127, 118, 69, 101, 127, 123, 103, 47, 74, 2, + 6, 0, 26, 6, 13, 1, 11, 25, 1, 21, + 15, 8, 10, 75, 84, 85, 44, 16, 19, 26, + 41, 9, 27, 31, 3, 75, 86, 30, 26, 28, + 62, 34, 41, 37, 39, 53, 41, 41, 98, 48, + 53, 34, 37, 34, 55, 54, 60, 46, 52, 53, + 39, 24, 56, 46, 33, 32, 35, 107, 48, 49, + 50, 33, 206, 133, 229, 135, 215, 214, 200, 201, + 140, 238, 237, 143, 223, 222, 192, 193, 148, 246, + 245, 151, 199, 198, 197, 196, 214, 148, 159, 150, + 251, 144, 155, 146, 243, 242, 236, 237, 169, 160, + 171, 192, 207, 164, 175, 166, 255, 254, 224, 225, + 189, 180, 191, 212, 211, 184, 179, 186, 235, 234, + 233, 232, 219, 185, 240, 187, 147, 146, 165, 164, + 192, 139, 136, 195, 155, 154, 173, 172, 200, 131, + 128, 203, 131, 130, 129, 128, 179, 216, 211, 218, + 150, 212, 223, 214, 143, 142, 185, 184, 237, 228, + 239, 173, 170, 232, 227, 234, 187, 186, 141, 140, + 225, 232, 227, 161, 190, 252, 247, 254, 167, 166, + 165, 164, 145, 178, 190, 246, 162, 247, 167, 176, + 94, 11, 91, 89, 75, 76, 69, 75, 75, 64, + 0, 85, 79, 74, 65, 127, 85, 85, 93, 112, + 80, 89, 83, 29, 66, 82, 66, 80, 91, 82, + 64, 80, 120, 43, 127, 96, 122, 103, 44, 65, + 109, 96, 97, 109, 38, 115, 125, 117, 127, 79, + 112, 124, 62, 75, 117, 112, 119, 73, 127, 127, + 115, 94, 122, 115, 5, 75, 1, 26, 78, 1, + 25, 1, 14, 47, 15, 2, 7, 11, 49, 49, + 57, 91, 80, 44, 42, 60, 85, 81, 82, 83, + 0, 3, 31, 20, 17, 85, 38, 46, 62, 44, + 34, 60, 26, 2, 14, 22, 13, 4, 7, 9, + 5, 9, 3, 8, 17, 10, 1, 15, 29, 30, + 25, 18, 23, 20, 27, 2, 24, 1, 227, 244, + 233, 250, 253, 234, 248, 242, 242, 226, 227, 234, + 231, 224, 225, 230, 232, 226, 232, 237, 241, 224, + 236, 252, 241, 248, 241, 246, 243, 238, 219, 192, + 248, 171, 228, 224, 237, 234, 226, 254, 231, 163, + 228, 238, 227, 244, 234, 162, 238, 187, 249, 245, + 242, 240, 235, 189, 196, 252, 252, 228, 251, 242, + 180, 212, 132, 138, 132, 144, 157, 134, 159, 180, + 141, 150, 146, 193, 138, 142, 135, 128, 148, 136, + 157, 217, 159, 147, 144, 146, 133, 128, 208, 158, + 152, 155, 141, 213, 251, 235, 191, 172, 171, 164, + 236, 162, 164, 227, 150, 174, 170, 178, 169, 160, + 250, 154, 182, 184, 178, 166, 175, 180, 161, 154, + 190, 167, 183, 187, 189, 177, 10, 89, 77, 90, + 94, 64, 66, 94, 71, 3, 70, 83, 73, 74, + 4, 104, 85, 95, 93, 3, 30, 106, 82, 86, + 92, 92, 71, 95, 101, 78, 89, 88, 111, 127, + 122, 96, 109, 47, 77, 110, 118, 106, 118, 100, + 85, 126, 105, 104, 127, 111, 106, 112, 125, 63, + 76, 124, 97, 122, 102, 116, 85, 123, 125, 112, + 4, 31, 59, 12, 28, 25, 9, 31, 32, 17, + 15, 0, 2, 4, 5, 22, 14, 118, 114, 53, + 17, 28, 29, 17, 82, 7, 25, 28, 19, 77, + 84, 120, 64, 7, 39, 42, 47, 35, 108, 14, + 46, 44, 35, 42, 102, 8, 34, 35, 41, 62, + 44, 99, 126, 127, 49, 46, 95, 89, 32, 62, + 57, 59, 122, 59, 222, 219, 134, 198, 220, 200, + 216, 196, 207, 198, 142, 214, 207, 201, 192, 202, + 205, 200, 150, 218, 209, 210, 200, 212, 223, 214, + 158, 214, 217, 216, 211, 217, 239, 165, 235, 230, + 227, 251, 229, 224, 231, 173, 238, 232, 245, 243, + 170, 226, 245, 237, 204, 240, 243, 250, 188, 234, + 243, 224, 176, 226, 239, 249, 247, 253, 152, 132, + 134, 128, 148, 138, 136, 195, 194, 160, 149, 147, + 148, 130, 138, 145, 218, 148, 158, 159, 141, 154, + 136, 221, 218, 158, 131, 216, 204, 215, 167, 128, + 185, 187, 173, 170, 186, 170, 168, 237, 171, 173, + 163, 174, 180, 181, 161, 166, 174, 251, 183, 191, + 184, 172, 185, 169, 242, 181, 162, 190, 187, 247, + 167, 176, 88, 93, 77, 91, 20, 15, 127, 72, + 78, 70, 67, 85, 67, 67, 4, 74, 88, 81, + 93, 90, 74, 31, 95, 92, 92, 20, 68, 17, + 84, 82, 20, 70, 111, 121, 97, 104, 98, 102, + 118, 104, 102, 85, 97, 115, 111, 102, 102, 105, + 127, 59, 111, 112, 106, 119, 60, 110, 98, 118, + 115, 120, 112, 126, 113, 113, 74, 5, 9, 4, + 11, 79, 2, 2, 22, 67, 5, 25, 15, 20, + 16, 22, 29, 23, 23, 27, 31, 19, 42, 28, + 0, 26, 17, 19, 26, 18, 7, 3, 43, 57, + 33, 40, 44, 35, 41, 35, 35, 46, 37, 55, + 39, 43, 49, 32, 51, 40, 22, 44, 50, 51, + 27, 49, 61, 49, 49, 61, 0, 54, 38, 60, + 203, 201, 196, 204, 221, 129, 200, 204, 214, 247, + 210, 212, 195, 243, 203, 202, 154, 217, 209, 222, + 158, 208, 222, 215, 215, 208, 196, 243, 195, 209, + 210, 208, 248, 238, 236, 217, 252, 224, 239, 232, + 241, 240, 239, 243, 209, 238, 240, 237, 202, 233, + 241, 246, 236, 246, 232, 228, 188, 195, 226, 254, + 245, 242, 231, 230, 167, 138, 134, 144, 186, 142, + 159, 134, 145, 217, 192, 160, 136, 199, 129, 151, + 136, 148, 138, 217, 145, 156, 159, 136, 128, 150, + 148, 203, 214, 181, 129, 147, 172, 174, 186, 172, + 170, 159, 190, 162, 161, 166, 179, 178, 169, 181, + 147, 172, 174, 179, 136, 171, 183, 176, 174, 180, + 166, 170, 254, 129, 163, 164, 188, 239, 10, 106, + 70, 9, 75, 93, 94, 66, 80, 3, 79, 66, + 69, 82, 86, 64, 94, 1, 24, 112, 80, 73, + 93, 81, 91, 87, 16, 65, 68, 94, 91, 71, + 99, 127, 113, 121, 98, 122, 107, 32, 107, 109, + 115, 47, 40, 91, 42, 43, 70, 53, 54, 69, + 86, 118, 111, 105, 125, 97, 105, 71, 121, 123, + 97, 120, 15, 42, 6, 8, 2, 22, 31, 4, + 17, 54, 19, 4, 20, 51, 22, 4, 30, 30, + 11, 58, 31, 28, 20, 24, 33, 22, 4, 5, + 31, 25, 19, 6, 25, 40, 58, 32, 62, 59, + 63, 30, 33, 49, 41, 49, 50, 52, 0, 36, + 46, 58, 17, 55, 58, 54, 63, 60, 38, 60, + 34, 34, 5, 35, 38, 52, 222, 206, 207, 192, + 203, 220, 252, 193, 195, 192, 197, 238, 212, 195, + 193, 215, 233, 207, 202, 216, 202, 218, 219, 212, + 215, 192, 230, 212, 216, 211, 219, 199, 249, 233, + 225, 231, 218, 234, 225, 253, 207, 230, 228, 232, + 231, 202, 225, 246, 233, 254, 246, 254, 251, 237, + 239, 212, 252, 231, 245, 227, 224, 246, 248, 175, + 202, 134, 137, 145, 170, 138, 139, 159, 135, 134, + 175, 135, 182, 134, 150, 132, 150, 151, 157, 149, + 151, 140, 145, 190, 157, 157, 158, 148, 149, 131, + 157, 154, 164, 235, 174, 160, 160, 166, 191, 165, + 167, 167, 131, 174, 168, 169, 161, 166, 174, 178, + 183, 183, 254, 179, 179, 174, 166, 156, 162, 181, + 179, 165, 244, 182, 88, 78, 73, 93, 75, 75, + 3, 78, 67, 77, 67, 68, 74, 66, 64, 10, + 72, 94, 72, 85, 95, 92, 89, 89, 125, 65, + 84, 84, 68, 23, 82, 92, 102, 103, 109, 109, + 65, 125, 104, 104, 112, 35, 114, 100, 108, 98, + 103, 113, 127, 127, 72, 118, 109, 118, 104, 116, + 125, 125, 48, 114, 122, 120, 103, 112, 14, 47, + 13, 15, 15, 26, 0, 25, 66, 2, 12, 4, + 20, 19, 49, 21, 30, 26, 12, 28, 94, 62, + 10, 28, 27, 31, 17, 19, 26, 18, 23, 26, + 36, 37, 45, 42, 58, 38, 35, 35, 4, 42, + 46, 40, 53, 47, 33, 33, 116, 44, 57, 47, + 61, 48, 50, 51, 55, 48, 36, 56, 57, 57, + 24, 58, 217, 223, 134, 222, 207, 217, 227, 223, + 198, 198, 210, 226, 212, 194, 197, 209, 223, 223, + 150, 206, 223, 201, 211, 207, 214, 214, 194, 247, + 223, 219, 216, 208, 238, 165, 255, 232, 248, 224, + 254, 233, 231, 241, 210, 228, 236, 226, 231, 241, + 255, 255, 182, 238, 255, 233, 204, 242, 225, 250, + 228, 248, 249, 249, 215, 249, 133, 152, 141, 141, + 192, 152, 141, 155, 166, 134, 134, 128, 147, 139, + 144, 164, 150, 158, 138, 141, 208, 136, 157, 139, + 167, 131, 148, 144, 130, 146, 218, 130, 171, 189, + 147, 230, 229, 242, 145, 180, 226, 167, 156, 165, + 154, 231, 172, 153, 178, 179, 132, 177, 130, 255, + 177, 129, 191, 190, 189, 141, 236, 164, 167, 166, + 118, 88, 76, 9, 70, 15, 65, 13, 81, 111, + 73, 66, 67, 73, 71, 64, 113, 94, 65, 106, + 74, 94, 78, 73, 118, 82, 68, 84, 98, 94, + 87, 94, 121, 78, 102, 109, 74, 110, 120, 104, + 86, 106, 99, 106, 117, 78, 106, 115, 123, 119, + 113, 125, 62, 107, 115, 118, 119, 125, 48, 101, + 111, 103, 113, 47, 74, 41, 41, 58, 39, 44, + 51, 61, 35, 32, 43, 32, 33, 34, 41, 44, + 40, 41, 55, 43, 33, 43, 46, 60, 54, 58, + 62, 54, 39, 34, 53, 59, 30, 4, 31, 12, + 28, 16, 0, 4, 22, 6, 3, 19, 31, 23, + 16, 10, 5, 18, 22, 29, 23, 30, 3, 13, + 19, 16, 27, 16, 17, 18, 4, 7, 239, 230, + 225, 252, 227, 240, 252, 225, 247, 240, 255, 241, + 231, 228, 239, 228, 253, 254, 232, 246, 233, 250, + 238, 233, 224, 242, 244, 244, 229, 232, 228, 244, + 201, 192, 201, 206, 203, 223, 222, 200, 207, 202, + 213, 204, 217, 215, 197, 198, 209, 218, 223, 220, + 209, 207, 200, 212, 221, 221, 195, 206, 198, 214, + 215, 222, 171, 172, 173, 189, 190, 160, 175, 165, + 163, 177, 180, 190, 182, 166, 167, 174, 187, 188, + 189, 173, 172, 190, 184, 180, 188, 180, 175, 162, + 191, 176, 186, 180, 134, 148, 152, 136, 141, 132, + 141, 138, 135, 135, 143, 140, 149, 146, 150, 131, + 155, 152, 157, 134, 142, 158, 159, 150, 147, 148, + 149, 158, 132, 147, 145, 135, 108, 103, 103, 126, + 113, 127, 109, 110, 105, 98, 103, 100, 114, 117, + 113, 96, 126, 122, 108, 120, 97, 105, 121, 113, + 125, 112, 121, 101, 111, 116, 97, 102, 94, 68, + 69, 76, 92, 95, 94, 66, 82, 92, 76, 72, + 69, 66, 74, 86, 95, 74, 77, 88, 80, 75, + 83, 74, 87, 65, 79, 80, 82, 65, 85, 91, + 41, 46, 44, 54, 43, 62, 57, 36, 54, 58, + 49, 52, 39, 41, 48, 42, 45, 62, 42, 38, + 63, 59, 42, 60, 60, 48, 53, 53, 41, 62, + 58, 49, 3, 8, 13, 26, 31, 26, 13, 3, + 22, 12, 23, 4, 20, 24, 5, 1, 12, 26, + 22, 26, 27, 27, 3, 30, 29, 30, 29, 30, + 18, 30, 0, 12, 251, 254, 233, 231, 250, 224, + 251, 232, 240, 252, 225, 229, 240, 230, 234, 230, + 255, 255, 231, 252, 239, 234, 245, 233, 235, 236, + 243, 254, 251, 250, 251, 241, 195, 223, 193, 204, + 221, 204, 201, 201, 208, 204, 205, 192, 212, 204, + 193, 209, 222, 218, 204, 216, 193, 207, 221, 222, + 217, 210, 215, 212, 212, 246, 231, 252, 137, 168, + 154, 144, 158, 155, 131, 205, 178, 130, 131, 138, + 135, 128, 129, 168, 143, 151, 140, 144, 211, 158, + 143, 142, 151, 135, 208, 161, 151, 148, 159, 148, + 173, 174, 137, 173, 184, 174, 162, 174, 167, 167, + 224, 135, 163, 166, 176, 176, 168, 190, 171, 137, + 172, 186, 177, 180, 167, 190, 240, 129, 186, 162, + 167, 148, 70, 71, 8, 64, 64, 15, 67, 67, + 71, 117, 79, 77, 83, 74, 65, 5, 123, 85, + 89, 85, 71, 76, 85, 78, 98, 92, 71, 84, + 68, 23, 96, 71, 107, 111, 109, 122, 74, 64, + 65, 45, 113, 118, 114, 103, 103, 100, 97, 74, + 104, 127, 125, 107, 62, 89, 112, 114, 101, 71, + 64, 94, 54, 84, 124, 116, 24, 31, 39, 25, + 26, 6, 3, 3, 66, 23, 18, 0, 2, 14, + 10, 2, 57, 14, 11, 13, 17, 18, 25, 15, + 34, 1, 31, 1, 59, 30, 6, 7, 37, 57, + 104, 29, 60, 46, 40, 36, 44, 36, 20, 51, + 39, 35, 45, 43, 61, 123, 11, 32, 45, 43, + 57, 48, 33, 2, 37, 48, 56, 35, 59, 34, + 207, 217, 136, 229, 199, 219, 201, 252, 215, 194, + 206, 213, 201, 208, 193, 215, 154, 250, 220, 207, + 223, 209, 223, 216, 214, 147, 157, 145, 243, 198, + 193, 220, 254, 242, 220, 251, 251, 234, 172, 201, + 227, 247, 225, 161, 208, 226, 232, 234, 249, 242, + 236, 224, 207, 234, 253, 243, 230, 252, 231, 244, + 228, 183, 213, 241, 156, 138, 134, 138, 139, 139, + 204, 192, 194, 170, 142, 133, 143, 132, 129, 150, + 218, 211, 177, 151, 154, 154, 132, 221, 180, 213, + 191, 216, 167, 130, 149, 155, 190, 164, 191, 172, + 188, 239, 141, 169, 180, 162, 174, 162, 163, 163, + 228, 237, 153, 180, 181, 180, 177, 187, 181, 169, + 171, 250, 129, 164, 183, 185, 160, 186, 93, 78, + 90, 9, 111, 75, 90, 76, 76, 64, 69, 69, + 6, 10, 4, 96, 75, 78, 81, 77, 71, 31, + 26, 29, 113, 92, 93, 92, 89, 83, 93, 65, + 115, 72, 109, 109, 124, 96, 44, 64, 99, 113, + 107, 100, 114, 39, 96, 100, 110, 122, 91, 120, + 112, 124, 121, 113, 50, 100, 113, 120, 98, 55, + 117, 118, 9, 14, 27, 26, 78, 27, 3, 6, + 7, 13, 5, 15, 2, 20, 1, 22, 9, 18, + 23, 23, 88, 33, 90, 30, 31, 23, 95, 18, + 86, 4, 0, 20, 56, 63, 104, 49, 42, 40, + 97, 34, 50, 38, 46, 46, 54, 34, 42, 2, + 63, 47, 30, 43, 59, 58, 12, 50, 32, 39, + 25, 63, 4, 54, 58, 50, 207, 135, 136, 230, + 219, 219, 140, 194, 196, 131, 208, 206, 212, 211, + 215, 214, 207, 217, 221, 212, 223, 214, 208, 216, + 220, 199, 217, 197, 207, 134, 209, 219, 254, 226, + 252, 240, 188, 161, 172, 206, 237, 237, 246, 228, + 244, 243, 225, 247, 233, 187, 165, 185, 221, 240, + 242, 243, 247, 240, 228, 248, 249, 249, 221, 241, + 173, 153, 135, 156, 158, 194, 174, 132, 140, 130, + 142, 130, 131, 165, 141, 139, 155, 149, 155, 156, + 222, 172, 140, 146, 134, 177, 153, 159, 151, 153, + 151, 144, 234, 158, 155, 139, 167, 161, 173, 163, + 161, 166, 224, 146, 182, 168, 176, 229, 143, 136, + 154, 176, 176, 190, 178, 190, 183, 243, 150, 164, + 162, 162, 166, 176, 89, 105, 65, 71, 79, 65, + 79, 72, 2, 118, 115, 101, 114, 10, 105, 5, + 124, 78, 76, 76, 76, 90, 79, 21, 31, 26, + 24, 28, 74, 19, 29, 21, 118, 43, 40, 117, + 46, 76, 99, 120, 108, 119, 32, 60, 38, 39, + 120, 37, 78, 116, 108, 120, 114, 63, 112, 120, + 100, 118, 124, 98, 54, 42, 52, 67, 15, 25, + 27, 0, 1, 1, 63, 8, 16, 10, 1, 13, + 15, 29, 1, 23, 64, 91, 30, 24, 23, 19, + 92, 9, 29, 83, 2, 20, 5, 3, 27, 7, + 47, 107, 33, 61, 43, 34, 98, 62, 39, 55, + 52, 40, 40, 32, 55, 49, 51, 56, 51, 42, + 31, 10, 24, 114, 17, 18, 20, 16, 3, 19, + 123, 22, 226, 237, 233, 252, 234, 128, 230, 253, + 251, 226, 245, 229, 137, 237, 244, 252, 154, 147, + 239, 252, 251, 244, 249, 243, 246, 154, 241, 228, + 242, 152, 252, 254, 206, 202, 221, 205, 161, 193, + 214, 201, 195, 214, 196, 174, 213, 192, 192, 196, + 207, 223, 183, 204, 205, 219, 221, 200, 214, 188, + 197, 194, 210, 183, 188, 194, 175, 174, 163, 172, + 160, 171, 197, 174, 163, 167, 207, 162, 174, 161, + 167, 164, 190, 212, 176, 178, 186, 188, 189, 185, + 221, 185, 160, 168, 181, 182, 176, 218, 153, 140, + 140, 138, 134, 137, 227, 133, 137, 135, 131, 137, + 128, 232, 142, 149, 131, 152, 144, 159, 241, 133, + 157, 143, 151, 134, 130, 254, 151, 130, 144, 144, + 127, 121, 7, 106, 111, 107, 105, 120, 112, 12, + 99, 105, 96, 98, 113, 119, 21, 120, 98, 114, + 123, 106, 110, 18, 118, 120, 123, 116, 99, 101, + 27, 114, 72, 91, 77, 92, 92, 32, 68, 70, + 70, 70, 85, 83, 41, 79, 81, 67, 95, 78, + 74, 54, 84, 79, 69, 88, 71, 65, 63, 92, + 78, 89, 81, 64, 56, 68, 38, 38, 37, 42, + 57, 63, 77, 45, 58, 37, 35, 50, 54, 74, + 42, 55, 54, 60, 43, 45, 83, 47, 61, 61, + 53, 36, 36, 88, 38, 32, 8, 14, 29, 27, + 97, 28, 9, 6, 7, 22, 18, 110, 21, 0, + 0, 0, 15, 9, 119, 13, 12, 6, 25, 8, + 0, 124, 5, 2, 18, 18, 1, 7, 133, 254, + 251, 237, 142, 135, 251, 232, 231, 232, 229, 239, + 226, 142, 225, 240, 232, 148, 226, 248, 236, 248, + 254, 237, 157, 242, 229, 245, 241, 245, 228, 154, + 201, 202, 204, 206, 204, 223, 163, 206, 202, 197, + 199, 195, 214, 168, 199, 223, 209, 220, 218, 201, + 177, 219, 215, 214, 213, 209, 192, 190, 222, 220, + 208, 210, 168, 187, 199, 161, 187, 169, 171, 175, + 178, 204, 170, 177, 191, 160, 166, 181, 213, 182, + 160, 183, 185, 189, 172, 210, 188, 188, 187, 182, + 180, 167, 219, 187, 144, 143, 143, 139, 158, 224, + 156, 129, 140, 132, 130, 145, 233, 148, 129, 142, + 157, 153, 136, 246, 141, 152, 152, 154, 144, 131, + 255, 133, 132, 142, 147, 151, 122, 4, 125, 122, + 106, 104, 110, 125, 13, 118, 115, 101, 6, 15, + 115, 96, 127, 112, 125, 119, 122, 22, 123, 127, + 98, 28, 106, 112, 100, 127, 127, 113, 37, 65, + 88, 80, 64, 64, 71, 34, 81, 70, 75, 79, + 92, 67, 43, 70, 91, 95, 86, 67, 90, 48, + 95, 85, 84, 93, 74, 85, 57, 95, 95, 81, + 36, 49, 44, 70, 36, 63, 53, 35, 56, 39, + 79, 50, 33, 35, 42, 63, 62, 84, 45, 42, + 58, 44, 59, 57, 93, 48, 56, 55, 37, 48, + 48, 90, 2, 0, 12, 26, 9, 11, 99, 7, + 18, 26, 20, 19, 31, 104, 14, 21, 3, 14, + 11, 29, 113, 28, 29, 25, 7, 0, 20, 126, + 21, 31, 18, 0, 249, 239, 135, 234, 230, 233, + 140, 133, 245, 230, 229, 234, 227, 233, 224, 140, + 239, 232, 252, 150, 253, 241, 244, 232, 225, 247, + 159, 242, 236, 252, 225, 230, 206, 164, 204, 194, + 197, 218, 223, 201, 173, 203, 203, 197, 211, 212, + 192, 170, 211, 213, 202, 204, 205, 219, 179, 213, + 199, 213, 197, 194, 210, 184, 221, 217, 185, 190, + 187, 173, 193, 165, 188, 180, 183, 176, 164, 206, + 172, 183, 189, 197, 210, 172, 189, 188, 181, 186, + 178, 185, 219, 166, 163, 181, 217, 186, 172, 187, + 159, 152, 140, 230, 128, 128, 135, 152, 145, 135, + 239, 145, 138, 137, 145, 150, 158, 244, 138, 150, + 144, 138, 143, 153, 253, 129, 133, 147, 131, 132, + 144, 250, 121, 106, 122, 124, 125, 107, 3, 126, + 103, 104, 117, 114, 98, 8, 119, 98, 126, 110, + 107, 125, 17, 107, 116, 127, 103, 96, 116, 30, + 98, 101, 109, 96, 89, 79, 39, 83, 79, 93, + 86, 76, 80, 44, 74, 81, 95, 64, 72, 65, + 53, 88, 86, 81, 77, 83, 74, 50, 81, 93, + 88, 86, 89, 91, 80, 58, 43, 62, 44, 46, + 33, 35, 40, 66, 33, 34, 36, 38, 41, 43, + 32, 74, 57, 51, 62, 62, 49, 51, 56, 82, + 55, 38, 34, 54, 57, 59, 48, 90, 13, 9, + 24, 14, 1, 3, 8, 98, 10, 8, 4, 6, + 9, 11, 0, 106, 16, 11, 1, 30, 17, 19, + 24, 114, 28, 9, 20, 22, 25, 27, 16, 122, + 249, 236, 236, 238, 225, 227, 232, 130, 241, 234, + 236, 247, 227, 245, 247, 236, 246, 237, 253, 235, + 145, 254, 233, 249, 225, 250, 252, 231, 243, 229, + 155, 246, 203, 207, 219, 192, 194, 217, 201, 223, + 173, 192, 200, 199, 213, 206, 200, 211, 223, 201, + 183, 220, 203, 205, 207, 212, 222, 197, 213, 195, + 185, 208, 214, 197, 185, 162, 164, 191, 171, 189, + 195, 165, 169, 167, 179, 168, 170, 177, 161, 183, + 213, 177, 168, 160, 173, 182, 176, 171, 183, 161, + 223, 191, 172, 179, 167, 188, 134, 157, 141, 155, + 225, 156, 139, 137, 154, 130, 135, 238, 135, 146, + 128, 157, 155, 156, 247, 140, 141, 155, 132, 156, + 135, 252, 145, 132, 146, 143, 149, 128, 5, 110, + 125, 123, 118, 110, 121, 2, 119, 112, 100, 121, + 118, 99, 11, 112, 105, 127, 96, 105, 106, 16, + 105, 110, 118, 114, 101, 98, 4, 7, 4, 116, + 95, 88, 92, 91, 79, 67, 69, 76, 34, 49, + 48, 49, 69, 79, 77, 75, 91, 59, 89, 44, + 46, 92, 83, 77, 66, 86, 66, 84, 69, 71, + 39, 32, 47, 62, 58, 38, 62, 42, 76, 88, + 82, 38, 53, 50, 50, 63, 81, 85, 60, 41, + 57, 77, 78, 57, 46, 60, 60, 48, 53, 81, + 66, 71, 51, 48, 24, 120, 120, 14, 11, 29, + 1, 12, 12, 26, 96, 114, 118, 0, 1, 23, + 23, 26, 22, 0, 126, 108, 108, 125, 122, 30, + 25, 31, 31, 126, 19, 16, 248, 230, 233, 231, + 247, 143, 159, 157, 130, 139, 247, 228, 227, 236, + 225, 235, 254, 146, 240, 242, 249, 140, 143, 245, + 253, 253, 247, 145, 253, 248, 250, 242, 170, 184, + 187, 193, 193, 193, 203, 173, 201, 204, 206, 198, + 166, 178, 180, 204, 212, 223, 209, 216, 190, 170, + 172, 212, 198, 210, 164, 161, 220, 199, 218, 167, + 216, 222, 162, 168, 190, 174, 162, 205, 208, 209, + 213, 171, 167, 183, 165, 171, 218, 201, 202, 204, + 222, 215, 171, 184, 183, 184, 181, 191, 178, 222, + 186, 180, 153, 250, 248, 249, 128, 138, 136, 255, + 247, 141, 133, 149, 142, 130, 150, 137, 155, 149, + 156, 138, 254, 237, 233, 142, 155, 157, 151, 144, + 134, 152, 134, 144, 10, 24, 24, 122, 126, 110, + 101, 99, 2, 16, 21, 114, 118, 127, 17, 21, + 10, 104, 109, 112, 12, 15, 111, 106, 119, 0, + 0, 98, 97, 126, 103, 102, 42, 57, 56, 93, + 79, 70, 91, 76, 76, 35, 73, 79, 66, 66, + 92, 80, 81, 42, 40, 41, 75, 84, 60, 44, + 34, 35, 69, 90, 54, 38, 36, 76, 74, 44, + 33, 37, 58, 58, 63, 94, 82, 54, 51, 65, + 40, 38, 55, 69, 75, 75, 72, 44, 45, 95, + 46, 40, 33, 32, 80, 67, 70, 71, 68, 32, + 25, 107, 27, 25, 22, 111, 121, 125, 114, 22, + 19, 97, 21, 23, 28, 101, 111, 107, 104, 121, + 118, 18, 21, 19, 27, 122, 5, 2, 118, 3, + 17, 22, 226, 139, 153, 153, 158, 250, 255, 141, + 246, 230, 227, 233, 134, 150, 148, 149, 154, 147, + 245, 240, 240, 246, 149, 232, 225, 147, 231, 240, + 250, 251, 148, 230, 222, 171, 187, 185, 217, 206, + 192, 193, 162, 208, 212, 211, 195, 194, 208, 165, + 169, 171, 207, 216, 210, 211, 188, 206, 198, 193, + 213, 212, 194, 183, 167, 165, 202, 195, 165, 160, + 160, 166, 197, 190, 173, 186, 166, 163, 180, 162, + 170, 177, 218, 184, 170, 172, 186, 186, 220, 178, + 187, 191, 179, 190, 164, 185, 179, 186, 134, 143, + 143, 134, 130, 139, 236, 229, 145, 147, 143, 149, + 239, 128, 139, 137, 158, 251, 240, 138, 142, 144, + 136, 253, 159, 154, 158, 152, 255, 144, 155, 153, + 110, 11, 0, 122, 126, 96, 120, 4, 2, 11, + 119, 100, 99, 108, 97, 107, 126, 18, 107, 112, + 114, 105, 121, 111, 97, 122, 124, 103, 115, 101, + 20, 29, 89, 91, 71, 93, 39, 92, 69, 65, + 84, 70, 82, 33, 46, 84, 84, 74, 78, 59, + 85, 80, 80, 86, 53, 83, 85, 82, 67, 95, + 87, 67, 65, 71, 43, 39, 72, 46, 47, 60, + 60, 44, 46, 47, 33, 37, 47, 50, 41, 53, + 54, 58, 44, 48, 48, 42, 49, 46, 61, 42, + 50, 52, 55, 57, 39, 38, 31, 12, 9, 27, + 27, 4, 108, 15, 16, 6, 14, 21, 102, 111, + 23, 21, 21, 15, 113, 12, 13, 127, 31, 15, + 7, 23, 21, 113, 126, 4, 4, 26, 254, 130, + 253, 250, 142, 236, 254, 248, 230, 230, 128, 137, + 245, 247, 235, 241, 147, 155, 144, 238, 251, 250, + 247, 248, 252, 247, 153, 228, 229, 151, 250, 244, + 222, 222, 218, 200, 194, 175, 203, 204, 209, 163, + 168, 210, 214, 200, 208, 172, 207, 200, 215, 208, + 210, 202, 215, 210, 219, 223, 199, 212, 197, 195, + 180, 193, 175, 179, 169, 186, 206, 160, 165, 161, + 181, 171, 165, 160, 178, 164, 172, 171, 207, 203, + 201, 201, 171, 172, 178, 178, 166, 182, 197, 164, + 165, 185, 187, 161, 143, 137, 157, 135, 138, 155, + 142, 130, 140, 135, 138, 145, 136, 133, 139, 139, + 158, 142, 147, 155, 145, 145, 152, 136, 129, 243, + 225, 225, 143, 247, 128, 248, 100, 100, 124, 108, + 123, 124, 12, 31, 123, 3, 116, 12, 104, 104, + 112, 96, 111, 104, 24, 12, 103, 31, 104, 16, + 124, 124, 100, 116, 99, 100, 20, 97, 39, 73, + 71, 71, 74, 90, 95, 73, 77, 79, 76, 64, + 84, 95, 70, 81, 53, 78, 75, 93, 70, 90, + 72, 50, 71, 64, 84, 73, 84, 89, 59, 64, + 57, 47, 48, 37, 45, 64, 57, 62, 38, 59, + 50, 49, 73, 50, 55, 33, 59, 14, 11, 13, + 12, 30, 16, 20, 19, 29, 80, 53, 25, 27, + 24, 20, 56, 107, 62, 58, 96, 111, 15, 44, + 44, 34, 36, 40, 39, 41, 100, 1, 53, 55, + 52, 56, 44, 30, 41, 46, 38, 33, 49, 61, + 63, 54, 58, 117, 238, 196, 196, 197, 207, 221, + 140, 219, 209, 141, 128, 242, 209, 206, 215, 214, + 154, 253, 202, 216, 208, 220, 253, 200, 193, 199, + 194, 208, 218, 222, 213, 219, 170, 207, 231, 229, + 226, 238, 254, 173, 244, 240, 174, 161, 204, 230, + 244, 228, 244, 254, 235, 252, 190, 198, 249, 243, + 211, 230, 227, 229, 228, 246, 248, 252, 139, 133, + 200, 173, 129, 131, 128, 140, 144, 195, 150, 146, + 200, 199, 174, 132, 138, 154, 150, 156, 141, 154, + 220, 164, 151, 157, 208, 217, 161, 146, 145, 158, + 175, 165, 172, 224, 143, 186, 191, 185, 176, 162, + 172, 168, 167, 169, 228, 129, 181, 183, 180, 184, + 172, 255, 170, 174, 252, 243, 152, 190, 184, 176, + 244, 158, 69, 69, 79, 9, 106, 64, 64, 65, + 67, 81, 97, 84, 85, 83, 86, 68, 86, 82, + 89, 87, 30, 123, 83, 81, 94, 82, 66, 17, + 64, 68, 26, 21, 68, 110, 127, 41, 84, 106, + 109, 97, 99, 109, 100, 33, 66, 104, 104, 105, + 123, 105, 89, 108, 109, 107, 110, 124, 126, 122, + 113, 127, 54, 83, 123, 121, 6, 10, 26, 73, + 24, 28, 66, 77, 49, 10, 14, 6, 7, 23, + 11, 23, 31, 91, 60, 22, 18, 19, 29, 15, + 51, 6, 3, 5, 4, 22, 24, 28, 43, 37, + 104, 13, 33, 35, 32, 44, 48, 99, 54, 50, + 104, 103, 17, 22, 122, 31, 55, 53, 50, 62, + 46, 28, 39, 32, 36, 35, 55, 59, 61, 52, + 196, 139, 236, 198, 194, 195, 205, 223, 130, 213, + 211, 143, 134, 242, 247, 133, 254, 212, 212, 213, + 223, 205, 156, 149, 229, 214, 213, 218, 211, 217, + 208, 156, 201, 234, 230, 232, 234, 230, 237, 227, + 162, 199, 239, 237, 234, 230, 246, 165, 236, 232, + 182, 185, 205, 232, 245, 238, 225, 179, 214, 227, + 247, 249, 247, 214, 139, 133, 137, 141, 135, 142, + 130, 205, 166, 140, 140, 141, 135, 149, 196, 147, + 137, 213, 216, 177, 145, 145, 155, 221, 185, 156, + 158, 150, 214, 179, 155, 153, 166, 170, 186, 138, + 175, 161, 173, 169, 171, 162, 174, 225, 130, 168, + 168, 169, 187, 169, 248, 175, 173, 241, 252, 151, + 179, 163, 177, 191, 179, 164, 177, 245, 115, 78, + 70, 106, 79, 65, 77, 73, 75, 66, 78, 1, + 98, 72, 72, 73, 91, 73, 24, 79, 77, 17, + 28, 110, 91, 93, 87, 80, 70, 88, 70, 80, + 42, 79, 103, 101, 98, 110, 126, 94, 117, 106, + 115, 114, 38, 65, 118, 100, 116, 120, 56, 111, + 109, 49, 60, 85, 125, 125, 119, 49, 93, 120, + 122, 114, 74, 47, 7, 5, 2, 14, 30, 62, + 21, 10, 19, 18, 70, 33, 22, 4, 20, 24, + 88, 15, 13, 81, 92, 55, 19, 3, 17, 31, + 19, 4, 17, 85, 19, 46, 38, 26, 57, 38, + 63, 62, 98, 5, 50, 32, 40, 36, 100, 51, + 41, 117, 120, 10, 49, 42, 40, 53, 114, 18, + 54, 35, 63, 52, 53, 59, 138, 249, 201, 199, + 202, 234, 217, 223, 205, 131, 214, 210, 136, 135, + 229, 208, 201, 207, 202, 216, 210, 214, 221, 211, + 146, 247, 223, 221, 218, 214, 198, 240, 255, 249, + 231, 169, 248, 252, 162, 173, 193, 226, 238, 224, + 226, 238, 229, 235, 186, 223, 247, 245, 242, 254, + 238, 216, 231, 225, 255, 177, 224, 228, 186, 181, + 185, 156, 129, 154, 157, 207, 170, 159, 131, 141, + 131, 164, 147, 149, 139, 197, 140, 136, 214, 217, + 189, 133, 153, 158, 154, 211, 187, 158, 132, 130, + 154, 148, 143, 190, 186, 166, 238, 185, 191, 227, + 226, 135, 161, 175, 175, 180, 172, 229, 145, 169, + 183, 183, 187, 154, 169, 175, 189, 243, 166, 162, + 248, 247, 150, 167, 67, 95, 65, 90, 70, 15, + 124, 66, 87, 77, 68, 100, 83, 85, 75, 5, + 76, 72, 22, 25, 118, 80, 82, 90, 18, 120, + 95, 95, 81, 23, 112, 90, 102, 103, 105, 123, + 75, 122, 126, 98, 34, 117, 115, 47, 38, 79, + 113, 107, 125, 122, 106, 112, 127, 113, 60, 91, + 125, 97, 121, 127, 98, 82, 97, 103, 5, 75, + 30, 26, 64, 79, 38, 12, 18, 2, 14, 4, + 21, 2, 68, 60, 31, 21, 61, 12, 12, 16, + 92, 11, 1, 93, 80, 60, 19, 15, 29, 22, + 43, 37, 104, 25, 43, 60, 35, 8, 55, 49, + 47, 97, 48, 52, 106, 101, 20, 52, 42, 46, + 59, 56, 53, 60, 60, 115, 27, 35, 57, 57, + 49, 16, 223, 217, 199, 137, 216, 220, 130, 141, + 236, 198, 215, 129, 252, 194, 197, 201, 219, 213, + 220, 153, 250, 208, 208, 209, 211, 193, 245, 196, + 196, 216, 148, 195, 249, 165, 168, 217, 225, 227, + 229, 254, 234, 163, 218, 237, 233, 243, 253, 192, + 239, 233, 247, 185, 232, 236, 178, 189, 192, 252, + 253, 240, 248, 254, 245, 251, 202, 167, 141, 156, + 171, 154, 158, 130, 194, 149, 147, 207, 198, 181, + 145, 150, 137, 146, 153, 151, 222, 173, 137, 159, + 158, 150, 181, 132, 132, 152, 212, 131, 185, 229, + 232, 154, 185, 170, 168, 164, 177, 171, 224, 138, + 180, 168, 170, 164, 159, 174, 170, 182, 254, 169, + 175, 243, 242, 128, 185, 191, 177, 182, 164, 186, + 88, 78, 8, 109, 65, 67, 64, 76, 80, 102, + 85, 83, 73, 7, 82, 86, 20, 27, 108, 76, + 76, 84, 85, 78, 90, 19, 124, 88, 68, 86, + 113, 64, 120, 100, 40, 127, 125, 33, 44, 88, + 81, 35, 68, 110, 106, 107, 101, 119, 95, 110, + 106, 118, 62, 105, 111, 51, 50, 70, 67, 49, + 82, 120, 120, 121, 11, 25, 72, 65, 57, 10, + 9, 6, 7, 13, 4, 72, 35, 18, 22, 10, + 90, 13, 11, 87, 94, 44, 19, 8, 6, 27, + 80, 48, 16, 5, 29, 22, 43, 37, 104, 27, + 47, 33, 40, 15, 48, 42, 52, 40, 53, 47, + 100, 21, 53, 46, 54, 61, 126, 41, 47, 115, + 114, 18, 37, 34, 34, 37, 53, 57, 195, 202, + 198, 137, 234, 192, 192, 193, 195, 209, 226, 211, + 207, 211, 205, 214, 210, 155, 232, 214, 203, 209, + 216, 157, 196, 192, 158, 145, 245, 214, 218, 212, + 238, 226, 233, 231, 174, 203, 227, 225, 238, 226, + 242, 195, 244, 238, 240, 236, 233, 243, 184, 201, + 241, 234, 242, 249, 178, 229, 227, 191, 182, 196, + 227, 252, 153, 152, 200, 175, 156, 142, 130, 142, + 160, 145, 137, 149, 143, 148, 140, 197, 170, 148, + 141, 151, 154, 223, 138, 142, 220, 211, 179, 139, + 147, 148, 156, 213, 129, 164, 186, 188, 160, 174, + 142, 191, 171, 183, 169, 178, 174, 231, 148, 170, + 175, 181, 188, 249, 168, 172, 242, 253, 150, 178, + 190, 184, 165, 191, 244, 158, 88, 68, 70, 76, + 108, 93, 69, 89, 75, 80, 72, 1, 118, 72, + 81, 75, 94, 27, 78, 74, 16, 31, 116, 82, + 92, 84, 16, 122, 89, 89, 83, 21, 78, 100, + 100, 101, 111, 125, 78, 127, 107, 119, 105, 114, + 110, 39, 84, 106, 111, 117, 124, 57, 104, 108, + 50, 61, 90, 102, 126, 118, 119, 101, 125, 116, + 4, 75, 46, 6, 28, 6, 2, 25, 32, 17, + 9, 21, 15, 20, 12, 69, 42, 20, 13, 23, + 26, 95, 10, 14, 92, 83, 58, 16, 6, 22, + 26, 16, 57, 46, 104, 16, 43, 33, 14, 63, + 43, 55, 41, 50, 46, 103, 20, 42, 47, 53, + 60, 121, 40, 44, 114, 125, 31, 54, 40, 56, + 53, 54, 58, 117, 250, 206, 219, 198, 236, 221, + 197, 217, 203, 208, 200, 129, 246, 200, 209, 203, + 222, 155, 206, 202, 144, 159, 242, 210, 192, 196, + 213, 214, 223, 214, 218, 149, 193, 249, 231, 231, + 235, 205, 254, 228, 246, 234, 243, 233, 166, 215, + 235, 240, 244, 255, 184, 239, 237, 177, 188, 211, + 247, 228, 176, 203, 243, 246, 248, 244, 132, 143, + 200, 173, 129, 131, 128, 140, 144, 161, 146, 136, + 146, 142, 151, 141, 218, 171, 151, 140, 144, 155, + 220, 139, 129, 221, 208, 161, 153, 155, 157, 134, + 162, 235, 146, 165, 161, 187, 181, 143, 176, 170, + 180, 168, 181, 175, 228, 149, 181, 174, 182, 189, + 254, 169, 175, 243, 242, 128, 167, 180, 178, 190, + 167, 189, 10, 96, 90, 70, 64, 78, 110, 95, + 75, 87, 73, 82, 78, 7, 116, 74, 79, 85, + 92, 25, 72, 76, 18, 29, 97, 90, 94, 86, + 87, 71, 91, 71, 111, 43, 76, 102, 98, 99, + 109, 127, 64, 113, 105, 117, 111, 116, 108, 37, + 74, 116, 109, 119, 122, 63, 106, 110, 60, 51, + 68, 100, 100, 124, 125, 102, 2, 75, 36, 0, + 28, 14, 46, 31, 11, 23, 9, 18, 14, 71, + 52, 10, 15, 21, 28, 89, 8, 12, 82, 93, + 39, 32, 80, 53, 25, 27, 24, 20, 56, 9, + 58, 32, 58, 38, 63, 37, 98, 19, 47, 52, + 40, 35, 100, 51, 41, 117, 120, 12, 13, 127, + 24, 50, 62, 63, 49, 35, 118, 127, 3, 48, + 207, 192, 205, 199, 202, 134, 238, 223, 203, 215, + 201, 210, 206, 135, 244, 202, 207, 213, 220, 153, + 200, 204, 146, 157, 225, 220, 197, 197, 222, 151, + 245, 211, 248, 226, 235, 232, 224, 175, 222, 236, + 236, 231, 200, 238, 232, 224, 164, 206, 245, 245, + 255, 185, 218, 240, 240, 241, 243, 225, 176, 231, + 229, 185, 180, 223, 139, 155, 137, 135, 139, 156, + 137, 205, 187, 134, 142, 175, 137, 149, 147, 128, + 157, 146, 153, 151, 222, 180, 142, 146, 156, 150, + 208, 135, 133, 217, 212, 166, 189, 174, 172, 160, + 189, 167, 236, 134, 176, 172, 174, 160, 136, 162, + 179, 229, 128, 190, 185, 181, 191, 177, 184, 253, + 150, 188, 188, 189, 183, 165, 244, 163, 89, 5, + 8, 106, 79, 65, 77, 73, 75, 66, 78, 1, + 98, 72, 72, 73, 91, 73, 118, 92, 73, 31, + 102, 88, 83, 95, 81, 95, 82, 23, 112, 90, + 102, 103, 105, 123, 46, 121, 127, 35, 34, 80, + 119, 104, 117, 116, 36, 67, 104, 122, 118, 122, + 80, 122, 107, 61, 72, 118, 113, 125, 119, 121, + 112, 53, 46, 4, 4, 5, 15, 29, 76, 27, + 17, 77, 64, 41, 9, 9, 3, 69, 49, 20, + 22, 30, 94, 59, 19, 17, 30, 18, 2, 63, + 19, 0, 84, 47, 47, 42, 36, 40, 32, 43, + 108, 9, 45, 47, 44, 32, 52, 103, 50, 54, + 116, 123, 18, 56, 46, 62, 50, 56, 33, 54, + 112, 8, 51, 57, 26, 48, 221, 139, 242, 204, + 207, 195, 205, 195, 198, 131, 228, 206, 202, 203, + 197, 215, 154, 205, 203, 151, 158, 236, 213, 211, + 213, 210, 192, 222, 196, 210, 148, 241, 229, 231, + 228, 232, 252, 193, 233, 250, 162, 217, 229, 224, + 234, 230, 234, 225, 186, 223, 247, 245, 242, 254, + 238, 189, 228, 224, 190, 177, 195, 196, 180, 209, + 133, 135, 132, 136, 156, 188, 133, 131, 133, 130, + 144, 142, 148, 130, 196, 161, 149, 151, 148, 152, + 140, 223, 138, 142, 220, 211, 163, 134, 159, 132, + 135, 213, 140, 185, 169, 167, 173, 156, 165, 163, + 165, 162, 176, 174, 180, 162, 228, 129, 181, 183, + 180, 184, 172, 255, 170, 174, 252, 243, 152, 190, + 184, 176, 244, 158, 69, 69, 79, 9, 106, 64, + 64, 65, 67, 81, 115, 72, 72, 64, 69, 85, + 85, 73, 93, 25, 122, 80, 80, 81, 83, 65, + 16, 71, 69, 25, 20, 127, 107, 123, 105, 103, + 107, 124, 105, 45, 91, 102, 110, 85, 115, 117, + 111, 108, 105, 115, 56, 85, 119, 109, 125, 61, + 100, 96, 62, 49, 92, 118, 100, 116, 4, 14, + 27, 12, 78, 54, 9, 3, 55, 48, 64, 37, + 9, 11, 8, 4, 8, 91, 14, 10, 80, 95, + 63, 28, 28, 18, 20, 24, 23, 25, 84, 49, + 37, 39, 36, 40, 60, 26, 31, 109, 6, 44, + 44, 45, 39, 53, 100, 51, 41, 117, 120, 10, + 41, 54, 47, 46, 114, 21, 34, 48, 56, 52, + 1, 6, 138, 239, 199, 197, 194, 206, 222, 141, + 212, 208, 142, 129, 245, 208, 205, 214, 201, 155, + 254, 203, 223, 209, 223, 157, 154, 228, 213, 212, + 221, 210, 218, 209, 163, 222, 219, 169, 202, 224, + 224, 225, 227, 241, 160, 247, 245, 169, 164, 198, + 242, 242, 246, 252, 237, 250, 188, 196, 231, 242, + 254, 196, 197, 183, 208, 250, 134, 135, 137, 155, + 206, 153, 159, 195, 194, 160, 154, 132, 133, 143, + 196, 174, 149, 137, 141, 151, 159, 170, 175, 221, + 182, 156, 156, 157, 151, 133, 212, 131, 185, 229, + 232, 141, 175, 161, 165, 190, 170, 227, 139, 179, + 169, 169, 161, 144, 137, 251, 156, 182, 178, 179, + 189, 175, 242, 165, 163, 255, 246, 159, 187, 187, + 77, 11, 99, 70, 64, 72, 12, 105, 77, 79, + 76, 64, 84, 114, 119, 5, 126, 84, 84, 85, + 95, 77, 28, 75, 65, 29, 16, 120, 88, 83, + 93, 84, 100, 43, 90, 124, 126, 106, 105, 88, + 81, 35, 68, 110, 106, 107, 101, 119, 58, 109, + 107, 55, 62, 87, 105, 115, 117, 114, 98, 120, + 119, 121, 52, 83, 5, 25, 1, 7, 26, 58, + 63, 77, 38, 12, 12, 13, 7, 21, 68, 19, + 9, 85, 88, 48, 13, 13, 29, 24, 30, 26, + 80, 63, 19, 0, 84, 38, 34, 46, 57, 44, + 34, 26, 31, 109, 6, 44, 44, 45, 39, 53, + 100, 51, 41, 117, 120, 19, 63, 47, 61, 51, + 55, 32, 53, 113, 15, 50, 58, 0, 249, 139, + 236, 198, 194, 195, 205, 223, 130, 213, 211, 143, + 134, 237, 197, 213, 219, 213, 221, 202, 219, 159, + 229, 216, 220, 147, 152, 230, 211, 210, 223, 208, + 228, 239, 161, 220, 221, 175, 200, 226, 238, 239, + 225, 243, 166, 241, 247, 171, 186, 214, 253, 225, + 247, 252, 253, 243, 178, 195, 245, 226, 249, 194, + 199, 181, 174, 132, 132, 133, 143, 157, 204, 155, + 145, 205, 192, 175, 137, 149, 147, 128, 157, 146, + 153, 151, 222, 180, 142, 146, 156, 150, 165, 162, + 214, 179, 155, 153, 166, 170, 186, 233, 184, 188, + 226, 237, 146, 172, 172, 168, 181, 175, 228, 159, + 182, 180, 172, 160, 139, 172, 252, 153, 189, 191, + 188, 176, 164, 247, 162, 166, 4, 11, 122, 70, + 67, 78, 66, 68, 67, 77, 0, 109, 67, 82, + 113, 118, 26, 127, 87, 85, 82, 94, 78, 29, + 68, 64, 30, 17, 100, 66, 71, 70, 99, 106, + 102, 41, 92, 122, 110, 97, 103, 86, 83, 33, + 66, 104, 104, 105, 123, 105, 56, 111, 109, 49, + 60, 78, 115, 102, 116, 120, 54, 86, 102, 116, + 8, 2, 9, 7, 78, 61, 5, 20, 3, 15, + 53, 50, 70, 35, 11, 9, 22, 26, 10, 89, + 8, 12, 82, 93, 33, 4, 21, 21, 31, 4, + 28, 85, 1, 57, 39, 39, 47, 26, 31, 109, + 6, 44, 44, 45, 39, 53, 100, 51, 41, 117, + 120, 10, 55, 49, 59, 60, 34, 60, 34, 52, + 118, 19, 59, 57, 198, 202, 218, 252, 253, 143, + 232, 194, 206, 207, 193, 211, 134, 209, 215, 139, + 154, 239, 208, 216, 215, 159, 254, 220, 218, 199, + 229, 226, 150, 243, 219, 217, 230, 234, 250, 169, + 248, 252, 162, 173, 214, 246, 242, 234, 239, 244, + 236, 165, 214, 242, 234, 248, 203, 204, 188, 217, + 253, 255, 252, 240, 228, 183, 226, 230, 196, 203, + 187, 134, 155, 155, 132, 205, 163, 133, 146, 136, + 133, 134, 138, 197, 168, 154, 150, 157, 173, 144, + 137, 137, 154, 211, 177, 151, 132, 158, 151, 148, + 164, 235, 154, 168, 160, 171, 236, 187, 177, 237, + 224, 139, 167, 183, 165, 171, 191, 168, 189, 249, + 135, 186, 178, 154, 189, 191, 180, 241, 160, 164, + 250, 245, 105, 67, 65, 71, 75, 92, 73, 13, + 123, 86, 65, 79, 117, 78, 72, 83, 95, 73, + 24, 79, 77, 17, 28, 126, 90, 90, 94, 84, + 69, 82, 20, 108, 127, 106, 102, 78, 97, 99, + 104, 45, 116, 112, 46, 33, 71, 114, 119, 113, + 104, 122, 116, 112, 127, 113, 60, 89, 125, 127, + 124, 112, 100, 80, 123, 121, 14, 75, 30, 26, + 64, 79, 47, 12, 12, 2, 4, 8, 7, 9, + 68, 33, 21, 23, 20, 24, 12, 56, 19, 17, + 22, 83, 6, 2, 88, 87, 39, 2, 35, 56, + 59, 105, 8, 61, 45, 35, 33, 4, 47, 45, + 34, 103, 50, 54, 116, 123, 29, 44, 44, 48, + 27, 50, 62, 55, 112, 39, 37, 121, 116, 23, + 216, 194, 220, 192, 221, 199, 140, 253, 205, 214, + 206, 197, 225, 200, 200, 193, 154, 205, 203, 151, + 158, 247, 211, 211, 213, 147, 251, 222, 216, 208, + 148, 241, 229, 231, 228, 232, 252, 200, 227, 225, + 230, 163, 246, 242, 168, 167, 206, 228, 234, 250, + 246, 252, 237, 250, 188, 196, 247, 253, 215, 254, + 250, 243, 180, 227, 153, 197, 200, 167, 139, 152, + 204, 183, 135, 130, 140, 128, 136, 131, 196, 161, + 149, 151, 148, 152, 140, 184, 147, 145, 150, 211, + 134, 130, 216, 215, 167, 156, 164, 172, 169, 185, + 161, 189, 169, 237, 134, 172, 172, 173, 167, 181, + 131, 170, 182, 191, 248, 175, 173, 241, 252, 142, + 187, 191, 166, 180, 164, 132, 189, 185, 92, 78, + 90, 9, 88, 92, 2, 13, 99, 86, 83, 85, + 84, 70, 72, 76, 91, 85, 24, 125, 81, 83, + 80, 92, 64, 96, 89, 93, 64, 82, 70, 21, + 124, 120, 38, 41, 77, 110, 98, 108, 102, 106, + 97, 111, 38, 67, 107, 105, 118, 122, 106, 74, + 119, 115, 106, 120, 96, 51, 102, 98, 56, 55, + 82, 103, 11, 5, 11, 58, 7, 3, 26, 8, + 16, 67, 22, 18, 72, 71, 33, 16, 8, 20, + 43, 16, 18, 9, 25, 15, 82, 5, 3, 95, + 86, 39, 27, 0, 36, 47, 27, 32, 34, 57, + 41, 63, 98, 53, 51, 111, 102, 15, 43, 43, + 61, 123, 19, 54, 48, 56, 124, 25, 61, 63, + 60, 48, 36, 4, 61, 57, 220, 206, 218, 137, + 216, 220, 130, 141, 232, 194, 208, 192, 200, 194, + 215, 192, 154, 226, 221, 215, 237, 214, 208, 203, + 215, 193, 144, 199, 197, 153, 148, 251, 239, 252, + 168, 211, 235, 238, 224, 236, 236, 231, 160, 197, + 233, 235, 232, 228, 232, 200, 241, 245, 232, 250, + 238, 189, 228, 224, 190, 177, 197, 254, 250, 242, + 139, 155, 135, 155, 139, 207, 168, 130, 142, 143, + 129, 147, 181, 151, 139, 145, 218, 168, 145, 149, + 136, 154, 142, 174, 130, 156, 132, 209, 177, 152, + 152, 145, 153, 187, 167, 189, 238, 159, 173, 161, + 174, 162, 164, 168, 179, 170, 151, 181, 181, 175, + 248, 137, 178, 190, 168, 180, 188, 166, 189, 130, + 240, 135, 251, 148, 121, 115, 8, 64, 64, 75, + 73, 85, 2, 76, 70, 1, 103, 82, 87, 81, + 72, 90, 84, 80, 95, 81, 28, 81, 91, 64, + 68, 84, 82, 23, 71, 93, 107, 121, 109, 122, + 79, 92, 84, 45, 81, 83, 73, 33, 52, 55, + 52, 37, 95, 106, 109, 112, 106, 102, 60, 84, + 124, 119, 117, 105, 54, 84, 82, 81, 74, 40, + 7, 7, 26, 29, 13, 14, 22, 32, 8, 8, + 8, 6, 68, 36, 79, 75, 88, 16, 16, 27, + 25, 5, 82, 28, 22, 81, 53, 31, 29, 27, + 47, 56, 45, 105, 34, 38, 63, 57, 39, 39, + 96, 50, 46, 38, 54, 32, 41, 24, 55, 41, + 46, 58, 46, 125, 27, 61, 52, 52, 46, 30, + 22, 16, 242, 139, 155, 156, 142, 198, 194, 201, + 199, 219, 128, 206, 192, 135, 247, 213, 219, 213, + 209, 202, 214, 159, 208, 212, 193, 199, 213, 213, + 150, 196, 220, 212, 248, 238, 251, 218, 218, 192, + 212, 213, 183, 179, 197, 161, 195, 246, 241, 236, + 238, 226, 184, 208, 240, 251, 249, 229, 178, 208, + 214, 213, 182, 212, 251, 251, 158, 153, 137, 138, + 154, 170, 153, 159, 141, 195, 179, 149, 137, 159, + 156, 197, 207, 203, 216, 144, 144, 155, 153, 133, + 210, 156, 150, 209, 179, 130, 134, 154, 186, 174, + 169, 167, 238, 163, 165, 190, 182, 166, 164, 225, + 181, 175, 165, 183, 191, 168, 155, 152, 157, 255, + 232, 237, 242, 186, 190, 181, 179, 175, 244, 186, + 76, 11, 110, 91, 75, 65, 79, 69, 2, 79, + 73, 82, 82, 66, 64, 5, 73, 83, 89, 75, + 91, 76, 127, 124, 113, 19, 4, 1, 22, 114, + 69, 64, 99, 127, 113, 41, 71, 97, 104, 104, + 122, 35, 67, 71, 66, 39, 71, 106, 116, 111, + 106, 120, 125, 107, 88, 92, 74, 51, 121, 127, + 114, 114, 108, 53, 5, 13, 72, 46, 11, 29, + 1, 12, 12, 67, 12, 8, 21, 19, 1, 1, + 90, 8, 16, 24, 12, 26, 15, 57, 51, 43, + 80, 66, 70, 87, 49, 4, 63, 34, 60, 48, + 110, 6, 34, 41, 39, 59, 96, 2, 0, 3, + 100, 6, 53, 53, 44, 43, 63, 60, 40, 25, + 19, 11, 112, 98, 102, 119, 17, 36, 223, 194, + 220, 208, 142, 230, 194, 201, 199, 219, 128, 236, + 207, 201, 205, 133, 249, 253, 252, 153, 253, 208, + 210, 201, 192, 210, 211, 197, 242, 246, 236, 149, + 185, 187, 168, 204, 255, 250, 229, 249, 251, 163, + 201, 239, 226, 226, 252, 165, 217, 221, 220, 185, + 221, 240, 242, 233, 224, 242, 243, 229, 182, 191, + 195, 240, 143, 128, 141, 135, 138, 198, 164, 140, + 140, 132, 192, 178, 131, 137, 131, 197, 147, 149, + 156, 156, 134, 223, 147, 155, 210, 187, 159, 159, + 145, 215, 191, 154, 164, 172, 232, 165, 167, 188, + 184, 168, 166, 227, 179, 169, 167, 181, 161, 182, + 146, 186, 182, 190, 254, 140, 185, 179, 181, 243, + 185, 191, 178, 178, 172, 245, 69, 77, 8, 97, + 65, 65, 75, 13, 105, 76, 78, 70, 6, 75, + 77, 86, 78, 94, 92, 25, 77, 87, 93, 79, + 87, 64, 16, 114, 112, 115, 124, 84, 100, 108, + 40, 90, 107, 97, 107, 45, 71, 114, 117, 104, + 114, 126, 36, 76, 116, 127, 125, 97, 62, 92, + 90, 89, 50, 80, 127, 127, 98, 101, 117, 118, + 30, 34, 6, 13, 7, 14, 76, 88, 82, 67, + 9, 15, 2, 2, 28, 69, 21, 29, 88, 48, + 16, 27, 21, 28, 28, 83, 28, 24, 5, 3, + 17, 17, 106, 56, 32, 40, 60, 42, 63, 11, + 22, 16, 5, 97, 11, 14, 6, 101, 51, 53, + 60, 60, 38, 127, 51, 59, 114, 26, 36, 48, + 58, 62, 53, 59, 138, 199, 193, 218, 218, 202, + 200, 141, 209, 203, 193, 211, 195, 212, 234, 204, + 209, 208, 221, 208, 158, 141, 142, 136, 146, 218, + 222, 213, 211, 207, 148, 218, 236, 171, 194, 232, + 254, 238, 226, 232, 241, 230, 160, 237, 239, 244, + 240, 224, 254, 187, 235, 241, 255, 237, 249, 238, + 220, 250, 251, 250, 243, 254, 180, 167, 216, 222, + 200, 172, 159, 154, 133, 153, 155, 195, 169, 143, + 130, 130, 156, 197, 185, 189, 188, 217, 189, 144, + 146, 137, 128, 146, 147, 133, 184, 158, 159, 158, + 175, 162, 232, 251, 252, 250, 236, 136, 179, 182, + 169, 181, 191, 231, 141, 171, 190, 190, 160, 249, + 157, 153, 152, 253, 145, 188, 190, 165, 164, 182, + 183, 161, 10, 3, 127, 76, 75, 68, 73, 67, + 70, 10, 116, 100, 101, 111, 4, 20, 10, 11, + 24, 80, 80, 91, 89, 69, 18, 92, 86, 17, + 99, 100, 20, 89, 99, 120, 124, 108, 106, 47, + 127, 101, 99, 113, 101, 114, 72, 98, 96, 96, + 104, 119, 121, 119, 122, 63, 46, 40, 50, 80, + 113, 98, 126, 55, 93, 123, 14, 14, 16, 40, + 43, 55, 76, 4, 12, 7, 5, 25, 70, 8, + 2, 69, 50, 20, 20, 21, 31, 17, 24, 90, + 1, 83, 28, 24, 5, 3, 17, 17, 106, 56, + 32, 40, 60, 42, 63, 109, 1, 5, 4, 8, + 40, 35, 33, 61, 122, 52, 62, 121, 42, 48, + 44, 125, 1, 20, 8, 113, 37, 63, 53, 39, + 207, 216, 136, 234, 232, 235, 229, 239, 231, 251, + 128, 146, 147, 135, 225, 212, 207, 210, 204, 192, + 158, 246, 210, 217, 215, 203, 144, 242, 240, 243, + 148, 246, 229, 229, 252, 251, 239, 236, 248, 222, + 164, 211, 160, 180, 182, 183, 164, 236, 244, 255, + 253, 225, 190, 240, 250, 189, 199, 192, 176, 253, + 255, 228, 224, 240, 142, 203, 155, 129, 143, 157, + 137, 158, 177, 148, 137, 146, 149, 199, 169, 132, + 136, 144, 157, 141, 222, 182, 146, 153, 151, 139, + 208, 158, 144, 215, 167, 130, 163, 184, 187, 233, + 162, 166, 191, 185, 167, 167, 224, 178, 174, 166, + 182, 160, 169, 148, 149, 129, 254, 140, 168, 178, + 177, 184, 184, 190, 186, 186, 244, 230, 26, 11, + 97, 71, 74, 74, 84, 126, 111, 106, 0, 103, + 83, 83, 81, 87, 95, 72, 24, 122, 120, 123, + 104, 92, 91, 68, 81, 95, 22, 94, 90, 81, + 111, 115, 40, 102, 104, 47, 88, 108, 107, 116, + 97, 111, 99, 116, 97, 37, 118, 114, 107, 109, + 123, 123, 60, 110, 122, 114, 98, 116, 101, 81, + 64, 70, 47, 75, 89, 89, 94, 79, 5, 3, + 6, 6, 24, 65, 9, 1, 68, 48, 49, 91, + 20, 16, 13, 11, 25, 25, 82, 0, 24, 16, + 4, 18, 7, 51, 30, 24, 13, 105, 127, 127, + 124, 109, 7, 50, 53, 40, 50, 62, 100, 12, + 52, 63, 61, 33, 126, 28, 26, 25, 114, 16, + 63, 63, 34, 37, 53, 54, 222, 231, 199, 199, + 201, 143, 235, 196, 206, 215, 128, 231, 211, 211, + 209, 215, 223, 200, 152, 250, 248, 251, 245, 211, + 214, 214, 200, 145, 217, 209, 148, 193, 229, 251, + 168, 186, 190, 175, 255, 229, 227, 241, 229, 242, + 166, 232, 234, 165, 205, 250, 244, 245, 190, 204, + 232, 239, 247, 246, 228, 223, 215, 196, 208, 212, + 187, 203, 217, 217, 222, 207, 133, 131, 134, 134, + 152, 193, 137, 129, 196, 176, 169, 219, 148, 144, + 141, 139, 153, 153, 210, 128, 152, 144, 132, 146, + 135, 213, 137, 141, 140, 155, 187, 188, 191, 168, + 174, 175, 224, 243, 246, 247, 244, 229, 147, 181, + 188, 188, 166, 255, 145, 180, 188, 186, 240, 151, + 163, 163, 161, 167, 79, 88, 8, 106, 104, 107, + 127, 11, 114, 3, 21, 17, 22, 7, 97, 84, + 79, 82, 76, 64, 30, 118, 82, 89, 87, 75, + 16, 114, 112, 115, 20, 118, 101, 101, 124, 123, + 111, 108, 120, 94, 36, 83, 32, 52, 54, 55, + 36, 64, 107, 110, 113, 109, 103, 63, 85, 115, + 118, 118, 104, 49, 91, 126, 122, 124, 74, 40, + 46, 45, 78, 44, 3, 3, 22, 17, 1, 2, + 18, 41, 5, 22, 30, 26, 9, 89, 79, 79, + 76, 93, 55, 2, 5, 24, 2, 14, 84, 60, + 36, 47, 45, 49, 110, 12, 10, 9, 98, 0, + 47, 47, 50, 53, 37, 38, 46, 21, 57, 42, + 58, 62, 45, 125, 99, 99, 96, 113, 19, 38, + 33, 60, 222, 210, 136, 224, 192, 203, 201, 213, + 130, 238, 201, 207, 207, 135, 231, 227, 254, 155, + 251, 214, 208, 203, 206, 220, 209, 199, 249, 223, + 210, 210, 204, 149, 229, 237, 168, 253, 230, 234, + 172, 249, 237, 243, 160, 242, 238, 230, 246, 224, + 233, 187, 247, 247, 190, 200, 253, 241, 254, 179, + 195, 229, 228, 242, 241, 225, 202, 168, 174, 173, + 170, 128, 155, 205, 168, 140, 142, 132, 149, 199, + 215, 213, 218, 190, 137, 140, 151, 139, 133, 221, + 187, 157, 148, 148, 142, 215, 183, 179, 142, 235, + 139, 166, 160, 187, 190, 172, 161, 183, 132, 174, + 177, 231, 142, 170, 180, 190, 171, 249, 237, 239, + 252, 152, 163, 166, 185, 165, 175, 247, 157, 187, + 78, 78, 80, 9, 99, 70, 66, 68, 2, 96, + 102, 101, 6, 100, 75, 75, 78, 73, 89, 90, + 74, 108, 83, 68, 80, 86, 81, 95, 117, 69, + 65, 81, 111, 43, 71, 96, 98, 47, 36, 79, + 112, 102, 110, 117, 47, 68, 107, 119, 116, 59, + 126, 108, 106, 106, 110, 120, 97, 51, 83, 87, + 82, 80, 123, 121, 14, 75, 59, 25, 1, 27, + 43, 2, 14, 7, 64, 50, 22, 8, 16, 69, + 60, 35, 88, 58, 17, 17, 8, 15, 19, 16, + 4, 54, 25, 27, 16, 85, 25, 59, 39, 61, + 110, 2, 37, 35, 43, 99, 6, 25, 102, 4, + 43, 43, 46, 41, 57, 58, 42, 24, 51, 49, + 54, 115, 3, 33, 57, 35, 116, 19, 242, 139, + 235, 198, 192, 219, 222, 204, 193, 215, 128, 137, + 241, 194, 193, 206, 223, 213, 220, 144, 237, 214, + 208, 203, 215, 193, 144, 226, 198, 216, 192, 230, + 227, 231, 254, 236, 252, 175, 223, 253, 237, 247, + 160, 199, 222, 167, 199, 234, 244, 239, 234, 248, + 253, 235, 207, 244, 254, 229, 245, 227, 182, 196, + 228, 250, 158, 203, 165, 128, 128, 134, 204, 171, + 186, 195, 163, 142, 136, 147, 150, 132, 153, 143, + 171, 137, 145, 139, 220, 179, 147, 135, 133, 131, + 151, 155, 212, 178, 171, 184, 134, 168, 186, 186, + 190, 172, 174, 227, 135, 160, 181, 231, 162, 176, + 174, 174, 170, 188, 173, 255, 159, 155, 150, 131, + 177, 189, 186, 182, 176, 188, 95, 70, 8, 95, + 93, 1, 12, 120, 113, 3, 100, 78, 74, 75, + 69, 87, 106, 87, 89, 77, 87, 81, 73, 80, + 18, 69, 67, 31, 22, 98, 103, 21, 78, 100, + 100, 101, 111, 125, 95, 98, 123, 97, 101, 96, + 104, 116, 36, 99, 111, 111, 109, 107, 123, 108, + 60, 94, 84, 87, 67, 100, 113, 118, 102, 53, + 12, 30, 28, 28, 28, 10, 31, 77, 33, 37, + 36, 52, 45, 71, 38, 23, 31, 21, 12, 89, + 45, 15, 19, 9, 82, 53, 40, 81, 53, 24, + 26, 1, 56, 42, 43, 61, 27, 28, 108, 14, + 48, 54, 36, 36, 102, 20, 52, 42, 46, 123, + 30, 1, 126, 28, 51, 51, 38, 33, 49, 50, + 34, 2, 7, 117, 233, 217, 221, 205, 203, 143, + 255, 221, 205, 215, 128, 231, 254, 135, 231, 202, + 212, 207, 202, 216, 221, 203, 156, 149, 229, 214, + 213, 218, 211, 217, 208, 156, 223, 216, 168, 199, + 239, 251, 249, 255, 227, 239, 160, 198, 231, 244, + 164, 214, 234, 244, 236, 185, 216, 199, 188, 222, + 253, 253, 228, 227, 247, 244, 224, 198, 154, 132, + 156, 201, 187, 188, 204, 174, 144, 150, 132, 132, + 198, 168, 141, 137, 169, 139, 151, 141, 222, 170, + 183, 221, 177, 129, 133, 149, 147, 215, 187, 156, + 166, 136, 186, 188, 170, 170, 236, 130, 171, 175, + 224, 233, 145, 147, 141, 236, 141, 179, 189, 184, + 170, 255, 186, 168, 166, 166, 162, 180, 165, 247, + 151, 147, 110, 104, 64, 64, 64, 78, 12, 108, + 23, 19, 0, 104, 72, 67, 65, 93, 111, 104, + 24, 8, 14, 31, 101, 88, 83, 65, 67, 17, + 98, 69, 81, 84, 121, 126, 122, 112, 46, 65, + 99, 121, 103, 86, 83, 33, 51, 39, 93, 96, + 123, 105, 107, 57, 74, 109, 121, 124, 97, 102, + 98, 104, 54, 89, 123, 97, 15, 46, 29, 27, + 1, 79, 46, 24, 12, 7, 53, 50, 70, 84, + 84, 69, 35, 30, 25, 11, 13, 95, 40, 15, + 23, 18, 3, 4, 4, 14, 84, 55, 37, 37, + 44, 58, 4, 46, 60, 44, 44, 99, 20, 51, + 35, 38, 55, 48, 40, 34, 120, 23, 49, 43, + 57, 8, 25, 115, 4, 35, 51, 54, 39, 32, + 216, 210, 136, 231, 193, 219, 201, 249, 199, 205, + 141, 216, 195, 198, 214, 133, 239, 149, 235, 151, + 158, 235, 206, 216, 211, 192, 197, 195, 207, 151, + 250, 218, 254, 238, 168, 202, 200, 203, 216, 250, + 237, 174, 249, 228, 231, 245, 164, 208, 180, 200, + 182, 185, 202, 237, 249, 252, 225, 230, 226, 232, + 182, 217, 251, 225, 143, 203, 171, 175, 170, 169, + 133, 155, 135, 206, 153, 132, 135, 149, 196, 176, + 212, 168, 214, 217, 170, 141, 153, 156, 129, 134, + 130, 136, 214, 185, 155, 129, 175, 235, 139, 143, + 138, 154, 226, 158, 236, 227, 148, 179, 163, 166, + 183, 176, 168, 162, 248, 155, 177, 177, 184, 253, + 145, 149, 148, 132, 133, 247, 144, 186, 70, 71, + 73, 91, 14, 102, 66, 73, 71, 91, 98, 72, + 82, 68, 75, 76, 84, 27, 78, 74, 30, 106, + 111, 29, 118, 92, 92, 93, 87, 69, 113, 65, + 98, 110, 122, 108, 123, 98, 44, 123, 113, 35, + 85, 82, 38, 67, 107, 105, 118, 122, 106, 91, + 119, 107, 114, 114, 102, 118, 48, 103, 101, 55, + 65, 70, 74, 47, 7, 5, 2, 14, 30, 33, + 7, 21, 9, 0, 20, 71, 18, 22, 90, 46, + 43, 89, 58, 16, 16, 17, 19, 1, 34, 24, + 6, 7, 24, 16, 106, 107, 62, 58, 110, 26, + 31, 109, 6, 44, 44, 45, 39, 53, 106, 101, + 31, 41, 42, 54, 44, 127, 43, 53, 59, 63, + 53, 113, 38, 62, 58, 50, 195, 197, 207, 137, + 198, 192, 223, 217, 152, 131, 246, 196, 200, 195, + 203, 215, 247, 218, 214, 216, 217, 218, 206, 135, + 146, 218, 222, 216, 194, 222, 213, 217, 227, 241, + 233, 253, 231, 224, 226, 163, 172, 173, 214, 228, + 232, 227, 235, 247, 204, 254, 246, 253, 241, 237, + 209, 252, 252, 242, 247, 244, 228, 173, 180, 243, + 139, 130, 132, 201, 154, 128, 204, 129, 141, 130, + 132, 193, 176, 130, 138, 129, 149, 137, 216, 141, + 135, 143, 153, 211, 210, 186, 158, 152, 130, 158, + 149, 153, 163, 177, 169, 189, 167, 160, 162, 237, + 177, 168, 169, 177, 182, 162, 160, 235, 140, 190, + 182, 189, 177, 173, 145, 188, 188, 178, 183, 180, + 164, 237, 244, 245, 92, 78, 70, 77, 65, 93, + 12, 68, 86, 70, 77, 82, 6, 80, 69, 86, + 26, 93, 87, 76, 80, 91, 123, 88, 70, 101, + 85, 95, 82, 88, 70, 120, 111, 127, 105, 77, + 111, 123, 109, 91, 103, 109, 100, 110, 116, 74, + 101, 107, 123, 124, 125, 107, 36, 63, 106, 120, + 124, 119, 127, 99, 54, 122, 113, 97, 11, 15, + 9, 29, 15, 79, 5, 30, 66, 13, 15, 21, + 70, 4, 11, 23, 8, 30, 27, 13, 80, 95, + 40, 4, 2, 22, 80, 76, 86, 33, 17, 27, + 46, 36, 58, 4, 47, 33, 45, 42, 39, 49, + 122, 97, 48, 34, 42, 33, 53, 41, 120, 48, + 45, 127, 61, 49, 32, 54, 49, 53, 47, 119, + 53, 49, 206, 206, 204, 137, 218, 192, 140, 206, + 195, 192, 200, 196, 136, 135, 234, 196, 215, 222, + 152, 132, 158, 159, 202, 216, 220, 215, 223, 195, + 150, 192, 213, 198, 170, 226, 230, 224, 250, 230, + 237, 225, 235, 249, 229, 229, 166, 244, 241, 230, + 249, 254, 235, 234, 248, 234, 240, 241, 235, 179, + 189, 177, 240, 246, 253, 249, 202, 159, 135, 201, + 156, 138, 152, 159, 139, 134, 150, 132, 198, 142, + 138, 131, 149, 219, 153, 155, 145, 138, 136, 221, + 132, 150, 158, 149, 153, 133, 162, 144, 164, 175, + 167, 187, 131, 174, 162, 172, 165, 166, 178, 251, + 230, 174, 170, 172, 174, 178, 185, 181, 183, 165, + 185, 185, 242, 160, 165, 178, 181, 178, 167, 166, + 76, 94, 68, 69, 87, 99, 69, 64, 75, 87, + 112, 68, 84, 78, 75, 65, 26, 6, 24, 21, + 30, 105, 93, 81, 71, 86, 16, 12, 22, 27, + 20, 124, 100, 127, 109, 123, 120, 110, 96, 45, + 63, 35, 44, 33, 84, 98, 117, 112, 127, 104, + 108, 77, 103, 111, 121, 110, 50, 46, 48, 89, + 127, 100, 96, 122, 24, 18, 72, 27, 11, 30, + 25, 8, 17, 23, 64, 58, 15, 3, 89, 56, + 64, 91, 42, 28, 10, 13, 21, 24, 4, 26, + 30, 22, 86, 19, 21, 1, 43, 107, 46, 59, + 33, 34, 108, 46, 35, 32, 40, 36, 104, 105, + 106, 24, 96, 123, 10, 60, 42, 45, 53, 56, + 36, 58, 62, 54, 118, 51, 53, 33, 203, 139, + 206, 219, 193, 194, 140, 206, 195, 192, 200, 196, + 134, 193, 205, 203, 211, 200, 208, 220, 218, 145, + 156, 230, 251, 199, 213, 220, 197, 151, 215, 218, + 255, 229, 252, 179, 174, 210, 209, 183, 162, 207, + 239, 224, 226, 238, 234, 226, 186, 255, 249, 237, + 255, 191, 250, 239, 253, 254, 176, 226, 243, 229, + 226, 240, 152, 197, 198, 199, 179, 213, 204, 161, + 141, 130, 132, 136, 136, 128, 196, 129, 155, 143, + 153, 217, 152, 141, 147, 144, 210, 128, 149, 131, + 128, 146, 134, 213, 172, 162, 166, 160, 189, 167, + 169, 169, 236, 227, 155, 136, 178, 162, 169, 182, + 250, 184, 183, 172, 176, 171, 230, 253, 135, 189, + 163, 164, 166, 167, 187, 167, 94, 78, 76, 9, + 79, 72, 75, 95, 71, 68, 65, 85, 79, 72, + 74, 31, 26, 27, 89, 94, 89, 77, 89, 90, + 83, 71, 89, 94, 88, 23, 90, 90, 126, 43, + 123, 124, 126, 127, 99, 127, 118, 102, 100, 69, + 53, 70, 48, 48, 44, 88, 42, 46, 41, 92, + 40, 94, 35, 34, 35, 38, 33, 37, 38, 80, + 92, 93, 42, 90, 92, 91, 41, 46, 87, 33, + 87, 89, 34, 33, 38, 39, 59, 77, 74, 76, + 78, 79, 72, 73, 48, 70, 64, 64, 55, 64, + 76, 68, 11, 8, 13, 8, 124, 14, 121, 126, + 114, 119, 1, 7, 113, 119, 2, 125, 105, 108, + 106, 111, 110, 29, 107, 106, 103, 18, 104, 28, + 55, 62, 58, 17, 207, 205, 201, 220, 194, 219, + 255, 200, 209, 208, 201, 206, 200, 212, 231, 202, + 212, 207, 217, 208, 208, 218, 206, 240, 215, 192, + 195, 208, 209, 210, 245, 198, 249, 238, 252, 192, + 234, 200, 254, 226, 247, 243, 201, 239, 224, 232, + 215, 234, 232, 239, 209, 247, 250, 250, 228, 211, + 243, 254, 245, 218, 243, 238, 192, 250, 133, 135, + 188, 128, 158, 164, 137, 148, 166, 130, 148, 128, + 178, 158, 148, 128, 188, 148, 138, 148, 159, 139, + 149, 147, 149, 167, 137, 129, 147, 180, 129, 134, + 190, 164, 165, 136, 189, 188, 169, 185, 139, 135, + 150, 168, 181, 174, 166, 169, 191, 146, 171, 149, + 183, 177, 183, 148, 182, 243, 237, 241, 250, 247, + 147, 167, 69, 94, 88, 9, 19, 15, 0, 13, + 116, 74, 83, 72, 68, 75, 65, 5, 7, 27, + 20, 25, 118, 86, 88, 89, 87, 93, 16, 12, + 22, 96, 85, 92, 126, 98, 102, 110, 46, 105, + 99, 127, 34, 112, 116, 96, 116, 115, 36, 113, + 115, 118, 125, 90, 113, 115, 112, 120, 113, 103, + 48, 120, 98, 114, 121, 102, 74, 31, 7, 73, + 12, 26, 10, 11, 7, 17, 64, 50, 7, 17, + 1, 1, 90, 91, 17, 13, 27, 18, 15, 83, + 10, 32, 9, 28, 20, 24, 24, 54, 37, 46, + 46, 47, 39, 44, 37, 40, 44, 55, 20, 51, + 39, 35, 33, 23, 59, 47, 49, 54, 15, 42, + 61, 51, 38, 58, 36, 40, 4, 62, 39, 62, + 248, 194, 219, 194, 142, 223, 201, 223, 193, 198, + 206, 213, 239, 201, 199, 202, 215, 210, 214, 222, + 158, 222, 206, 218, 199, 222, 213, 223, 194, 151, + 220, 212, 249, 171, 255, 251, 225, 225, 235, 173, + 246, 250, 240, 228, 168, 167, 193, 253, 234, 254, + 251, 237, 251, 251, 188, 186, 181, 179, 228, 232, + 230, 242, 220, 250, 134, 130, 140, 136, 151, 166, + 130, 139, 141, 167, 129, 149, 131, 180, 129, 150, + 137, 146, 151, 151, 177, 143, 153, 147, 166, 154, + 157, 148, 162, 142, 132, 144, 131, 184, 152, 187, + 167, 162, 173, 191, 187, 128, 172, 174, 181, 162, + 144, 172, 183, 190, 139, 188, 173, 172, 181, 178, + 188, 160, 148, 176, 175, 164, 144, 180, 83, 100, + 78, 126, 75, 74, 71, 110, 71, 81, 84, 64, + 79, 73, 96, 68, 78, 94, 75, 123, 75, 76, + 85, 83, 87, 64, 67, 126, 84, 93, 81, 86, + 126, 66, 102, 111, 97, 78, 111, 110, 109, 118, + 110, 117, 82, 126, 116, 96, 58, 117, 119, 109, + 62, 108, 105, 109, 98, 124, 98, 101, 115, 115, + 80, 112, 25, 8, 26, 0, 30, 27, 5, 2, + 12, 89, 64, 65, 93, 36, 5, 11, 26, 15, + 88, 31, 23, 17, 24, 93, 30, 26, 3, 5, + 86, 0, 29, 1, 34, 107, 59, 57, 43, 44, + 37, 43, 43, 38, 36, 97, 40, 38, 41, 32, + 122, 102, 120, 63, 42, 47, 114, 44, 39, 50, + 62, 37, 57, 32, 49, 39, 132, 194, 198, 203, + 207, 204, 199, 216, 210, 208, 205, 192, 200, 198, + 195, 192, 200, 254, 213, 255, 200, 209, 212, 252, + 245, 128, 211, 200, 217, 205, 213, 140, 219, 179, + 222, 254, 197, 226, 229, 254, 225, 240, 249, 236, + 228, 232, 232, 246, 197, 247, 241, 234, 234, 236, + 232, 228, 226, 246, 195, 221, 194, 199, 228, 231, + 131, 136, 141, 152, 155, 142, 130, 153, 139, 151, + 153, 145, 148, 142, 135, 128, 183, 158, 153, 138, + 139, 141, 153, 144, 151, 157, 132, 176, 148, 132, + 155, 153, 191, 191, 173, 134, 168, 169, 191, 168, + 182, 170, 179, 149, 180, 166, 173, 169, 179, 181, + 191, 168, 171, 190, 178, 169, 187, 167, 169, 129, + 179, 165, 183, 176, 68, 95, 73, 78, 75, 127, + 94, 68, 65, 70, 112, 83, 79, 68, 65, 104, + 95, 90, 75, 76, 76, 90, 81, 88, 92, 71, + 121, 66, 98, 69, 85, 92, 102, 98, 102, 110, + 95, 122, 109, 99, 118, 106, 116, 120, 86, 98, + 118, 102, 127, 117, 108, 120, 121, 122, 32, 61, + 46, 46, 48, 71, 119, 101, 125, 116, 8, 7, + 13, 61, 7, 12, 7, 33, 7, 5, 20, 35, + 9, 21, 0, 0, 8, 41, 17, 30, 22, 11, + 62, 18, 0, 23, 21, 3, 63, 25, 23, 25, + 63, 47, 45, 5, 43, 41, 56, 15, 45, 49, + 36, 36, 52, 19, 45, 38, 49, 8, 49, 35, + 59, 11, 53, 62, 57, 16, 63, 34, 34, 7, + 38, 48, 201, 194, 219, 192, 193, 193, 237, 193, + 208, 198, 193, 197, 223, 135, 199, 202, 212, 213, + 221, 218, 202, 214, 210, 218, 146, 221, 223, 198, + 242, 222, 199, 214, 229, 229, 230, 236, 237, 251, + 229, 227, 229, 163, 238, 238, 241, 167, 231, 234, + 244, 245, 253, 250, 234, 246, 242, 250, 188, 189, + 190, 177, 245, 248, 250, 251, 143, 136, 156, 128, + 128, 136, 204, 139, 131, 138, 140, 132, 130, 201, + 196, 183, 159, 154, 139, 150, 144, 197, 220, 177, + 157, 146, 148, 152, 152, 144, 212, 134, 175, 184, + 187, 160, 161, 161, 191, 227, 236, 237, 131, 251, + 154, 128, 173, 177, 182, 186, 186, 244, 140, 170, + 178, 179, 183, 161, 140, 179, 163, 190, 184, 177, + 89, 119, 26, 74, 118, 26, 110, 99, 110, 115, + 124, 17, 122, 68, 72, 76, 95, 85, 76, 101, + 74, 90, 78, 80, 91, 93, 81, 93, 106, 83, + 81, 67, 111, 103, 103, 121, 99, 106, 98, 121, + 94, 65, 117, 114, 111, 105, 97, 118, 105, 87, + 121, 96, 123, 109, 64, 73, 96, 114, 116, 120, + 120, 112, 68, 121, 11, 31, 14, 6, 28, 2, + 66, 47, 23, 16, 9, 15, 3, 20, 23, 41, + 27, 2, 29, 11, 34, 60, 19, 19, 28, 22, + 19, 5, 31, 24, 26, 6, 22, 8, 39, 39, + 32, 42, 47, 57, 43, 44, 46, 111, 37, 52, + 8, 42, 59, 63, 49, 55, 57, 127, 57, 37, + 49, 59, 49, 63, 49, 50, 39, 123, 132, 133, + 228, 198, 207, 203, 197, 195, 197, 131, 211, 216, + 203, 197, 203, 201, 154, 220, 202, 214, 203, 207, + 207, 147, 156, 157, 252, 222, 215, 211, 221, 219, + 237, 171, 231, 251, 234, 234, 254, 173, 246, 250, + 240, 228, 245, 169, 170, 171, 214, 244, 249, 253, + 247, 241, 251, 189, 243, 224, 227, 244, 226, 228, + 186, 187, 196, 167, 135, 136, 138, 134, 130, 138, + 194, 130, 131, 130, 137, 146, 138, 145, 137, 213, + 214, 215, 178, 144, 157, 153, 155, 157, 151, 209, + 153, 135, 128, 156, 165, 165, 232, 186, 171, 189, + 165, 168, 177, 237, 238, 239, 138, 168, 165, 161, + 179, 181, 191, 249, 173, 166, 177, 191, 189, 191, + 163, 255, 248, 249, 152, 186, 75, 79, 65, 71, + 73, 15, 94, 88, 78, 70, 83, 15, 8, 9, + 104, 74, 91, 95, 81, 87, 89, 31, 76, 82, + 65, 90, 68, 88, 89, 89, 71, 27, 36, 37, + 68, 102, 111, 107, 101, 99, 101, 35, 99, 109, + 105, 116, 97, 97, 58, 107, 119, 106, 119, 107, + 117, 114, 124, 96, 62, 63, 56, 91, 123, 116, + 14, 2, 6, 14, 78, 29, 9, 29, 13, 17, + 20, 18, 72, 73, 74, 41, 21, 26, 28, 16, + 16, 24, 92, 18, 0, 23, 21, 3, 5, 89, + 90, 91, 6, 36, 41, 45, 39, 33, 43, 109, + 35, 32, 35, 46, 51, 41, 48, 101, 53, 43, + 61, 43, 63, 43, 53, 50, 60, 32, 126, 127, + 120, 27, 59, 52, 206, 194, 198, 206, 142, 219, + 222, 204, 198, 202, 206, 198, 134, 212, 205, 194, + 212, 218, 212, 202, 144, 145, 146, 237, 192, 220, + 211, 212, 197, 196, 221, 219, 237, 171, 229, 236, + 253, 252, 237, 234, 231, 240, 174, 175, 168, 239, + 237, 246, 238, 244, 234, 224, 176, 251, 254, 235, + 253, 255, 229, 252, 243, 186, 245, 251, 139, 135, + 145, 154, 135, 156, 194, 137, 128, 150, 147, 132, + 148, 202, 144, 151, 155, 159, 157, 138, 208, 155, + 158, 178, 130, 150, 130, 144, 130, 158, 155, 155, + 234, 188, 169, 186, 238, 172, 173, 163, 161, 166, + 172, 173, 163, 163, 228, 166, 181, 181, 182, 188, + 189, 171, 185, 185, 242, 160, 165, 178, 181, 178, + 167, 166, 76, 94, 68, 69, 87, 76, 67, 67, + 76, 70, 67, 85, 67, 67, 103, 74, 84, 85, + 93, 90, 74, 86, 83, 83, 18, 68, 81, 66, + 22, 83, 93, 70, 105, 100, 102, 103, 107, 108, + 120, 104, 102, 35, 100, 116, 99, 39, 112, 106, + 58, 111, 112, 124, 62, 115, 125, 126, 121, 51, + 127, 119, 54, 123, 125, 118, 15, 5, 27, 12, + 55, 0, 25, 77, 10, 2, 22, 4, 70, 5, + 1, 0, 20, 91, 27, 22, 16, 17, 25, 30, + 6, 22, 20, 81, 5, 2, 23, 22, 47, 56, + 59, 47, 59, 35, 32, 52, 13, 55, 40, 36, + 52, 103, 50, 32, 52, 63, 55, 43, 45, 127, + 43, 56, 32, 54, 112, 53, 63, 36, 55, 58, + 196, 197, 205, 202, 218, 202, 200, 141, 198, 214, + 197, 129, 210, 200, 132, 209, 210, 222, 152, 213, + 223, 220, 215, 157, 221, 213, 144, 221, 223, 212, + 209, 219, 249, 238, 203, 230, 224, 225, 233, 238, + 246, 234, 239, 239, 193, 245, 235, 240, 234, 244, + 217, 236, 234, 247, 188, 242, 226, 231, 249, 254, + 248, 228, 180, 226, 139, 152, 200, 135, 129, 155, + 204, 158, 135, 151, 166, 128, 143, 139, 196, 145, + 149, 219, 159, 156, 144, 154, 142, 156, 134, 150, + 208, 131, 151, 153, 144, 154, 167, 235, 184, 166, + 188, 187, 164, 185, 182, 179, 250, 238, 233, 171, + 171, 166, 187, 183, 176, 182, 173, 171, 230, 190, + 134, 161, 177, 181, 179, 165, 183, 185, 67, 78, + 70, 93, 113, 70, 72, 78, 78, 74, 69, 79, + 82, 120, 87, 64, 89, 73, 93, 77, 76, 90, + 90, 79, 87, 64, 88, 110, 66, 88, 95, 80, + 100, 108, 122, 104, 96, 123, 83, 121, 123, 115, + 101, 64, 101, 100, 97, 118, 105, 79, 119, 114, + 123, 113, 78, 120, 116, 97, 117, 98, 126, 67, + 123, 126, 15, 5, 45, 17, 30, 6, 30, 8, + 17, 42, 14, 34, 9, 9, 10, 0, 25, 15, + 17, 22, 16, 69, 92, 46, 23, 7, 80, 35, + 19, 17, 6, 16, 57, 35, 28, 38, 37, 42, + 34, 31, 39, 48, 53, 45, 50, 103, 52, 55, + 53, 43, 61, 43, 42, 54, 57, 46, 49, 60, + 52, 52, 53, 56, 48, 48, 138, 207, 199, 204, + 221, 143, 194, 194, 214, 131, 197, 217, 207, 212, + 208, 215, 223, 223, 209, 203, 219, 220, 200, 226, + 199, 193, 217, 208, 195, 195, 220, 218, 248, 226, + 242, 232, 250, 230, 227, 227, 221, 224, 239, 229, + 227, 227, 237, 246, 249, 244, 246, 247, 251, 252, + 232, 244, 252, 244, 176, 245, 255, 228, 247, 250, + 132, 133, 141, 138, 154, 134, 130, 138, 204, 205, + 206, 193, 130, 142, 151, 134, 149, 149, 150, 156, + 157, 139, 153, 153, 210, 144, 159, 159, 152, 146, + 151, 129, 163, 164, 166, 233, 162, 160, 191, 185, + 226, 130, 181, 181, 169, 231, 182, 160, 185, 184, + 183, 183, 187, 188, 168, 180, 189, 189, 240, 184, + 165, 247, 176, 188, 89, 74, 74, 69, 75, 75, + 111, 66, 76, 77, 69, 66, 82, 78, 75, 75, + 26, 82, 75, 25, 80, 80, 72, 29, 81, 92, + 94, 95, 83, 84, 64, 80, 110, 72, 103, 103, + 96, 106, 111, 121, 107, 108, 110, 33, 111, 116, + 36, 80, 116, 112, 118, 118, 105, 113, 60, 114, + 96, 119, 117, 99, 54, 99, 109, 101, 15, 36, + 26, 13, 11, 29, 76, 29, 3, 17, 1, 12, + 3, 19, 1, 23, 9, 91, 17, 10, 94, 26, + 17, 13, 6, 10, 35, 8, 27, 21, 27, 25, + 57, 107, 46, 59, 33, 34, 108, 41, 43, 37, + 38, 36, 52, 34, 42, 49, 122, 56, 55, 55, + 48, 58, 63, 41, 59, 60, 62, 34, 23, 59, + 56, 58, 221, 139, 230, 204, 217, 143, 227, 238, + 237, 243, 204, 192, 197, 194, 132, 234, 249, 244, + 152, 215, 209, 203, 156, 220, 222, 223, 223, 198, + 211, 211, 243, 208, 254, 197, 231, 231, 200, 230, + 244, 232, 230, 208, 249, 236, 228, 232, 232, 165, + 232, 254, 233, 236, 251, 236, 232, 189, 230, 250, + 253, 244, 182, 248, 225, 225, 202, 152, 145, 132, + 140, 128, 128, 205, 139, 135, 192, 220, 198, 171, + 139, 132, 158, 146, 150, 158, 222, 223, 154, 143, + 157, 158, 202, 209, 214, 131, 155, 207, 234, 235, + 174, 160, 160, 166, 191, 165, 167, 167, 224, 167, + 167, 174, 168, 182, 175, 184, 187, 188, 173, 172, + 240, 253, 144, 178, 162, 162, 236, 247, 248, 245, + 110, 94, 90, 72, 90, 70, 67, 67, 24, 3, + 110, 19, 6, 84, 65, 70, 79, 75, 92, 88, + 74, 90, 125, 94, 70, 90, 95, 95, 22, 84, + 91, 64, 102, 111, 40, 103, 97, 123, 44, 111, + 103, 35, 110, 116, 106, 107, 103, 100, 118, 119, + 122, 120, 125, 116, 114, 114, 50, 114, 115, 101, + 127, 97, 113, 53, 5, 25, 12, 12, 28, 28, + 76, 12, 1, 23, 9, 23, 3, 71, 11, 23, + 30, 30, 10, 81, 13, 86, 92, 85, 28, 28, + 80, 1, 25, 4, 29, 1, 35, 36, 38, 58, + 110, 63, 35, 62, 43, 55, 41, 46, 40, 111, + 55, 108, 122, 115, 120, 46, 55, 43, 52, 125, + 114, 50, 62, 53, 118, 26, 49, 38, 217, 202, + 207, 204, 225, 223, 201, 195, 237, 209, 196, 196, + 212, 135, 204, 196, 204, 222, 152, 215, 209, 159, + 253, 222, 209, 220, 197, 223, 194, 254, 208, 153, + 170, 219, 231, 250, 231, 251, 229, 226, 236, 202, + 228, 161, 187, 167, 201, 224, 233, 232, 249, 254, + 251, 208, 236, 248, 252, 220, 226, 245, 243, 229, + 180, 253, 139, 157, 141, 201, 128, 128, 204, 190, + 155, 142, 130, 142, 138, 174, 128, 201, 218, 171, + 151, 138, 151, 139, 149, 146, 156, 186, 148, 209, + 203, 215, 185, 144, 185, 184, 169, 174, 171, 128, + 188, 168, 172, 147, 175, 178, 175, 179, 173, 170, + 180, 251, 176, 184, 168, 186, 252, 179, 189, 243, + 145, 178, 181, 184, 161, 187, 94, 98, 76, 5, + 14, 127, 67, 94, 75, 87, 73, 78, 72, 110, + 64, 5, 7, 27, 117, 92, 77, 76, 93, 90, + 87, 124, 64, 84, 88, 103, 91, 70, 99, 127, + 97, 102, 96, 47, 100, 108, 116, 102, 32, 111, + 105, 39, 87, 124, 119, 121, 119, 117, 87, 123, + 48, 61, 66, 124, 99, 120, 98, 126, 123, 123, + 35, 15, 72, 84, 78, 34, 9, 30, 17, 2, + 7, 4, 37, 11, 11, 22, 31, 31, 40, 22, + 13, 22, 8, 20, 29, 29, 80, 25, 23, 1, + 17, 85, 36, 36, 104, 8, 45, 44, 35, 56, + 44, 55, 9, 37, 106, 103, 20, 42, 41, 50, + 44, 48, 49, 49, 21, 57, 114, 110, 112, 28, + 51, 36, 39, 52, 205, 206, 235, 197, 193, 220, + 201, 201, 242, 204, 211, 200, 210, 206, 203, 203, + 154, 211, 217, 207, 219, 159, 210, 210, 146, 224, + 201, 220, 212, 216, 216, 252, 238, 167, 168, 217, + 225, 252, 229, 249, 235, 236, 238, 200, 226, 167, + 185, 165, 215, 254, 235, 234, 255, 248, 249, 222, + 224, 234, 224, 229, 249, 214, 231, 230, 143, 159, + 170, 136, 130, 142, 130, 142, 135, 144, 192, 137, + 135, 145, 129, 197, 148, 148, 216, 184, 157, 156, + 147, 136, 156, 135, 185, 149, 187, 146, 135, 134, + 171, 172, 173, 138, 188, 182, 188, 185, 173, 130, + 179, 178, 163, 179, 134, 164, 182, 186, 182, 186, + 187, 172, 252, 181, 179, 165, 181, 241, 184, 184, + 244, 148, 89, 88, 77, 93, 103, 75, 111, 95, + 91, 83, 84, 78, 103, 68, 71, 74, 79, 85, + 76, 25, 87, 76, 28, 79, 87, 66, 69, 88, + 68, 82, 80, 21, 108, 100, 122, 41, 67, 106, + 127, 126, 99, 100, 101, 66, 116, 126, 116, 113, + 117, 90, 107, 106, 123, 107, 94, 124, 126, 114, + 126, 114, 115, 100, 58, 53, 43, 8, 11, 6, + 27, 1, 24, 77, 11, 7, 64, 92, 70, 36, + 5, 11, 26, 15, 88, 31, 23, 17, 24, 93, + 19, 16, 19, 30, 3, 25, 0, 85, 61, 34, + 60, 33, 110, 38, 40, 109, 127, 99, 3, 46, + 40, 41, 33, 38, 46, 50, 55, 55, 126, 49, + 61, 48, 55, 5, 53, 63, 50, 56, 38, 27, + 203, 198, 205, 224, 221, 233, 205, 219, 205, 214, + 210, 200, 210, 194, 231, 202, 212, 213, 221, 218, + 202, 214, 211, 211, 225, 199, 209, 197, 211, 244, + 198, 208, 235, 255, 225, 230, 224, 219, 245, 253, + 231, 205, 225, 236, 227, 189, 164, 165, 204, 254, + 246, 253, 241, 237, 166, 189, 178, 213, 241, 231, + 249, 229, 253, 225, 143, 209, 200, 170, 129, 129, + 130, 136, 129, 151, 137, 142, 136, 148, 222, 197, + 147, 149, 145, 141, 151, 158, 144, 148, 136, 146, + 132, 152, 153, 153, 218, 219, 228, 136, 167, 167, + 160, 170, 175, 185, 171, 172, 174, 178, 252, 231, + 173, 171, 179, 175, 177, 184, 178, 182, 166, 184, + 182, 243, 163, 164, 181, 180, 177, 166, 89, 77, + 93, 69, 66, 86, 90, 72, 76, 71, 79, 83, + 104, 70, 73, 64, 121, 90, 86, 30, 74, 31, + 90, 84, 92, 87, 16, 85, 83, 81, 85, 64, + 102, 127, 40, 106, 97, 97, 98, 104, 97, 119, + 105, 110, 104, 39, 109, 107, 124, 116, 56, 127, + 113, 109, 60, 107, 119, 125, 116, 126, 100, 55, + 41, 53, 74, 10, 6, 13, 78, 8, 30, 2, + 23, 19, 64, 92, 70, 36, 22, 0, 27, 15, + 29, 89, 29, 10, 15, 9, 29, 30, 80, 18, + 25, 25, 26, 16, 41, 63, 33, 38, 32, 60, + 108, 36, 49, 99, 36, 36, 40, 46, 33, 33, + 122, 61, 55, 43, 126, 41, 57, 51, 54, 60, + 34, 113, 107, 119, 55, 58, 196, 197, 205, 202, + 218, 198, 195, 195, 235, 205, 198, 206, 231, 195, + 192, 133, 206, 222, 219, 209, 208, 214, 223, 220, + 222, 147, 243, 222, 216, 217, 209, 214, 254, 226, + 231, 231, 199, 225, 234, 226, 162, 234, 243, 161, + 226, 226, 234, 236, 255, 255, 246, 252, 233, 209, + 253, 240, 247, 208, 255, 227, 243, 173, 180, 252, + 132, 130, 156, 128, 143, 131, 133, 151, 131, 151, + 137, 142, 136, 201, 202, 203, 182, 148, 159, 158, + 155, 141, 198, 221, 155, 157, 153, 133, 159, 150, + 152, 156, 176, 174, 172, 233, 189, 186, 175, 174, + 167, 176, 179, 167, 179, 171, 168, 188, 153, 180, + 170, 188, 228, 255, 181, 179, 187, 167, 185, 176, + 186, 190, 174, 176, 78, 11, 91, 92, 77, 76, + 73, 94, 81, 69, 85, 77, 74, 94, 69, 70, + 89, 84, 77, 87, 74, 118, 82, 91, 93, 112, + 101, 98, 98, 120, 121, 106, 89, 82, 69, 75, + 65, 67, 83, 78, 77, 77, 78, 68, 69, 83, + 77, 74, 84, 83, 81, 74, 74, 80, 78, 84, + 81, 82, 92, 78, 69, 78, 89, 87, 37, 39, + 55, 42, 33, 33, 34, 40, 33, 55, 41, 46, + 40, 56, 45, 33, 35, 20, 13, 89, 22, 30, + 10, 24, 82, 30, 31, 3, 19, 87, 0, 29, + 43, 37, 104, 38, 32, 42, 108, 44, 33, 55, + 41, 55, 35, 103, 39, 42, 52, 53, 61, 58, + 42, 54, 51, 51, 126, 115, 41, 62, 35, 119, + 39, 61, 197, 222, 196, 205, 142, 220, 220, 200, + 193, 202, 198, 216, 134, 196, 203, 203, 212, 222, + 219, 205, 215, 208, 210, 244, 214, 147, 192, 208, + 196, 214, 217, 208, 254, 238, 250, 169, 250, 224, + 172, 234, 231, 247, 160, 242, 255, 234, 230, 234, + 246, 232, 225, 244, 252, 240, 240, 212, 252, 245, + 255, 227, 243, 230, 225, 240, 153, 159, 184, 136, + 156, 142, 129, 136, 150, 134, 146, 146, 191, 136, + 145, 197, 151, 142, 139, 141, 222, 140, 140, 152, + 145, 154, 150, 136, 214, 165, 155, 154, 190, 235, + 167, 187, 238, 186, 162, 169, 167, 177, 172, 168, + 163, 181, 157, 170, 175, 251, 176, 184, 168, 186, + 252, 176, 189, 161, 181, 241, 162, 191, 181, 187, + 10, 68, 70, 76, 14, 78, 79, 89, 75, 85, + 69, 1, 69, 72, 74, 75, 95, 88, 76, 80, + 81, 81, 16, 29, 75, 92, 69, 17, 69, 95, + 91, 64, 102, 111, 40, 122, 126, 106, 111, 100, + 100, 122, 32, 98, 105, 105, 106, 96, 121, 111, + 113, 118, 112, 86, 120, 61, 98, 114, 98, 112, + 123, 114, 96, 112, 24, 75, 28, 6, 78, 8, + 9, 25, 66, 5, 21, 21, 19, 21, 1, 69, + 25, 20, 22, 13, 12, 30, 31, 9, 1, 38, + 30, 21, 19, 5, 24, 28, 47, 57, 1, 45, + 29, 42, 62, 36, 39, 10, 36, 14, 52, 35, + 33, 55, 122, 46, 40, 61, 63, 43, 57, 18, + 32, 55, 53, 35, 118, 37, 49, 56, 197, 221, + 205, 198, 220, 203, 201, 223, 246, 218, 208, 196, + 239, 195, 253, 202, 207, 155, 208, 216, 200, 218, + 156, 208, 221, 193, 213, 145, 194, 223, 213, 219, + 170, 228, 230, 236, 174, 238, 239, 249, 235, 245, + 229, 161, 229, 232, 234, 235, 255, 248, 236, 240, + 241, 241, 176, 189, 235, 252, 229, 177, 229, 255, + 251, 224, 134, 143, 200, 154, 158, 138, 143, 132, + 132, 154, 192, 130, 137, 137, 138, 128, 153, 143, + 145, 150, 144, 182, 152, 221, 130, 146, 130, 144, + 155, 146, 128, 144, 184, 235, 188, 166, 238, 168, + 169, 185, 226, 140, 178, 165, 163, 181, 144, 188, + 170, 190, 150, 182, 254, 178, 189, 169, 177, 187, + 185, 191, 177, 247, 183, 186, 68, 69, 77, 74, + 90, 70, 67, 67, 118, 81, 65, 69, 67, 9, + 4, 106, 72, 95, 93, 75, 30, 86, 82, 91, + 93, 9, 16, 82, 87, 89, 19, 65, 42, 109, + 97, 103, 106, 47, 99, 127, 102, 102, 114, 78, + 116, 99, 97, 119, 58, 115, 113, 106, 106, 112, + 110, 100, 65, 103, 127, 97, 69, 99, 123, 101, + 38, 2, 5, 0, 26, 59, 30, 67, 17, 23, + 15, 17, 43, 6, 22, 14, 31, 15, 10, 28, + 15, 10, 25, 14, 6, 1, 21, 0, 3, 18, + 7, 1, 57, 10, 36, 37, 33, 56, 108, 42, + 48, 44, 53, 49, 102, 40, 54, 33, 63, 41, + 43, 54, 44, 59, 57, 47, 33, 42, 61, 51, + 57, 59, 39, 25, 195, 216, 220, 231, 207, 194, + 201, 222, 219, 206, 194, 206, 202, 212, 202, 192, + 205, 232, 193, 212, 220, 208, 208, 206, 254, 218, + 195, 197, 248, 214, 217, 208, 200, 249, 233, 231, + 234, 230, 226, 234, 199, 238, 245, 237, 231, 243, + 235, 247, 215, 250, 234, 242, 251, 235, 188, 207, + 247, 227, 252, 240, 239, 195, 230, 244, 142, 130, + 134, 142, 206, 188, 133, 128, 151, 143, 129, 149, + 137, 149, 182, 128, 139, 142, 157, 138, 138, 223, + 142, 152, 152, 150, 147, 133, 147, 147, 212, 145, + 191, 174, 232, 189, 161, 239, 184, 191, 163, 167, + 169, 175, 161, 231, 180, 183, 181, 175, 189, 186, + 170, 182, 179, 179, 242, 160, 169, 162, 162, 178, + 185, 251, 10, 104, 64, 76, 77, 68, 12, 84, + 77, 86, 82, 1, 85, 66, 80, 81, 83, 85, + 95, 74, 30, 23, 123, 88, 92, 86, 66, 80, + 90, 23, 71, 80, 126, 127, 97, 103, 105, 124, + 44, 32, 60, 35, 84, 115, 103, 99, 109, 107, + 125, 59, 104, 107, 113, 107, 121, 126, 102, 122, + 127, 127, 63, 84, 46, 73, 45, 2, 28, 5, + 15, 13, 65, 63, 23, 13, 14, 4, 20, 59, + 6, 16, 19, 23, 28, 10, 34, 77, 31, 37, + 71, 49, 62, 61, 38, 43, 68, 41, 41, 39, + 33, 44, 32, 59, 16, 57, 39, 49, 45, 40, + 40, 38, 40, 25, 62, 62, 46, 60, 50, 48, + 44, 48, 55, 61, 36, 13, 20, 34, 39, 60, + 196, 206, 219, 218, 226, 206, 213, 200, 208, 255, + 244, 211, 199, 195, 205, 203, 221, 235, 212, 216, + 202, 217, 211, 207, 223, 157, 242, 196, 197, 222, + 218, 208, 249, 248, 196, 232, 247, 234, 254, 209, + 193, 236, 242, 228, 168, 228, 247, 202, 232, 255, + 253, 235, 190, 237, 249, 236, 231, 246, 227, 229, + 182, 229, 241, 255, 143, 136, 156, 140, 138, 207, + 136, 152, 135, 195, 148, 142, 198, 192, 167, 138, + 148, 157, 145, 139, 147, 223, 136, 143, 147, 151, + 153, 159, 145, 215, 155, 155, 234, 185, 173, 168, + 162, 239, 175, 162, 172, 173, 165, 162, 178, 174, + 171, 171, 250, 172, 177, 173, 182, 255, 174, 168, + 188, 189, 185, 191, 177, 247, 167, 188, 71, 94, + 68, 72, 90, 64, 94, 10, 2, 80, 69, 85, + 82, 78, 74, 66, 20, 27, 123, 81, 91, 92, + 87, 29, 75, 92, 69, 67, 22, 68, 81, 65, + 126, 98, 102, 110, 125, 47, 36, 74, 103, 109, + 101, 115, 103, 107, 36, 118, 127, 111, 108, 112, + 112, 120, 111, 61, 63, 45, 48, 82, 121, 121, + 114, 124, 24, 6, 9, 29, 7, 0, 2, 30, + 66, 69, 64, 54, 7, 21, 10, 12, 20, 28, + 11, 80, 23, 12, 61, 30, 6, 26, 6, 20, + 18, 22, 0, 16, 37, 59, 45, 39, 1, 41, + 42, 62, 39, 55, 35, 45, 41, 52, 33, 10, + 60, 61, 43, 60, 42, 59, 61, 36, 33, 60, + 32, 52, 56, 3, 61, 56, 207, 200, 196, 198, + 221, 202, 248, 196, 207, 198, 201, 197, 197, 200, + 202, 203, 223, 216, 204, 208, 209, 209, 245, 217, + 215, 203, 211, 217, 215, 217, 211, 208, 195, 239, + 251, 240, 227, 237, 227, 225, 203, 231, 227, 238, + 232, 243, 229, 236, 244, 254, 234, 208, 250, 235, + 245, 240, 247, 201, 255, 255, 243, 227, 253, 248, + 143, 177, 135, 135, 139, 166, 130, 139, 141, 144, + 133, 146, 149, 142, 139, 139, 137, 147, 151, 149, + 151, 155, 157, 132, 129, 128, 149, 130, 133, 158, + 155, 155, 137, 164, 166, 189, 175, 166, 162, 168, + 176, 176, 161, 178, 181, 174, 163, 171, 183, 190, + 182, 173, 173, 156, 189, 179, 178, 167, 240, 183, + 191, 185, 176, 245, 75, 76, 79, 91, 75, 72, + 77, 89, 75, 76, 78, 1, 81, 78, 80, 77, + 26, 72, 72, 92, 93, 86, 90, 84, 87, 87, + 16, 95, 87, 90, 81, 21, 89, 127, 105, 123, + 122, 47, 124, 127, 109, 96, 101, 114, 117, 110, + 106, 98, 52, 53, 54, 57, 69, 76, 104, 120, + 98, 51, 62, 63, 56, 55, 79, 72, 80, 75, + 59, 29, 11, 31, 76, 67, 66, 34, 7, 6, + 20, 2, 3, 4, 14, 18, 23, 23, 94, 23, + 21, 14, 6, 28, 2, 8, 88, 89, 90, 85, + 57, 36, 61, 59, 45, 42, 108, 37, 43, 48, + 52, 46, 52, 62, 100, 38, 53, 46, 54, 45, + 126, 113, 124, 28, 53, 52, 34, 52, 49, 54, + 32, 60, 197, 197, 136, 193, 199, 220, 216, 194, + 208, 218, 128, 199, 207, 201, 205, 214, 210, 222, + 220, 151, 158, 228, 245, 201, 215, 222, 195, 145, + 213, 216, 193, 219, 254, 177, 168, 169, 254, 253, + 227, 238, 231, 240, 243, 228, 226, 169, 208, 236, + 249, 240, 200, 235, 241, 252, 249, 238, 225, 250, + 254, 246, 182, 241, 253, 251, 131, 152, 128, 140, + 138, 193, 204, 182, 182, 140, 148, 128, 138, 199, + 148, 151, 149, 152, 157, 138, 141, 150, 146, 154, + 210, 135, 153, 156, 147, 205, 212, 213, 185, 229, + 232, 157, 161, 187, 173, 161, 226, 179, 178, 174, + 165, 162, 183, 182, 191, 191, 248, 176, 170, 186, + 177, 174, 232, 243, 254, 241, 132, 178, 167, 160, + 70, 95, 8, 72, 73, 72, 94, 72, 69, 66, + 84, 68, 66, 7, 77, 81, 95, 86, 75, 3, + 30, 124, 93, 83, 21, 71, 16, 87, 95, 89, + 80, 21, 99, 101, 108, 96, 109, 110, 120, 98, + 112, 35, 119, 104, 114, 111, 36, 98, 115, 109, + 125, 119, 62, 113, 125, 112, 119, 80, 113, 127, + 118, 99, 52, 115, 3, 5, 12, 73, 15, 8, + 11, 31, 7, 4, 1, 21, 9, 21, 68, 3, + 21, 9, 88, 10, 27, 19, 25, 30, 6, 22, + 20, 81, 6, 22, 6, 20, 39, 46, 60, 44, + 60, 60, 39, 40, 59, 21, 33, 45, 51, 34, + 100, 40, 47, 40, 44, 121, 60, 58, 124, 58, + 32, 54, 49, 37, 51, 37, 116, 33, 194, 202, + 198, 137, 158, 223, 201, 223, 203, 204, 196, 236, + 211, 203, 208, 204, 202, 215, 209, 220, 204, 234, + 210, 214, 220, 220, 199, 223, 150, 213, 213, 198, + 239, 171, 248, 236, 252, 230, 227, 233, 193, 185, + 220, 198, 239, 243, 232, 228, 248, 182, 202, 236, + 240, 241, 249, 239, 206, 241, 229, 248, 250, 243, + 231, 201, 216, 136, 176, 220, 172, 161, 160, 189, + 190, 211, 188, 130, 138, 142, 129, 139, 142, 167, + 140, 156, 140, 146, 149, 147, 147, 159, 172, 149, + 147, 129, 145, 153, 165, 187, 165, 172, 160, 187, + 144, 143, 183, 176, 169, 175, 163, 180, 183, 137, + 187, 162, 189, 171, 130, 139, 174, 188, 182, 186, + 190, 182, 134, 187, 181, 161, 76, 68, 90, 68, + 0, 109, 89, 94, 75, 77, 69, 82, 85, 107, + 69, 92, 95, 73, 100, 113, 87, 76, 72, 82, + 64, 74, 108, 97, 83, 69, 93, 90, 110, 37, + 107, 122, 99, 71, 72, 90, 91, 65, 97, 114, + 99, 87, 97, 119, 115, 116, 124, 73, 123, 109, + 117, 114, 118, 94, 101, 125, 98, 126, 100, 121, + 19, 14, 26, 32, 0, 31, 25, 25, 66, 19, + 1, 19, 7, 10, 1, 17, 31, 9, 11, 58, + 68, 35, 59, 20, 6, 31, 17, 19, 91, 37, + 1, 27, 36, 46, 58, 21, 44, 58, 37, 33, + 38, 48, 28, 115, 37, 31, 113, 7, 20, 23, + 8, 5, 110, 3, 63, 49, 59, 54, 62, 37, + 10, 35, 49, 39, 199, 194, 198, 200, 194, 243, + 200, 200, 212, 198, 204, 206, 214, 202, 193, 203, + 206, 231, 250, 204, 205, 214, 210, 216, 193, 192, + 252, 208, 207, 210, 198, 233, 222, 249, 233, 237, + 231, 225, 235, 221, 238, 226, 244, 231, 233, 245, + 233, 171, 216, 238, 235, 240, 240, 250, 239, 238, + 222, 242, 233, 244, 228, 203, 217, 250, 142, 158, + 132, 140, 157, 179, 169, 149, 135, 128, 149, 149, + 143, 136, 138, 160, 148, 143, 145, 141, 135, 209, + 159, 142, 187, 157, 128, 132, 130, 167, 149, 135, + 171, 166, 173, 189, 171, 189, 191, 237, 239, 227, + 176, 160, 180, 166, 169, 160, 174, 190, 170, 249, + 252, 253, 252, 188, 190, 161, 181, 176, 178, 174, + 244, 176, 82, 66, 91, 93, 93, 124, 79, 95, + 75, 83, 84, 106, 67, 94, 109, 75, 89, 84, + 74, 75, 91, 92, 72, 29, 94, 86, 94, 86, + 66, 95, 20, 90, 108, 43, 94, 104, 124, 102, + 109, 99, 118, 112, 46, 33, 79, 115, 36, 104, + 111, 104, 108, 57, 124, 122, 60, 120, 100, 118, + 126, 49, 62, 124, 113, 108, 74, 70, 72, 31, + 15, 3, 25, 8, 66, 19, 1, 8, 20, 20, + 77, 40, 31, 22, 26, 28, 12, 95, 8, 4, + 2, 22, 80, 28, 3, 4, 0, 85, 40, 46, + 104, 0, 13, 32, 33, 61, 35, 49, 33, 35, + 42, 34, 11, 39, 48, 62, 59, 45, 45, 127, + 40, 36, 34, 54, 112, 62, 48, 119, 2, 52, + 216, 194, 201, 199, 218, 220, 130, 141, 235, 215, + 128, 204, 211, 212, 208, 133, 216, 222, 152, 240, + 253, 208, 209, 205, 211, 193, 209, 211, 218, 210, + 226, 212, 248, 226, 233, 231, 250, 252, 172, 228, + 246, 230, 237, 161, 226, 232, 225, 246, 186, 245, + 247, 237, 190, 235, 244, 248, 178, 224, 241, 252, + 243, 183, 224, 236, 154, 142, 200, 157, 134, 142, + 152, 205, 131, 151, 148, 147, 143, 133, 145, 145, + 159, 159, 216, 154, 146, 158, 143, 142, 210, 158, + 149, 156, 148, 146, 134, 219, 234, 130, 188, 233, + 163, 186, 191, 185, 226, 161, 165, 225, 136, 168, + 176, 229, 169, 174, 168, 169, 177, 173, 168, 184, + 182, 243, 185, 191, 166, 162, 160, 245, 90, 74, + 90, 72, 67, 74, 88, 72, 80, 3, 84, 88, + 86, 66, 4, 13, 83, 85, 92, 80, 93, 94, + 72, 82, 64, 122, 94, 85, 95, 84, 85, 65, + 101, 121, 40, 96, 125, 47, 109, 97, 112, 102, + 97, 101, 127, 39, 101, 97, 126, 126, 124, 85, + 119, 113, 121, 91, 125, 97, 125, 112, 98, 99, + 113, 113, 60, 10, 4, 28, 11, 32, 30, 9, + 7, 17, 19, 41, 15, 20, 16, 10, 8, 2, + 42, 28, 15, 10, 25, 14, 6, 35, 17, 3, + 23, 26, 17, 1, 47, 57, 59, 47, 60, 32, + 33, 57, 45, 23, 50, 32, 34, 34, 55, 13, + 51, 40, 44, 54, 44, 38, 14, 56, 35, 38, + 53, 34, 34, 7, 53, 39, 203, 198, 205, 221, + 203, 221, 223, 203, 205, 209, 195, 196, 244, 194, + 200, 202, 219, 223, 247, 248, 203, 203, 212, 239, + 215, 192, 197, 221, 194, 242, 218, 214, 248, 242, + 248, 253, 235, 235, 222, 232, 228, 241, 229, 242, + 238, 211, 235, 238, 255, 245, 205, 234, 251, 204, + 253, 235, 247, 247, 196, 254, 253, 242, 250, 230, + 166, 130, 134, 130, 186, 138, 148, 153, 178, 130, + 147, 146, 145, 136, 150, 129, 178, 148, 148, 157, + 155, 141, 172, 156, 129, 128, 135, 158, 132, 147, + 167, 148, 188, 174, 152, 168, 189, 188, 187, 162, + 176, 167, 180, 179, 167, 163, 165, 167, 182, 190, + 139, 160, 179, 189, 179, 177, 163, 166, 191, 165, + 179, 164, 135, 172, 71, 73, 71, 69, 90, 70, + 79, 70, 106, 74, 83, 85, 73, 85, 93, 118, + 67, 86, 90, 86, 82, 82, 85, 83, 71, 71, + 85, 121, 95, 68, 64, 90, 120, 114, 91, 112, + 99, 109, 99, 97, 102, 98, 121, 73, 111, 116, + 112, 106, 104, 98, 75, 96, 115, 125, 115, 113, + 100, 124, 124, 100, 123, 114, 85, 123, 11, 7, + 17, 26, 7, 28, 63, 20, 15, 1, 15, 13, + 21, 30, 9, 7, 21, 23, 53, 24, 14, 12, + 5, 16, 16, 28, 28, 60, 23, 7, 61, 17, + 30, 57, 41, 45, 47, 45, 32, 40, 17, 58, + 45, 35, 41, 43, 23, 60, 55, 57, 55, 53, + 126, 50, 61, 45, 114, 53, 63, 35, 118, 119, + 53, 57, 216, 206, 201, 205, 215, 143, 201, 213, + 203, 208, 212, 210, 242, 213, 197, 193, 219, 217, + 212, 220, 158, 222, 210, 217, 146, 194, 197, 222, + 194, 210, 199, 149, 249, 242, 229, 235, 225, 227, + 172, 236, 240, 230, 160, 245, 238, 226, 164, 246, + 251, 246, 253, 183, 190, 210, 253, 237, 226, 250, + 254, 246, 182, 254, 231, 181, 140, 132, 154, 139, + 135, 139, 136, 136, 140, 195, 148, 142, 198, 142, + 144, 150, 159, 151, 158, 173, 140, 158, 152, 156, + 144, 159, 149, 209, 151, 153, 144, 213, 190, 162, + 171, 162, 189, 239, 164, 164, 177, 183, 175, 179, + 191, 231, 183, 188, 183, 185, 183, 181, 254, 190, + 174, 184, 242, 167, 184, 180, 246, 164, 181, 184, + 79, 5, 8, 100, 79, 95, 92, 68, 76, 68, + 0, 72, 85, 7, 66, 74, 72, 89, 81, 93, + 90, 90, 82, 29, 70, 92, 16, 88, 66, 68, + 81, 89, 108, 95, 122, 104, 106, 110, 110, 97, + 103, 35, 97, 111, 98, 39, 105, 108, 116, 110, + 108, 124, 109, 63, 116, 116, 97, 103, 127, 99, + 111, 55, 103, 108, 7, 9, 7, 5, 78, 14, + 30, 8, 66, 23, 8, 4, 70, 20, 5, 8, + 31, 85, 88, 52, 31, 15, 12, 20, 28, 20, + 80, 24, 5, 87, 18, 26, 56, 41, 33, 45, + 42, 42, 34, 109, 54, 44, 96, 40, 50, 52, + 33, 41, 60, 15, 42, 56, 58, 62, 62, 49, + 55, 115, 49, 63, 50, 119, 48, 52, 211, 216, + 136, 193, 199, 220, 216, 194, 208, 218, 128, 210, + 223, 202, 198, 202, 214, 155, 217, 203, 219, 159, + 200, 213, 215, 147, 195, 208, 219, 210, 154, 149, + 199, 234, 248, 249, 231, 225, 235, 173, 235, 240, + 160, 231, 233, 245, 230, 236, 254, 255, 253, 247, + 190, 235, 243, 189, 251, 231, 227, 244, 250, 241, + 192, 231, 139, 143, 137, 139, 130, 138, 204, 140, + 140, 135, 192, 151, 137, 139, 145, 136, 159, 219, + 153, 151, 159, 147, 133, 142, 155, 128, 208, 130, + 143, 154, 150, 154, 166, 235, 169, 187, 171, 239, + 184, 165, 167, 227, 179, 160, 171, 162, 234, 229, + 151, 186, 168, 169, 183, 177, 187, 253, 187, 160, + 240, 183, 185, 165, 182, 188, 78, 79, 77, 71, + 14, 91, 67, 13, 75, 87, 83, 68, 74, 65, + 4, 8, 4, 27, 97, 86, 75, 31, 84, 92, + 68, 86, 16, 95, 89, 67, 20, 69, 101, 120, + 123, 96, 108, 102, 96, 100, 118, 122, 32, 117, + 105, 39, 103, 119, 127, 122, 108, 124, 62, 108, + 101, 112, 112, 124, 124, 98, 54, 122, 117, 101, + 26, 2, 6, 14, 78, 13, 9, 14, 3, 22, + 19, 4, 70, 14, 16, 69, 29, 20, 12, 89, + 10, 16, 92, 30, 27, 1, 19, 29, 19, 87, + 7, 12, 39, 41, 39, 37, 61, 111, 33, 44, + 50, 51, 41, 47, 33, 103, 108, 22, 35, 54, + 58, 54, 50, 30, 63, 62, 61, 38, 62, 37, + 6, 54, 61, 39, 249, 210, 197, 203, 193, 195, + 140, 144, 130, 143, 128, 224, 197, 196, 203, 208, + 212, 207, 152, 132, 158, 238, 201, 220, 220, 199, + 223, 198, 211, 197, 118, 28, 170, 218, 253, 232, + 224, 251, 227, 250, 231, 241, 160, 205, 202, 196, + 168, 165, 168, 171, 169, 161, 176, 191, 221, 241, + 254, 179, 226, 248, 241, 255, 224, 230, 202, 153, + 141, 154, 139, 157, 154, 136, 134, 139, 148, 149, + 150, 148, 222, 202, 213, 138, 141, 152, 144, 139, + 147, 138, 151, 129, 222, 146, 153, 154, 219, 133, + 184, 162, 190, 168, 173, 182, 164, 185, 182, 179, + 179, 251, 233, 232, 179, 178, 173, 245, 169, 172, + 191, 177, 168, 178, 165, 182, 162, 255, 181, 184, + 185, 250, 94, 78, 90, 68, 93, 2, 67, 75, + 15, 86, 83, 68, 78, 83, 80, 85, 73, 1, + 23, 22, 79, 74, 93, 83, 70, 92, 71, 84, + 68, 25, 87, 90, 103, 36, 96, 125, 122, 127, + 127, 55, 45, 44, 118, 51, 40, 125, 107, 117, + 115, 118, 54, 122, 113, 114, 51, 106, 123, 119, + 119, 116, 98, 56, 120, 124, 28, 14, 11, 1, + 15, 27, 66, 5, 22, 14, 12, 94, 7, 23, + 13, 58, 25, 26, 20, 21, 13, 66, 89, 72, + 48, 86, 69, 53, 80, 31, 27, 6, 62, 37, + 41, 36, 43, 114, 61, 56, 35, 45, 52, 46, + 49, 34, 54, 107, 57, 52, 53, 127, 53, 58, + 37, 96, 103, 4, 30, 53, 27, 39, 99, 103, + 157, 232, 223, 232, 204, 247, 234, 226, 237, 249, + 212, 219, 234, 200, 239, 213, 226, 207, 129, 242, + 230, 201, 244, 251, 148, 223, 209, 223, 209, 138, + 209, 219, 172, 227, 252, 253, 254, 252, 182, 162, + 173, 246, 240, 229, 231, 243, 225, 246, 180, 234, + 237, 248, 240, 235, 243, 234, 247, 225, 190, 242, + 249, 250, 187, 196, 159, 138, 134, 157, 129, 152, + 137, 159, 138, 151, 148, 145, 149, 221, 203, 202, + 139, 142, 153, 151, 138, 144, 139, 152, 128, 221, + 147, 158, 155, 216, 132, 135, 163, 168, 161, 167, + 169, 167, 184, 185, 178, 176, 250, 238, 233, 166, + 167, 166, 181, 174, 182, 173, 173, 241, 173, 168, + 179, 189, 164, 190, 161, 178, 166, 251, 73, 68, + 69, 126, 75, 15, 68, 76, 84, 70, 0, 82, + 67, 83, 4, 80, 74, 27, 76, 81, 91, 31, + 88, 88, 84, 82, 69, 93, 66, 23, 64, 71, + 107, 111, 97, 103, 105, 47, 105, 99, 116, 106, + 114, 110, 104, 106, 97, 107, 110, 59, 126, 118, + 108, 63, 101, 114, 103, 51, 103, 120, 98, 127, + 52, 87, 3, 5, 9, 7, 13, 10, 76, 36, + 12, 5, 15, 65, 11, 8, 0, 0, 84, 71, + 26, 11, 64, 67, 30, 15, 76, 42, 31, 4, + 86, 26, 21, 12, 106, 40, 39, 39, 32, 42, + 47, 57, 98, 55, 47, 97, 52, 34, 37, 41, + 122, 57, 42, 54, 53, 58, 46, 125, 37, 59, + 53, 63, 118, 46, 59, 32, 138, 202, 218, 204, + 142, 221, 201, 204, 198, 218, 128, 213, 201, 135, + 215, 209, 219, 201, 204, 153, 202, 205, 221, 217, + 219, 221, 215, 159, 245, 216, 193, 217, 238, 171, + 230, 230, 250, 175, 224, 226, 227, 231, 160, 243, + 227, 246, 241, 236, 232, 254, 252, 185, 255, 236, + 239, 248, 255, 241, 252, 232, 182, 246, 225, 225, + 133, 134, 137, 157, 135, 140, 141, 129, 142, 154, + 192, 175, 135, 138, 129, 223, 218, 219, 170, 156, + 143, 138, 153, 142, 134, 154, 158, 150, 183, 132, + 135, 144, 167, 169, 164, 176, 244, 239, 142, 164, + 172, 167, 169, 175, 161, 231, 182, 160, 190, 178, + 170, 188, 189, 171, 252, 170, 179, 160, 240, 176, + 166, 167, 184, 188, 79, 79, 8, 93, 65, 15, + 98, 76, 79, 70, 26, 1, 6, 117, 65, 65, + 83, 73, 93, 90, 74, 111, 93, 73, 90, 9, + 16, 127, 87, 90, 81, 21, 105, 106, 102, 41, + 96, 96, 120, 45, 96, 102, 32, 100, 107, 119, + 112, 124, 78, 115, 125, 57, 119, 107, 121, 112, + 50, 100, 121, 101, 126, 55, 103, 116, 7, 14, + 72, 7, 15, 2, 9, 77, 3, 15, 18, 4, + 7, 3, 29, 69, 31, 3, 17, 10, 10, 12, + 41, 86, 60, 18, 29, 20, 86, 20, 27, 0, + 38, 47, 104, 42, 33, 33, 56, 44, 43, 45, + 51, 123, 102, 10, 37, 44, 54, 29, 42, 54, + 51, 30, 56, 57, 32, 54, 35, 34, 118, 62, + 39, 117, 196, 222, 196, 197, 142, 192, 222, 141, + 199, 206, 208, 213, 223, 211, 193, 221, 206, 148, + 200, 213, 223, 214, 210, 129, 240, 225, 142, 187, + 138, 245, 230, 139, 170, 206, 229, 235, 235, 235, + 232, 232, 230, 163, 233, 236, 231, 224, 225, 165, + 166, 242, 245, 254, 190, 236, 238, 254, 175, 240, + 249, 245, 172, 244, 251, 248, 154, 138, 134, 144, + 130, 128, 139, 130, 220, 223, 162, 179, 216, 147, + 129, 157, 142, 212, 144, 141, 147, 147, 159, 146, + 159, 131, 145, 159, 143, 155, 155, 146, 165, 152, + 173, 189, 186, 166, 162, 170, 177, 142, 161, 175, + 167, 160, 161, 183, 244, 150, 185, 176, 178, 140, + 185, 175, 164, 182, 162, 255, 155, 182, 189, 185, + 127, 88, 77, 122, 125, 99, 111, 66, 76, 77, + 69, 66, 82, 78, 75, 75, 111, 72, 93, 25, + 109, 108, 112, 29, 81, 92, 94, 95, 83, 84, + 64, 92, 101, 101, 91, 108, 122, 123, 101, 99, + 101, 112, 77, 96, 104, 102, 99, 96, 104, 53, + 85, 120, 119, 115, 79, 120, 96, 101, 117, 99, + 56, 90, 117, 124, 6, 39, 7, 14, 7, 1, + 45, 24, 22, 11, 5, 15, 18, 14, 7, 4, + 14, 18, 23, 23, 94, 19, 19, 26, 27, 29, + 35, 20, 2, 3, 29, 27, 45, 56, 5, 40, + 32, 46, 43, 40, 48, 109, 13, 32, 47, 43, + 23, 32, 40, 45, 61, 43, 112, 18, 61, 52, + 62, 3, 49, 34, 37, 32, 59, 39, 206, 234, + 221, 221, 198, 202, 194, 217, 203, 192, 193, 213, + 207, 200, 202, 133, 202, 218, 203, 202, 201, 208, + 206, 217, 225, 214, 196, 197, 223, 217, 211, 198, + 199, 234, 230, 232, 233, 234, 254, 163, 207, 226, + 233, 237, 213, 226, 246, 243, 255, 233, 182, 212, + 255, 246, 240, 206, 223, 199, 192, 194, 243, 229, + 226, 240, 152, 191, 129, 132, 139, 128, 153, 153, + 177, 174, 180, 177, 198, 148, 129, 151, 140, 158, + 138, 217, 138, 150, 145, 152, 157, 134, 132, 221, + 214, 154, 135, 166, 175, 191, 188, 160, 160, 168, + 191, 128, 163, 173, 161, 166, 163, 181, 234, 136, + 187, 178, 180, 138, 187, 173, 170, 184, 160, 253, + 157, 176, 191, 187, 135, 152, 126, 123, 123, 76, + 92, 89, 73, 95, 113, 110, 116, 113, 6, 84, + 65, 87, 76, 94, 74, 106, 91, 75, 72, 84, + 92, 84, 67, 124, 87, 89, 85, 82, 111, 121, + 38, 68, 111, 102, 96, 94, 103, 113, 118, 100, + 116, 41, 73, 100, 115, 119, 75, 84, 74, 79, + 76, 114, 96, 103, 67, 92, 66, 71, 52, 101, + 5, 25, 28, 57, 15, 6, 30, 46, 13, 15, + 15, 19, 37, 8, 8, 10, 8, 74, 59, 22, + 18, 16, 14, 79, 33, 10, 29, 19, 25, 27, + 7, 85, 38, 34, 59, 61, 110, 33, 45, 32, + 39, 99, 35, 32, 40, 103, 42, 42, 46, 123, + 58, 60, 126, 58, 49, 45, 38, 42, 3, 48, + 59, 50, 116, 38, 211, 198, 202, 198, 194, 220, + 140, 193, 203, 208, 212, 129, 200, 198, 201, 192, + 154, 218, 212, 203, 219, 222, 216, 196, 146, 214, + 200, 216, 197, 195, 154, 149, 197, 249, 236, 236, + 252, 175, 197, 233, 184, 163, 160, 211, 227, 246, + 241, 224, 233, 239, 209, 253, 164, 191, 200, 239, + 243, 247, 249, 255, 241, 183, 251, 229, 143, 153, + 137, 157, 135, 128, 130, 205, 144, 134, 147, 148, + 138, 147, 192, 179, 149, 151, 141, 148, 155, 223, + 157, 147, 147, 159, 137, 130, 159, 132, 212, 150, + 171, 167, 171, 188, 162, 174, 184, 164, 173, 173, + 224, 167, 180, 168, 169, 229, 174, 178, 187, 178, + 173, 255, 180, 180, 161, 167, 191, 163, 175, 247, + 189, 166, 10, 69, 71, 93, 14, 78, 64, 65, + 77, 84, 69, 69, 6, 65, 75, 87, 26, 27, + 89, 91, 81, 77, 72, 88, 86, 29, 16, 98, + 79, 90, 86, 90, 102, 43, 53, 41, 97, 127, + 120, 100, 109, 109, 85, 111, 98, 98, 118, 105, + 115, 126, 106, 80, 106, 122, 113, 92, 113, 103, + 121, 126, 120, 86, 115, 114, 24, 14, 27, 26, + 1, 29, 42, 1, 3, 4, 35, 0, 10, 4, + 17, 9, 27, 15, 23, 11, 68, 95, 61, 17, + 23, 1, 4, 52, 24, 22, 22, 25, 47, 47, + 1, 58, 13, 32, 32, 34, 48, 42, 46, 38, + 7, 43, 33, 55, 46, 29, 49, 53, 42, 58, + 46, 28, 62, 54, 34, 37, 24, 50, 49, 49, + 233, 196, 198, 207, 199, 221, 193, 249, 208, 194, + 196, 200, 200, 192, 225, 221, 202, 210, 202, 220, + 251, 199, 204, 212, 192, 202, 228, 216, 219, 210, + 208, 209, 199, 198, 241, 240, 247, 246, 172, 197, + 202, 185, 237, 236, 188, 244, 247, 171, 252, 253, + 254, 255, 248, 249, 206, 248, 226, 246, 241, 229, + 215, 251, 241, 231, 158, 170, 139, 157, 135, 128, + 130, 158, 176, 134, 144, 132, 135, 147, 169, 132, + 130, 184, 151, 140, 144, 139, 174, 152, 130, 150, + 145, 133, 166, 146, 134, 156, 165, 175, 133, 160, + 160, 186, 184, 168, 177, 144, 165, 160, 180, 164, + 172, 132, 182, 190, 170, 173, 151, 155, 159, 178, + 188, 183, 185, 165, 191, 184, 186, 146, 88, 68, + 93, 89, 93, 110, 79, 89, 75, 76, 78, 82, + 101, 72, 74, 65, 83, 79, 81, 86, 80, 76, + 105, 83, 86, 86, 86, 88, 88, 82, 80, 102, + 115, 102, 106, 102, 98, 32, 78, 120, 113, 106, + 110, 100, 117, 116, 75, 103, 112, 126, 123, 109, + 87, 113, 122, 114, 83, 112, 115, 126, 99, 121, + 96, 58, 40, 30, 27, 0, 0, 10, 31, 30, + 45, 1, 10, 4, 5, 19, 45, 11, 28, 20, + 49, 10, 45, 26, 16, 24, 17, 7, 21, 21, + 53, 24, 25, 24, 35, 56, 59, 32, 33, 33, + 13, 63, 32, 42, 52, 51, 39, 32, 33, 22, + 35, 54, 58, 54, 50, 11, 53, 48, 55, 21, + 34, 48, 59, 50, 23, 58, 196, 205, 193, 206, + 199, 219, 201, 192, 246, 202, 195, 202, 134, 138, + 132, 241, 211, 216, 211, 153, 147, 159, 141, 201, + 219, 208, 219, 194, 226, 222, 215, 222, 170, 233, + 233, 251, 253, 204, 224, 248, 241, 247, 229, 243, + 197, 242, 247, 241, 245, 246, 219, 246, 242, 240, + 238, 209, 247, 229, 245, 253, 223, 228, 215, 253, + 143, 136, 131, 140, 138, 187, 137, 149, 150, 160, + 143, 141, 137, 149, 166, 132, 153, 144, 159, 139, + 145, 138, 146, 154, 177, 156, 156, 158, 132, 180, + 155, 153, 165, 185, 155, 189, 183, 163, 169, 154, + 171, 183, 168, 130, 169, 171, 171, 183, 137, 175, + 161, 181, 187, 136, 181, 185, 166, 187, 147, 190, + 186, 162, 185, 187, 105, 68, 70, 77, 71, 91, + 69, 66, 76, 106, 84, 68, 75, 100, 75, 75, + 94, 82, 76, 80, 81, 81, 104, 68, 66, 86, + 115, 94, 88, 83, 93, 65, 99, 100, 102, 95, + 111, 99, 121, 104, 65, 108, 108, 116, 107, 105, + 53, 74, 124, 125, 107, 124, 106, 92, 115, 113, + 103, 126, 126, 35, 89, 113, 114, 102, 15, 31, + 43, 6, 2, 26, 1, 3, 80, 49, 1, 15, + 1, 2, 55, 0, 22, 30, 27, 13, 17, 13, + 46, 28, 28, 20, 21, 37, 15, 7, 17, 48, + 36, 47, 7, 47, 40, 60, 41, 57, 4, 49, + 47, 44, 18, 40, 2, 44, 56, 52, 54, 56, + 61, 60, 53, 17, 55, 37, 53, 61, 26, 50, + 34, 48, 198, 254, 219, 204, 237, 218, 223, 217, + 205, 206, 233, 210, 227, 201, 197, 199, 214, 222, + 220, 250, 223, 207, 200, 212, 221, 221, 246, 222, + 216, 195, 247, 218, 230, 228, 250, 202, 239, 255, + 248, 228, 237, 237, 198, 238, 232, 243, 194, 228, + 247, 242, 244, 224, 208, 254, 241, 248, 209, 242, + 224, 229, 255, 248, 250, 211, 133, 133, 156, 186, + 135, 149, 137, 189, 141, 138, 142, 149, 170, 142, + 138, 128, 181, 139, 140, 144, 145, 145, 143, 170, + 155, 135, 152, 178, 158, 146, 151, 158, 136, 164, + 176, 158, 167, 187, 164, 131, 183, 174, 165, 179, + 175, 164, 147, 172, 174, 179, 155, 182, 178, 176, + 174, 155, 189, 189, 164, 156, 183, 175, 189, 184, + 95, 70, 127, 64, 74, 91, 68, 97, 75, 77, + 69, 114, 82, 94, 72, 64, 104, 72, 75, 112, + 74, 90, 81, 78, 96, 64, 67, 98, 83, 67, + 64, 92, 100, 108, 123, 75, 123, 124, 101, 99, + 103, 112, 115, 33, 72, 98, 115, 118, 58, 73, + 125, 108, 106, 122, 110, 110, 122, 103, 100, 97, + 44, 56, 59, 115, 15, 14, 12, 26, 64, 29, + 9, 24, 22, 6, 18, 18, 72, 4, 11, 8, + 85, 9, 29, 12, 10, 26, 14, 14, 93, 17, + 5, 2, 31, 25, 17, 6, 57, 37, 45, 62, + 61, 13, 14, 14, 98, 22, 11, 41, 50, 51, + 52, 127, 117, 116, 62, 60, 59, 59, 47, 115, + 48, 49, 51, 56, 120, 52, 59, 123, 223, 192, + 135, 199, 203, 216, 223, 130, 214, 198, 195, 201, + 200, 200, 200, 202, 221, 194, 151, 203, 205, 204, + 146, 197, 223, 223, 143, 212, 210, 222, 192, 220, + 229, 229, 181, 252, 229, 194, 237, 255, 233, 230, + 244, 241, 243, 235, 247, 224, 242, 239, 236, 233, + 164, 176, 179, 251, 247, 246, 244, 226, 184, 250, + 245, 231, 129, 142, 156, 158, 143, 155, 143, 133, + 204, 128, 143, 140, 201, 138, 133, 151, 145, 158, + 140, 142, 159, 139, 159, 149, 221, 158, 145, 131, + 157, 146, 128, 133, 191, 167, 187, 172, 225, 157, + 191, 190, 139, 183, 165, 172, 143, 180, 133, 166, + 174, 178, 174, 188, 139, 173, 176, 184, 188, 178, + 178, 189, 179, 179, 151, 239, 118, 108, 65, 93, + 66, 78, 78, 0, 112, 86, 78, 79, 67, 85, + 120, 71, 79, 82, 84, 93, 77, 99, 14, 94, + 106, 6, 114, 127, 122, 103, 104, 5, 86, 104, + 100, 96, 107, 97, 120, 81, 118, 102, 114, 108, + 111, 105, 101, 105, 70, 127, 125, 111, 123, 115, + 115, 109, 127, 118, 126, 101, 74, 85, 97, 102, + 3, 5, 13, 26, 29, 35, 13, 20, 7, 17, + 60, 53, 20, 6, 0, 12, 20, 28, 40, 21, + 31, 11, 26, 18, 0, 30, 94, 51, 3, 4, + 29, 27, 47, 56, 59, 5, 47, 54, 41, 63, + 30, 22, 52, 40, 42, 52, 24, 17, 40, 58, + 60, 48, 48, 56, 12, 47, 61, 39, 53, 50, + 34, 62, 59, 59, 246, 255, 218, 200, 202, 198, + 194, 202, 242, 209, 207, 213, 195, 196, 208, 202, + 200, 149, 219, 202, 206, 218, 206, 212, 221, 215, + 220, 216, 219, 222, 192, 250, 248, 239, 237, 251, + 253, 175, 224, 228, 239, 234, 244, 210, 227, 243, + 240, 236, 244, 252, 235, 212, 255, 241, 253, 250, + 247, 225, 190, 197, 228, 246, 240, 252, 132, 140, + 184, 155, 129, 155, 137, 142, 150, 138, 143, 143, + 200, 168, 150, 129, 159, 137, 139, 181, 151, 146, + 149, 137, 147, 135, 153, 158, 152, 217, 164, 144, + 184, 162, 167, 173, 157, 170, 184, 185, 171, 173, + 167, 178, 139, 166, 170, 164, 189, 190, 170, 247, + 138, 173, 189, 185, 187, 189, 183, 129, 164, 184, + 160, 176, 73, 95, 65, 70, 64, 1, 99, 95, + 70, 70, 82, 82, 106, 78, 73, 76, 78, 90, + 76, 80, 81, 81, 18, 113, 91, 94, 89, 69, + 117, 66, 70, 71, 111, 101, 124, 89, 111, 123, + 100, 94, 109, 118, 110, 101, 79, 115, 97, 104, + 105, 111, 119, 107, 127, 120, 121, 89, 115, 103, + 113, 66, 98, 120, 102, 116, 13, 14, 72, 0, + 29, 79, 8, 4, 17, 19, 15, 18, 3, 3, + 43, 49, 42, 51, 23, 21, 26, 26, 14, 50, + 38, 35, 38, 16, 26, 2, 17, 54, 37, 37, + 44, 32, 58, 38, 35, 35, 6, 34, 52, 32, + 9, 55, 33, 55, 59, 53, 60, 104, 17, 47, + 57, 47, 51, 61, 52, 99, 21, 56, 58, 49, + 195, 223, 193, 198, 192, 230, 216, 200, 207, 208, + 239, 209, 195, 213, 197, 203, 222, 248, 205, 202, + 202, 208, 209, 238, 198, 193, 217, 223, 209, 248, + 196, 208, 248, 234, 230, 237, 205, 250, 255, 249, + 237, 238, 211, 248, 235, 229, 235, 233, 213, 235, + 253, 235, 255, 241, 248, 222, 231, 224, 228, 254, + 251, 211, 245, 225, 143, 164, 152, 140, 156, 142, + 130, 137, 161, 150, 147, 149, 137, 138, 165, 134, + 153, 148, 141, 151, 138, 176, 140, 152, 128, 146, + 158, 149, 181, 130, 135, 129, 165, 166, 155, 172, + 162, 170, 175, 185, 173, 177, 143, 177, 163, 181, + 165, 171, 190, 148, 186, 179, 187, 188, 168, 141, + 160, 188, 160, 180, 164, 163, 173, 154, 90, 78, + 90, 72, 64, 75, 99, 79, 72, 70, 67, 85, + 118, 85, 75, 85, 95, 73, 76, 64, 109, 90, + 80, 88, 81, 71, 95, 67, 101, 67, 85, 71, + 126, 43, 122, 108, 125, 123, 99, 127, 103, 35, + 114, 100, 96, 117, 97, 118, 114, 59, 108, 118, + 117, 122, 114, 91, 115, 122, 124, 116, 114, 55, + 96, 122, 74, 25, 13, 26, 26, 0, 30, 8, + 66, 19, 18, 4, 16, 14, 11, 16, 9, 91, + 11, 28, 13, 12, 21, 18, 28, 93, 76, 51, + 36, 73, 36, 25, 47, 42, 59, 44, 110, 35, + 35, 42, 43, 45, 96, 32, 33, 38, 45, 43, + 116, 29, 57, 48, 50, 127, 40, 50, 114, 55, + 53, 50, 36, 46, 36, 33, 138, 228, 233, 252, + 250, 231, 140, 223, 199, 208, 212, 206, 212, 194, + 132, 209, 213, 208, 221, 215, 251, 209, 216, 157, + 192, 214, 195, 197, 217, 197, 209, 149, 248, 238, + 238, 251, 235, 252, 228, 173, 246, 236, 235, 228, + 232, 198, 241, 241, 242, 244, 234, 240, 234, 230, + 188, 200, 192, 223, 176, 249, 247, 228, 180, 251, + 133, 159, 200, 143, 129, 154, 130, 137, 164, 130, + 137, 141, 198, 147, 139, 197, 153, 148, 150, 151, + 155, 156, 136, 221, 134, 156, 208, 158, 183, 130, + 128, 157, 234, 241, 232, 143, 175, 166, 160, 237, + 182, 172, 224, 166, 163, 179, 228, 176, 169, 190, + 170, 249, 183, 177, 186, 178, 242, 233, 240, 157, + 191, 180, 177, 187, 73, 78, 8, 90, 75, 93, + 90, 68, 65, 70, 0, 116, 116, 107, 4, 77, + 91, 72, 24, 87, 81, 75, 28, 91, 93, 70, + 94, 85, 112, 86, 93, 89, 111, 111, 40, 125, + 97, 47, 111, 98, 108, 109, 101, 98, 114, 61, + 36, 55, 43, 45, 41, 43, 43, 44, 36, 45, + 34, 35, 32, 37, 34, 36, 57, 64, 4, 0, + 6, 6, 25, 1, 65, 93, 82, 87, 82, 88, + 75, 95, 84, 80, 72, 73, 85, 74, 74, 71, + 78, 68, 95, 50, 49, 65, 78, 65, 70, 71, + 122, 121, 125, 122, 125, 120, 124, 125, 114, 115, + 112, 117, 117, 106, 17, 43, 49, 53, 55, 46, + 48, 114, 108, 109, 102, 97, 105, 124, 110, 103, + 97, 103, 152, 134, 155, 157, 150, 157, 149, 128, + 227, 226, 144, 153, 144, 227, 193, 195, 219, 206, + 212, 205, 158, 204, 200, 207, 219, 221, 215, 156, + 156, 154, 132, 133, 185, 184, 185, 164, 191, 191, + 188, 189, 178, 174, 176, 177, 182, 183, 181, 168, + 219, 218, 169, 160, 172, 217, 253, 244, 254, 179, + 228, 254, 182, 244, 251, 251, 132, 142, 139, 157, + 206, 155, 131, 205, 141, 162, 149, 149, 142, 199, + 204, 151, 159, 136, 140, 150, 140, 154, 220, 137, + 157, 152, 149, 159, 223, 205, 212, 188, 174, 174, + 166, 189, 167, 187, 181, 237, 177, 166, 178, 183, + 163, 181, 228, 172, 169, 251, 173, 183, 191, 169, + 189, 180, 190, 178, 178, 189, 179, 247, 186, 186, + 93, 109, 73, 64, 66, 74, 72, 13, 86, 76, + 0, 83, 67, 84, 80, 74, 72, 94, 24, 74, + 91, 76, 79, 84, 93, 93, 10, 17, 94, 67, + 64, 69, 121, 49, 39, 38, 105, 110, 120, 104, + 117, 98, 121, 47, 103, 100, 103, 106, 111, 117, + 108, 106, 48, 110, 105, 124, 124, 103, 127, 102, + 115, 101, 58, 118, 5, 6, 71, 8, 30, 6, + 67, 27, 83, 76, 7, 0, 18, 2, 19, 4, + 3, 84, 17, 29, 27, 17, 8, 20, 6, 10, + 47, 20, 24, 19, 4, 26, 35, 37, 60, 29, + 60, 54, 108, 57, 45, 99, 39, 36, 50, 103, + 45, 33, 63, 53, 44, 48, 42, 38, 124, 56, + 60, 55, 32, 62, 63, 57, 32, 117, 204, 217, + 199, 196, 142, 195, 195, 206, 195, 207, 200, 206, + 213, 211, 197, 213, 211, 148, 206, 136, 145, 216, + 221, 201, 215, 196, 209, 200, 153, 208, 209, 193, + 213, 238, 230, 237, 254, 224, 229, 227, 246, 240, + 212, 243, 255, 167, 240, 234, 186, 252, 253, 237, + 190, 250, 242, 249, 226, 252, 249, 255, 226, 228, + 180, 243, 152, 132, 133, 201, 130, 128, 143, 140, + 142, 139, 143, 146, 146, 139, 141, 134, 159, 149, + 155, 156, 159, 143, 149, 210, 132, 194, 223, 131, + 131, 155, 145, 134, 158, 185, 177, 233, 186, 160, + 236, 170, 167, 183, 224, 173, 175, 164, 161, 171, + 185, 190, 171, 249, 184, 173, 179, 176, 242, 191, + 191, 178, 183, 187, 188, 186, 89, 95, 64, 76, + 79, 67, 88, 69, 107, 71, 69, 79, 82, 78, + 80, 92, 26, 83, 93, 88, 82, 75, 84, 7, + 18, 127, 89, 82, 83, 89, 87, 80, 71, 106, + 102, 104, 105, 106, 126, 45, 119, 112, 101, 115, + 38, 84, 109, 98, 116, 126, 124, 86, 107, 107, + 60, 127, 107, 51, 99, 116, 100, 97, 113, 103, + 38, 2, 11, 12, 0, 12, 9, 77, 15, 2, + 14, 0, 1, 2, 22, 69, 29, 30, 12, 89, + 12, 10, 16, 24, 1, 83, 21, 3, 4, 24, + 6, 79, 106, 7, 33, 42, 43, 33, 47, 40, + 98, 14, 33, 47, 39, 32, 33, 55, 96, 123, + 52, 48, 45, 43, 57, 51, 55, 33, 112, 33, + 57, 37, 32, 117, 197, 219, 205, 199, 199, 203, + 220, 223, 205, 197, 201, 205, 195, 200, 194, 195, + 214, 210, 214, 220, 225, 222, 223, 222, 215, 192, + 195, 253, 223, 212, 209, 219, 233, 238, 219, 236, + 252, 249, 229, 238, 231, 210, 245, 224, 232, 243, + 235, 242, 255, 233, 204, 252, 236, 242, 245, 243, + 243, 255, 166, 243, 242, 242, 165, 167, 137, 218, + 197, 222, 136, 216, 142, 192, 214, 211, 130, 215, + 203, 133, 129, 135, 155, 214, 206, 154, 206, 204, + 159, 158, 194, 145, 201, 192, 151, 195, 160, 135, + 179, 235, 188, 166, 238, 168, 169, 185, 226, 175, + 169, 162, 163, 169, 167, 160, 169, 251, 190, 171, + 177, 178, 252, 174, 183, 161, 166, 180, 164, 247, + 163, 188, 94, 67, 8, 90, 75, 67, 74, 13, + 81, 74, 71, 79, 67, 67, 4, 70, 95, 73, + 76, 114, 91, 76, 72, 79, 87, 95, 16, 93, + 95, 68, 64, 80, 100, 98, 102, 110, 46, 122, + 126, 97, 56, 35, 60, 105, 55, 57, 93, 106, + 111, 59, 123, 120, 112, 63, 114, 114, 101, 51, + 98, 116, 98, 98, 102, 123, 74, 31, 7, 73, + 26, 7, 9, 77, 3, 19, 16, 13, 15, 4, + 5, 17, 19, 20, 22, 87, 66, 80, 20, 76, + 76, 52, 53, 37, 57, 39, 32, 60, 5, 5, + 27, 25, 1, 28, 24, 44, 50, 51, 44, 40, + 37, 38, 48, 44, 53, 53, 119, 33, 115, 40, + 43, 42, 127, 53, 63, 35, 59, 122, 33, 39, + 198, 206, 198, 202, 193, 203, 201, 201, 206, 204, + 195, 192, 202, 207, 203, 214, 206, 249, 202, 214, + 201, 204, 217, 207, 146, 193, 213, 194, 195, 219, + 192, 149, 176, 171, 205, 228, 254, 251, 245, 173, + 240, 230, 243, 241, 233, 233, 247, 224, 180, 181, + 184, 220, 240, 235, 245, 233, 235, 179, 173, 177, + 219, 242, 249, 247, 143, 153, 200, 206, 201, 207, + 129, 132, 145, 144, 137, 143, 129, 164, 222, 185, + 189, 146, 140, 149, 159, 157, 209, 175, 135, 157, + 158, 148, 132, 171, 150, 128, 163, 167, 172, 186, + 146, 253, 175, 149, 247, 129, 142, 141, 150, 155, + 244, 153, 185, 183, 177, 188, 176, 171, 128, 169, + 183, 161, 189, 184, 184, 182, 184, 137, 78, 78, + 94, 76, 66, 64, 92, 64, 71, 77, 84, 125, + 100, 82, 87, 76, 84, 94, 75, 74, 114, 94, + 69, 88, 64, 111, 100, 67, 87, 83, 93, 91, + 109, 91, 100, 104, 122, 105, 99, 127, 111, 45, + 66, 116, 117, 110, 106, 96, 105, 104, 84, 120, + 103, 122, 110, 65, 86, 114, 100, 112, 84, 126, + 122, 113, 3, 5, 15, 53, 45, 0, 2, 27, + 7, 17, 20, 4, 20, 20, 56, 54, 14, 9, + 17, 23, 25, 43, 19, 49, 29, 16, 17, 29, + 31, 13, 17, 17, 25, 63, 58, 32, 32, 40, + 15, 34, 44, 53, 37, 51, 50, 34, 54, 107, + 57, 40, 59, 54, 48, 41, 57, 47, 38, 23, + 53, 61, 51, 48, 53, 33, 207, 255, 205, 197, + 203, 200, 222, 204, 207, 230, 205, 192, 207, 203, + 233, 192, 201, 200, 221, 215, 217, 218, 206, 206, + 255, 210, 222, 208, 209, 210, 198, 143, 170, 226, + 230, 224, 250, 230, 237, 225, 235, 249, 225, 245, + 239, 232, 234, 171, 180, 181, 213, 252, 237, 236, + 249, 243, 245, 246, 226, 210, 247, 249, 179, 225, + 202, 136, 154, 140, 143, 155, 137, 205, 171, 174, + 133, 146, 149, 130, 138, 130, 159, 137, 216, 159, + 140, 144, 145, 221, 134, 138, 128, 148, 214, 186, + 145, 134, 185, 174, 166, 174, 171, 189, 236, 186, + 171, 183, 168, 225, 168, 166, 169, 160, 250, 251, + 185, 181, 172, 186, 189, 185, 171, 243, 181, 169, + 191, 164, 160, 166, 4, 102, 77, 90, 93, 74, + 66, 74, 71, 81, 83, 108, 71, 73, 69, 66, + 95, 73, 2, 25, 30, 82, 89, 78, 65, 86, + 94, 86, 83, 69, 71, 21, 125, 110, 122, 108, + 46, 99, 99, 108, 102, 102, 100, 47, 75, 98, + 119, 118, 127, 117, 127, 124, 108, 108, 81, 124, + 124, 114, 119, 116, 100, 45, 52, 124, 4, 2, + 28, 0, 15, 3, 5, 23, 3, 23, 9, 14, + 8, 71, 2, 12, 20, 18, 11, 17, 27, 27, + 82, 60, 1, 0, 21, 5, 5, 50, 12, 22, + 34, 42, 38, 46, 43, 60, 13, 46, 33, 44, + 53, 47, 50, 52, 23, 60, 55, 57, 55, 53, + 45, 16, 44, 41, 59, 60, 62, 2, 51, 37, + 61, 48, 217, 239, 201, 208, 236, 206, 222, 222, + 225, 209, 217, 209, 210, 200, 229, 198, 217, 212, + 205, 215, 202, 204, 253, 206, 193, 214, 196, 243, + 215, 219, 213, 219, 233, 238, 251, 198, 254, 234, + 226, 194, 240, 231, 229, 243, 245, 202, 225, 246, + 233, 250, 255, 252, 237, 207, 243, 238, 251, 231, + 249, 254, 248, 218, 241, 230, 153, 138, 143, 140, + 157, 160, 156, 136, 140, 167, 133, 141, 143, 145, + 129, 151, 159, 159, 185, 138, 141, 154, 136, 176, + 151, 128, 131, 144, 145, 146, 135, 166, 175, 184, + 187, 160, 161, 161, 191, 142, 173, 173, 180, 160, + 175, 169, 161, 183, 169, 136, 182, 184, 174, 172, + 180, 178, 166, 151, 177, 165, 183, 251, 244, 156, + 110, 17, 8, 5, 14, 97, 77, 64, 71, 25, + 0, 13, 6, 101, 69, 73, 91, 85, 91, 92, + 4, 31, 113, 88, 65, 64, 81, 86, 83, 118, + 87, 86, 101, 126, 102, 125, 79, 124, 127, 104, + 118, 74, 100, 67, 103, 107, 101, 107, 121, 126, + 86, 124, 106, 107, 117, 115, 117, 71, 105, 97, + 115, 86, 119, 118, 5, 30, 6, 29, 47, 11, + 8, 4, 22, 10, 15, 15, 7, 11, 45, 11, + 28, 20, 60, 28, 13, 28, 14, 20, 2, 7, + 25, 30, 24, 58, 29, 27, 35, 38, 61, 36, + 13, 39, 45, 35, 37, 38, 9, 18, 9, 6, + 39, 38, 53, 46, 54, 45, 23, 59, 8, 50, + 38, 50, 60, 19, 55, 59, 53, 59, 201, 206, + 233, 223, 207, 198, 192, 204, 192, 207, 197, 227, + 199, 203, 197, 203, 217, 222, 234, 220, 205, 218, + 206, 203, 215, 215, 242, 208, 218, 214, 218, 214, + 239, 223, 231, 253, 239, 227, 197, 227, 215, 208, + 196, 213, 233, 243, 229, 233, 211, 245, 218, 205, + 221, 219, 249, 255, 230, 214, 225, 228, 255, 227, + 237, 208, 155, 158, 129, 157, 151, 166, 130, 175, + 182, 160, 204, 193, 168, 134, 137, 128, 218, 182, + 157, 138, 141, 158, 155, 152, 183, 139, 147, 153, + 151, 153, 147, 144, 143, 179, 171, 161, 175, 161, + 171, 168, 139, 167, 133, 185, 165, 175, 165, 171, + 189, 190, 150, 184, 179, 186, 143, 184, 161, 160, + 185, 190, 184, 164, 151, 186, 68, 95, 73, 64, + 64, 74, 94, 100, 70, 110, 69, 82, 85, 70, + 67, 64, 117, 75, 93, 87, 122, 90, 80, 84, + 68, 86, 66, 84, 82, 118, 71, 70, 111, 127, + 91, 112, 99, 109, 99, 97, 75, 103, 83, 117, + 103, 115, 113, 118, 89, 105, 125, 120, 106, 118, + 115, 115, 70, 122, 125, 116, 58, 55, 71, 108, + 7, 9, 7, 5, 84, 79, 64, 77, 50, 17, + 9, 2, 3, 93, 68, 73, 90, 40, 17, 29, + 27, 69, 92, 81, 82, 39, 9, 1, 19, 77, + 84, 56, 47, 56, 59, 40, 41, 42, 3, 61, + 39, 45, 15, 51, 34, 34, 54, 10, 40, 63, + 61, 43, 23, 59, 27, 47, 61, 38, 32, 24, + 50, 7, 59, 38, 195, 223, 193, 198, 192, 230, + 200, 249, 205, 215, 193, 205, 247, 210, 197, 203, + 206, 210, 204, 192, 248, 214, 208, 209, 215, 215, + 225, 196, 215, 217, 192, 220, 254, 242, 219, 224, + 234, 234, 207, 226, 239, 238, 229, 239, 242, 203, + 229, 246, 238, 206, 232, 253, 255, 235, 249, 201, + 251, 254, 245, 222, 228, 243, 241, 231, 190, 146, + 152, 140, 167, 139, 184, 132, 143, 134, 169, 143, + 160, 136, 150, 134, 159, 190, 128, 137, 151, 141, + 157, 137, 155, 156, 158, 165, 159, 154, 145, 161, + 184, 162, 175, 174, 171, 189, 156, 191, 171, 160, + 165, 149, 180, 166, 173, 169, 149, 189, 190, 170, + 187, 171, 147, 175, 187, 180, 185, 191, 183, 187, + 135, 161, 75, 95, 93, 90, 111, 75, 72, 68, + 86, 74, 79, 79, 71, 75, 109, 75, 92, 84, + 113, 77, 91, 82, 79, 17, 18, 124, 64, 84, + 88, 23, 68, 71, 99, 104, 109, 51, 46, 66, + 105, 126, 113, 98, 103, 100, 73, 119, 97, 107, + 74, 116, 107, 112, 106, 118, 115, 115, 93, 99, + 117, 127, 70, 101, 125, 118, 15, 36, 24, 12, + 0, 32, 30, 9, 7, 17, 41, 5, 42, 14, + 21, 16, 19, 31, 25, 13, 23, 16, 18, 45, + 0, 26, 19, 20, 37, 14, 25, 23, 37, 39, + 114, 105, 110, 10, 52, 61, 6, 34, 52, 36, + 124, 103, 100, 11, 59, 54, 61, 99, 126, 18, + 57, 46, 33, 50, 55, 52, 25, 39, 32, 60, + 197, 197, 251, 204, 220, 198, 201, 232, 218, 211, + 201, 211, 199, 211, 205, 202, 212, 255, 217, 205, + 219, 236, 217, 207, 219, 214, 228, 200, 198, 210, + 152, 149, 220, 234, 228, 252, 235, 181, 172, 197, + 237, 239, 233, 229, 231, 254, 247, 214, 255, 232, + 235, 240, 241, 241, 239, 206, 247, 231, 227, 220, + 243, 228, 231, 244, 141, 142, 187, 140, 157, 156, + 133, 130, 140, 144, 163, 142, 136, 147, 133, 140, + 148, 158, 138, 181, 145, 139, 175, 137, 151, 131, + 189, 152, 152, 187, 155, 129, 135, 170, 176, 133, + 161, 187, 153, 163, 166, 166, 178, 173, 175, 162, + 182, 139, 187, 182, 189, 152, 168, 190, 181, 177, + 179, 177, 188, 180, 144, 162, 160, 160, 88, 78, + 91, 104, 88, 78, 69, 65, 67, 65, 76, 68, + 105, 87, 80, 76, 85, 85, 75, 118, 78, 75, + 85, 82, 92, 96, 85, 67, 95, 82, 125, 81, + 69, 123, 124, 96, 97, 97, 88, 116, 114, 102, + 83, 117, 116, 110, 111, 96, 74, 105, 113, 122, + 123, 83, 125, 110, 102, 71, 98, 112, 114, 126, + 122, 114, 46, 10, 28, 12, 56, 14, 30, 4, + 3, 1, 12, 4, 50, 14, 7, 14, 54, 18, + 11, 13, 42, 13, 29, 25, 23, 73, 80, 93, + 86, 38, 0, 12, 112, 107, 100, 105, 1, 61, + 40, 40, 48, 99, 41, 37, 124, 103, 23, 44, + 61, 53, 57, 53, 100, 127, 17, 52, 60, 7, + 34, 48, 50, 50, 2, 58, 198, 222, 197, 204, + 227, 198, 194, 141, 214, 209, 193, 197, 195, 135, + 210, 202, 214, 206, 213, 220, 253, 133, 224, 250, + 219, 199, 220, 208, 212, 154, 230, 192, 228, 229, + 237, 251, 210, 237, 249, 228, 238, 231, 243, 221, + 180, 228, 220, 176, 216, 213, 212, 201, 194, 175, + 192, 254, 254, 250, 245, 255, 226, 203, 224, 240, + 152, 134, 129, 135, 143, 131, 176, 137, 135, 149, + 133, 141, 137, 151, 137, 128, 148, 143, 164, 187, + 139, 140, 149, 147, 151, 128, 131, 189, 151, 142, + 145, 135, 150, 159, 186, 168, 170, 166, 162, 170, + 146, 175, 161, 181, 160, 168, 182, 168, 244, 153, + 173, 170, 183, 177, 185, 174, 161, 159, 177, 168, + 179, 165, 136, 157, 67, 88, 92, 70, 92, 86, + 112, 108, 69, 68, 82, 68, 65, 70, 80, 76, + 85, 85, 75, 101, 118, 86, 79, 73, 93, 65, + 73, 112, 81, 80, 70, 80, 109, 106, 124, 96, + 97, 97, 92, 98, 117, 102, 114, 85, 116, 102, + 96, 96, 105, 75, 121, 107, 127, 114, 121, 105, + 119, 97, 99, 63, 117, 100, 89, 116, 18, 63, + 26, 8, 10, 10, 58, 2, 14, 22, 13, 4, + 43, 6, 28, 69, 14, 9, 25, 29, 27, 95, + 10, 18, 30, 6, 29, 20, 34, 24, 0, 20, + 38, 29, 39, 37, 59, 34, 41, 25, 45, 55, + 33, 45, 102, 49, 43, 41, 47, 54, 61, 13, + 55, 50, 57, 20, 60, 39, 53, 35, 32, 54, + 56, 1, 195, 198, 205, 137, 199, 193, 216, 200, + 208, 213, 193, 205, 138, 135, 215, 192, 217, 249, + 217, 202, 215, 204, 234, 210, 222, 198, 221, 212, + 255, 217, 192, 208, 248, 253, 233, 229, 204, 238, + 255, 228, 241, 163, 246, 238, 234, 242, 233, 224, + 186, 242, 246, 237, 251, 237, 234, 252, 254, 191, + 176, 226, 243, 244, 208, 240, 134, 159, 137, 175, + 135, 131, 152, 136, 144, 165, 137, 141, 146, 130, + 150, 197, 152, 130, 216, 189, 155, 147, 136, 156, + 222, 211, 213, 179, 151, 132, 157, 134, 152, 170, + 188, 160, 161, 137, 165, 161, 182, 166, 178, 135, + 175, 171, 176, 160, 168, 251, 186, 160, 254, 157, + 189, 174, 187, 160, 240, 163, 183, 163, 189, 186, + 6, 11, 13, 100, 79, 87, 118, 66, 76, 70, + 104, 68, 79, 64, 76, 81, 119, 90, 64, 25, + 68, 80, 82, 88, 18, 91, 85, 88, 81, 95, + 64, 25, 42, 127, 97, 106, 101, 124, 65, 100, + 108, 89, 111, 111, 99, 79, 97, 108, 125, 115, + 108, 84, 119, 113, 60, 103, 125, 125, 117, 49, + 126, 114, 125, 114, 2, 31, 68, 73, 26, 6, + 15, 6, 17, 32, 21, 18, 18, 8, 9, 49, + 19, 24, 19, 42, 23, 5, 25, 62, 7, 0, + 4, 30, 27, 87, 0, 28, 41, 32, 104, 58, + 39, 53, 41, 15, 35, 49, 16, 51, 47, 36, + 33, 17, 35, 43, 61, 10, 42, 59, 31, 60, + 62, 48, 37, 61, 55, 35, 61, 58, 196, 255, + 209, 217, 203, 143, 208, 141, 246, 204, 212, 192, + 202, 135, 198, 196, 214, 218, 214, 218, 219, 133, + 156, 233, 221, 199, 209, 221, 244, 214, 216, 212, + 228, 232, 237, 169, 254, 234, 254, 238, 231, 237, + 244, 190, 175, 184, 215, 224, 246, 254, 251, 237, + 251, 251, 188, 233, 251, 254, 245, 177, 255, 249, + 180, 243, 133, 153, 139, 140, 206, 129, 131, 153, + 194, 130, 140, 141, 137, 144, 129, 129, 218, 157, + 151, 139, 222, 223, 147, 143, 150, 150, 130, 209, + 130, 142, 132, 144, 131, 165, 171, 166, 188, 189, + 169, 174, 182, 227, 147, 141, 233, 147, 148, 229, + 170, 169, 177, 186, 187, 255, 177, 184, 179, 160, + 165, 163, 179, 186, 177, 187, 94, 17, 8, 14, + 9, 15, 65, 72, 67, 80, 85, 83, 67, 74, + 65, 75, 78, 27, 89, 85, 82, 80, 75, 88, + 86, 31, 16, 83, 67, 67, 20, 18, 45, 43, + 101, 108, 111, 124, 121, 127, 103, 110, 101, 111, + 114, 39, 119, 96, 118, 126, 123, 109, 123, 123, + 50, 61, 66, 127, 117, 112, 101, 114, 56, 53, + 9, 4, 26, 27, 11, 12, 24, 77, 49, 47, + 79, 53, 54, 71, 20, 4, 8, 26, 21, 28, + 10, 26, 14, 14, 49, 28, 30, 31, 19, 20, + 0, 28, 37, 37, 7, 59, 42, 42, 62, 109, + 11, 7, 15, 51, 34, 34, 54, 101, 46, 34, + 40, 60, 10, 22, 26, 14, 38, 60, 32, 113, + 58, 56, 39, 38, 138, 240, 252, 219, 128, 143, + 255, 225, 130, 204, 198, 199, 213, 194, 208, 133, + 225, 232, 204, 214, 206, 159, 208, 210, 193, 192, + 228, 195, 152, 151, 231, 249, 170, 228, 238, 239, + 253, 234, 248, 217, 227, 232, 229, 161, 246, 245, + 235, 227, 243, 239, 184, 194, 202, 254, 247, 248, + 178, 227, 226, 254, 240, 254, 224, 209, 139, 159, + 141, 198, 186, 134, 129, 136, 177, 140, 149, 147, + 133, 130, 176, 140, 151, 158, 216, 144, 144, 223, + 154, 146, 128, 144, 149, 178, 204, 171, 179, 156, + 190, 167, 169, 171, 227, 157, 185, 163, 172, 166, + 178, 157, 164, 178, 173, 169, 190, 168, 132, 235, + 189, 135, 233, 159, 156, 159, 128, 141, 230, 139, + 183, 185, 67, 78, 70, 93, 114, 91, 73, 95, + 79, 74, 78, 64, 74, 123, 64, 64, 76, 94, + 84, 86, 78, 82, 89, 83, 70, 111, 114, 68, + 69, 94, 90, 80, 121, 120, 68, 104, 119, 106, + 126, 81, 86, 113, 97, 101, 111, 105, 99, 85, + 118, 122, 108, 127, 113, 109, 113, 51, 80, 102, + 99, 120, 120, 114, 103, 102, 38, 10, 17, 12, + 28, 51, 46, 24, 17, 10, 14, 4, 21, 20, + 43, 7, 16, 30, 27, 13, 13, 35, 51, 15, + 22, 22, 2, 37, 15, 7, 17, 6, 22, 4, + 58, 45, 43, 61, 24, 52, 50, 38, 110, 34, + 53, 2, 60, 53, 51, 41, 57, 45, 55, 48, + 50, 31, 39, 42, 3, 52, 58, 59, 56, 58, + 222, 216, 250, 192, 221, 196, 128, 141, 134, 241, + 201, 210, 205, 139, 132, 128, 159, 155, 233, 205, + 199, 133, 156, 157, 230, 193, 158, 194, 194, 216, + 196, 143, 170, 171, 219, 197, 76, 47, 227, 235, + 228, 240, 229, 245, 188, 167, 70, 37, 234, 233, + 241, 250, 251, 165, 188, 189, 253, 245, 246, 226, + 243, 227, 174, 181, 202, 191, 184, 201, 158, 157, + 133, 142, 135, 217, 192, 201, 198, 129, 139, 151, + 218, 219, 208, 182, 189, 176, 213, 221, 218, 191, + 159, 146, 151, 155, 221, 157, 163, 184, 188, 166, + 188, 182, 158, 168, 179, 182, 165, 178, 178, 151, + 165, 183, 187, 182, 189, 173, 187, 173, 175, 155, + 226, 227, 224, 225, 230, 231, 132, 229, 106, 11, + 92, 70, 14, 15, 127, 89, 82, 25, 0, 104, + 85, 100, 86, 92, 74, 79, 87, 23, 70, 82, + 80, 110, 75, 94, 82, 94, 90, 99, 77, 69, + 111, 77, 125, 125, 123, 125, 105, 126, 65, 108, + 110, 117, 116, 102, 103, 113, 78, 98, 104, 124, + 76, 112, 115, 105, 65, 106, 125, 115, 121, 123, + 52, 98, 11, 24, 72, 7, 1, 27, 76, 11, + 13, 22, 14, 5, 70, 1, 11, 23, 90, 22, + 29, 10, 13, 30, 27, 24, 82, 94, 78, 81, + 86, 4, 13, 24, 40, 36, 36, 0, 42, 111, + 113, 109, 101, 34, 51, 50, 47, 32, 42, 40, + 63, 53, 44, 42, 59, 44, 47, 52, 61, 61, + 56, 62, 58, 62, 48, 52, 211, 216, 205, 218, + 221, 198, 195, 195, 225, 204, 206, 213, 199, 206, + 202, 192, 200, 255, 221, 213, 202, 222, 156, 223, + 211, 193, 195, 245, 211, 219, 192, 212, 170, 253, + 233, 229, 251, 234, 172, 225, 237, 247, 243, 192, + 225, 224, 246, 224, 253, 250, 236, 252, 250, 191, + 216, 210, 223, 208, 241, 253, 245, 226, 248, 244, + 158, 130, 135, 135, 206, 141, 141, 158, 139, 144, + 176, 147, 143, 132, 129, 197, 150, 158, 142, 156, + 146, 140, 220, 145, 155, 158, 153, 133, 184, 152, + 128, 213, 185, 190, 184, 185, 161, 189, 184, 168, + 166, 227, 172, 164, 176, 162, 168, 182, 158, 148, + 149, 249, 188, 166, 252, 169, 187, 190, 181, 149, + 153, 154, 244, 183, 83, 11, 92, 64, 77, 68, + 95, 13, 65, 76, 85, 79, 82, 115, 77, 70, + 81, 72, 24, 90, 81, 74, 82, 73, 122, 86, + 89, 90, 95, 89, 20, 116, 121, 99, 97, 69, + 111, 124, 120, 64, 99, 113, 107, 67, 111, 99, + 69, 118, 113, 86, 113, 125, 110, 112, 117, 115, + 102, 80, 42, 77, 81, 126, 96, 121, 11, 9, + 69, 59, 27, 1, 2, 8, 16, 63, 2, 20, + 15, 11, 0, 22, 38, 73, 27, 33, 75, 61, + 50, 49, 34, 47, 64, 45, 21, 27, 29, 16, + 36, 63, 20, 61, 43, 61, 33, 36, 44, 34, + 44, 29, 34, 34, 50, 32, 54, 52, 40, 52, + 59, 49, 40, 1, 16, 38, 35, 56, 56, 50, + 39, 38, 230, 202, 209, 204, 220, 243, 248, 223, + 195, 199, 201, 207, 193, 247, 200, 196, 206, 221, + 215, 203, 211, 145, 254, 200, 193, 218, 222, 212, + 197, 196, 248, 212, 243, 238, 250, 213, 198, 230, + 255, 249, 237, 241, 249, 221, 199, 224, 227, 247, + 255, 252, 249, 237, 247, 240, 242, 238, 206, 219, + 249, 226, 226, 248, 230, 236, 171, 140, 143, 155, + 139, 136, 141, 153, 139, 140, 142, 169, 131, 142, + 143, 128, 148, 186, 139, 145, 151, 209, 159, 142, + 129, 156, 133, 131, 149, 146, 182, 128, 163, 167, + 172, 233, 168, 189, 163, 160, 138, 170, 179, 181, + 169, 181, 189, 229, 174, 162, 168, 188, 146, 186, + 170, 184, 190, 225, 128, 163, 191, 180, 177, 245, + 73, 67, 73, 71, 73, 74, 95, 13, 65, 76, + 85, 79, 82, 7, 70, 68, 72, 72, 106, 88, + 80, 88, 89, 29, 80, 82, 66, 66, 98, 94, + 87, 94, 121, 89, 109, 127, 107, 125, 127, 108, + 110, 79, 101, 111, 97, 115, 108, 87, 127, 109, + 125, 107, 109, 126, 112, 61, 94, 118, 126, 118, + 98, 127, 87, 116, 6, 8, 29, 5, 15, 27, + 5, 2, 12, 67, 52, 24, 22, 2, 39, 95, + 38, 60, 17, 13, 18, 30, 30, 80, 32, 6, + 30, 31, 19, 5, 40, 23, 63, 34, 36, 45, + 61, 19, 126, 46, 26, 118, 2, 15, 10, 23, + 24, 117, 6, 56, 52, 48, 59, 49, 40, 1, + 38, 54, 34, 60, 63, 57, 53, 57, 246, 207, + 205, 223, 203, 195, 195, 221, 207, 198, 206, 213, + 250, 229, 209, 214, 211, 213, 221, 202, 205, 243, + 221, 196, 215, 193, 236, 229, 196, 214, 208, 220, + 228, 236, 216, 229, 239, 251, 234, 226, 240, 238, + 174, 195, 243, 244, 237, 235, 255, 232, 235, 213, + 255, 230, 249, 239, 206, 219, 249, 226, 226, 248, + 230, 236, 182, 170, 143, 142, 156, 138, 139, 140, + 150, 138, 143, 143, 149, 187, 172, 140, 137, 143, + 151, 139, 135, 190, 155, 154, 128, 150, 151, 144, + 130, 158, 155, 155, 152, 174, 190, 172, 188, 188, + 173, 161, 236, 160, 179, 131, 175, 163, 228, 132, + 169, 176, 154, 176, 186, 158, 175, 182, 147, 180, + 183, 163, 179, 176, 181, 161, 79, 79, 8, 93, + 71, 76, 71, 94, 2, 11, 108, 64, 85, 83, + 13, 113, 83, 86, 93, 125, 91, 83, 93, 68, + 102, 90, 93, 84, 26, 23, 89, 70, 73, 49, + 84, 78, 103, 123, 96, 108, 96, 46, 82, 116, + 104, 105, 97, 119, 70, 121, 109, 112, 114, 123, + 111, 65, 32, 112, 72, 36, 84, 89, 88, 69, + 54, 91, 52, 10, 2, 6, 9, 3, 22, 63, + 20, 4, 20, 10, 13, 11, 27, 23, 36, 29, + 27, 9, 25, 17, 29, 3, 29, 20, 24, 3, + 40, 55, 63, 56, 33, 39, 43, 60, 63, 1, + 35, 58, 37, 51, 26, 19, 54, 36, 62, 50, + 54, 62, 14, 51, 61, 41, 52, 60, 34, 60, + 120, 21, 33, 38, 195, 197, 205, 218, 221, 227, + 205, 212, 199, 209, 252, 233, 207, 212, 208, 202, + 200, 194, 228, 248, 217, 216, 206, 216, 213, 210, + 196, 216, 217, 217, 199, 233, 194, 226, 251, 253, + 225, 253, 245, 204, 229, 228, 242, 228, 225, 230, + 240, 236, 245, 245, 204, 240, 253, 244, 208, 252, + 225, 231, 209, 246, 241, 229, 241, 242, 139, 159, + 141, 141, 192, 140, 159, 185, 139, 142, 133, 181, + 143, 138, 129, 197, 137, 143, 153, 141, 151, 140, + 136, 148, 145, 128, 166, 158, 154, 130, 153, 144, + 234, 187, 186, 166, 168, 166, 160, 168, 148, 172, + 172, 180, 171, 162, 228, 179, 187, 183, 173, 188, + 136, 136, 157, 141, 155, 189, 166, 176, 186, 190, + 176, 245, 126, 67, 65, 90, 14, 103, 69, 94, + 86, 76, 82, 72, 69, 70, 72, 97, 91, 79, + 89, 122, 75, 76, 72, 82, 95, 19, 89, 66, + 22, 86, 64, 65, 107, 104, 96, 108, 106, 47, + 120, 98, 34, 106, 110, 101, 111, 100, 101, 113, + 117, 105, 56, 59, 60, 49, 60, 75, 115, 127, + 101, 116, 101, 55, 119, 122, 31, 5, 28, 73, + 25, 6, 0, 1, 66, 1, 5, 65, 21, 30, + 10, 6, 18, 9, 23, 23, 23, 5, 25, 25, + 82, 4, 25, 5, 30, 87, 29, 27, 46, 34, + 43, 40, 58, 32, 62, 45, 49, 99, 35, 46, + 51, 41, 48, 107, 122, 24, 57, 53, 50, 127, + 15, 56, 38, 5, 49, 61, 35, 50, 116, 60, + 196, 216, 220, 204, 207, 203, 128, 141, 205, 209, + 128, 194, 212, 194, 197, 209, 223, 155, 214, 220, + 201, 159, 156, 202, 219, 199, 216, 222, 195, 195, + 148, 212, 254, 255, 233, 234, 230, 230, 226, 234, + 162, 247, 239, 161, 239, 233, 224, 236, 249, 250, + 236, 246, 236, 214, 242, 254, 253, 225, 226, 244, + 245, 227, 180, 250, 140, 141, 155, 140, 154, 207, + 184, 132, 129, 136, 147, 193, 219, 199, 196, 190, + 167, 219, 183, 217, 211, 223, 220, 181, 210, 222, + 208, 209, 186, 215, 217, 213, 234, 136, 232, 228, + 238, 139, 163, 186, 172, 150, 176, 225, 186, 231, + 136, 164, 169, 175, 248, 228, 254, 255, 160, 253, + 132, 188, 188, 164, 187, 178, 244, 232, 10, 111, + 73, 80, 108, 78, 94, 108, 81, 72, 115, 72, + 92, 66, 102, 76, 94, 104, 81, 67, 91, 115, + 93, 78, 70, 96, 89, 75, 83, 120, 68, 80, + 100, 67, 97, 110, 102, 67, 99, 122, 82, 113, + 101, 119, 111, 104, 113, 118, 89, 119, 119, 106, + 123, 75, 110, 124, 118, 118, 99, 64, 99, 120, + 96, 112, 43, 24, 27, 12, 26, 57, 3, 1, + 23, 14, 5, 32, 21, 12, 68, 39, 19, 31, + 88, 85, 94, 44, 21, 7, 23, 73, 80, 93, + 86, 62, 16, 79, 106, 103, 104, 10, 34, 32, + 63, 40, 38, 121, 96, 109, 102, 5, 45, 33, + 96, 123, 116, 121, 31, 44, 55, 103, 114, 127, + 112, 19, 63, 51, 7, 60, 208, 206, 146, 137, + 130, 143, 237, 222, 201, 240, 201, 219, 195, 157, + 132, 225, 219, 207, 217, 153, 205, 218, 206, 212, + 215, 192, 144, 146, 205, 135, 201, 246, 176, 215, + 207, 224, 250, 227, 237, 239, 175, 209, 245, 239, + 232, 226, 246, 217, 248, 238, 241, 245, 250, 236, + 192, 175, 241, 203, 165, 211, 216, 219, 196, 201, + 218, 183, 139, 133, 135, 138, 130, 153, 190, 151, + 133, 147, 139, 142, 138, 132, 150, 167, 156, 156, + 136, 154, 144, 146, 130, 158, 149, 159, 130, 171, + 182, 128, 185, 162, 166, 172, 189, 188, 128, 172, + 187, 166, 178, 157, 146, 181, 165, 161, 179, 181, + 191, 137, 178, 190, 168, 187, 189, 161, 189, 255, + 148, 162, 167, 188, 68, 78, 91, 90, 98, 78, + 85, 72, 80, 127, 109, 78, 66, 82, 72, 64, + 73, 103, 113, 87, 90, 86, 95, 92, 70, 92, + 66, 66, 106, 126, 90, 81, 99, 104, 105, 125, + 97, 125, 34, 110, 113, 79, 105, 111, 99, 88, + 35, 126, 42, 102, 63, 57, 122, 126, 104, 124, + 50, 96, 117, 99, 127, 114, 103, 53, 26, 25, + 7, 25, 11, 29, 24, 4, 7, 16, 44, 4, + 16, 2, 8, 69, 30, 26, 12, 24, 94, 12, + 25, 15, 27, 22, 3, 81, 85, 12, 68, 8, + 6, 46, 62, 44, 34, 16, 3, 35, 98, 55, + 41, 34, 45, 8, 42, 101, 56, 58, 42, 121, + 61, 51, 51, 46, 55, 6, 32, 53, 55, 35, + 49, 1, 211, 219, 205, 197, 199, 193, 201, 254, + 199, 209, 201, 196, 213, 203, 205, 203, 223, 247, + 221, 207, 219, 211, 245, 211, 214, 218, 211, 208, + 194, 216, 198, 149, 235, 231, 250, 236, 239, 235, + 245, 173, 227, 231, 228, 228, 226, 235, 237, 235, + 255, 210, 246, 253, 251, 231, 244, 244, 225, 231, + 255, 227, 255, 244, 245, 249, 174, 138, 156, 136, + 212, 207, 163, 131, 171, 141, 137, 149, 220, 199, + 171, 139, 175, 139, 156, 152, 138, 154, 198, 221, + 189, 157, 179, 157, 147, 150, 134, 207, 234, 132, + 166, 157, 188, 182, 139, 168, 182, 142, 169, 175, + 139, 166, 188, 166, 175, 168, 172, 182, 179, 151, + 181, 174, 166, 188, 162, 184, 181, 182, 184, 145, + 75, 95, 73, 106, 91, 92, 88, 66, 79, 3, + 72, 72, 85, 83, 75, 87, 83, 88, 89, 85, + 30, 91, 93, 73, 83, 19, 81, 93, 68, 82, + 85, 81, 115, 43, 105, 109, 106, 106, 104, 89, + 107, 110, 101, 33, 117, 111, 109, 99, 110, 72, + 112, 118, 105, 63, 112, 116, 124, 118, 48, 124, + 119, 101, 127, 112, 24, 39, 1, 7, 11, 60, + 9, 31, 11, 6, 19, 40, 2, 8, 2, 3, + 9, 30, 12, 16, 16, 12, 8, 28, 28, 16, + 21, 63, 23, 26, 17, 60, 36, 56, 60, 40, + 32, 44, 41, 109, 44, 34, 45, 36, 5, 125, + 24, 2, 51, 47, 52, 56, 60, 114, 14, 40, + 60, 61, 53, 35, 10, 53, 33, 60, 198, 207, + 219, 245, 156, 204, 244, 152, 224, 237, 236, 241, + 250, 151, 248, 198, 214, 210, 221, 215, 202, 227, + 200, 216, 192, 222, 217, 223, 215, 219, 232, 209, + 239, 253, 237, 229, 225, 255, 225, 232, 236, 247, + 220, 195, 243, 244, 237, 235, 255, 232, 235, 213, + 255, 230, 249, 239, 206, 199, 226, 240, 242, 254, + 250, 242, 186, 135, 137, 157, 136, 128, 158, 128, + 204, 161, 149, 146, 143, 137, 129, 150, 137, 183, + 153, 128, 155, 141, 160, 176, 157, 151, 133, 157, + 147, 132, 168, 166, 190, 185, 169, 189, 171, 168, + 165, 168, 177, 159, 147, 181, 180, 166, 176, 160, + 189, 162, 246, 186, 173, 152, 185, 179, 183, 161, + 177, 189, 149, 182, 186, 242, 94, 11, 75, 65, + 79, 65, 75, 72, 2, 80, 84, 83, 71, 83, + 65, 66, 67, 27, 75, 92, 74, 75, 85, 83, + 85, 64, 16, 70, 94, 94, 88, 80, 42, 120, + 124, 123, 111, 123, 105, 106, 123, 35, 115, 117, + 103, 115, 97, 37, 115, 104, 56, 110, 113, 109, + 119, 116, 124, 116, 124, 126, 113, 100, 71, 97, + 24, 10, 28, 12, 9, 22, 93, 67, 82, 34, + 14, 65, 3, 31, 7, 0, 10, 15, 17, 22, + 16, 95, 20, 28, 1, 83, 31, 18, 21, 2, + 6, 7, 47, 47, 104, 62, 38, 38, 32, 40, + 98, 48, 52, 51, 39, 51, 33, 34, 35, 123, + 59, 43, 59, 62, 40, 52, 60, 52, 126, 113, + 19, 47, 55, 48, 218, 223, 193, 198, 192, 149, + 140, 151, 130, 236, 206, 232, 200, 206, 208, 204, + 219, 215, 209, 195, 219, 242, 217, 201, 192, 218, + 211, 194, 229, 195, 198, 212, 254, 238, 239, 240, + 174, 248, 237, 254, 162, 224, 242, 228, 231, 243, + 225, 225, 180, 181, 182, 163, 190, 208, 242, 222, + 224, 246, 241, 229, 243, 243, 199, 225, 152, 138, + 156, 140, 137, 150, 204, 158, 150, 130, 146, 149, + 131, 131, 202, 203, 212, 186, 150, 217, 155, 135, + 159, 152, 130, 135, 153, 158, 152, 215, 156, 148, + 185, 235, 167, 170, 173, 186, 190, 191, 167, 167, + 224, 182, 174, 174, 168, 160, 250, 168, 172, 171, + 191, 171, 185, 186, 171, 243, 162, 164, 184, 185, + 189, 187, 77, 5, 8, 108, 86, 76, 73, 93, + 86, 74, 79, 79, 28, 7, 30, 5, 104, 78, + 86, 106, 74, 77, 93, 73, 87, 84, 73, 17, + 65, 86, 71, 21, 121, 127, 103, 121, 126, 106, + 104, 35, 44, 45, 65, 111, 38, 98, 124, 102, + 127, 107, 108, 112, 113, 113, 60, 117, 115, 96, + 48, 126, 117, 116, 97, 103, 24, 14, 12, 73, + 25, 7, 5, 1, 7, 67, 19, 21, 20, 6, + 16, 0, 29, 2, 88, 10, 10, 16, 12, 13, + 27, 29, 23, 95, 86, 50, 12, 22, 47, 59, + 60, 32, 33, 33, 118, 109, 120, 99, 19, 53, + 41, 55, 5, 43, 122, 62, 32, 58, 59, 47, + 40, 52, 61, 61, 112, 57, 55, 36, 116, 58, + 201, 200, 221, 219, 220, 202, 200, 141, 213, 203, + 201, 205, 195, 135, 215, 209, 200, 218, 204, 220, + 217, 198, 156, 217, 211, 199, 209, 145, 210, 210, + 216, 208, 254, 226, 230, 238, 160, 175, 201, 245, + 225, 230, 240, 245, 239, 232, 234, 191, 186, 161, + 184, 203, 251, 242, 243, 235, 247, 192, 228, 227, + 247, 227, 241, 242, 147, 203, 159, 136, 157, 207, + 158, 136, 143, 140, 150, 132, 130, 201, 202, 203, + 187, 149, 216, 156, 134, 156, 153, 141, 134, 154, + 159, 159, 214, 159, 149, 134, 234, 164, 171, 170, + 187, 189, 190, 168, 166, 227, 183, 169, 175, 171, + 161, 229, 169, 175, 170, 184, 170, 186, 187, 164, + 242, 161, 181, 188, 185, 161, 189, 187, 77, 5, + 8, 108, 86, 76, 73, 93, 86, 74, 79, 79, + 28, 7, 30, 5, 125, 94, 76, 116, 91, 75, + 78, 84, 81, 64, 98, 68, 88, 23, 112, 84, + 126, 110, 39, 93, 103, 98, 105, 90, 109, 113, + 107, 104, 104, 96, 36, 113, 115, 118, 125, 74, + 106, 126, 104, 120, 50, 92, 98, 117, 115, 101, + 46, 53, 74, 4, 26, 13, 11, 29, 76, 14, + 3, 13, 3, 4, 10, 71, 22, 0, 11, 14, + 29, 10, 10, 60, 29, 19, 17, 22, 28, 81, + 25, 5, 16, 16, 56, 107, 11, 38, 32, 33, + 41, 46, 54, 42, 47, 47, 124, 103, 5, 38, + 57, 52, 45, 55, 42, 101, 124, 12, 39, 50, + 62, 37, 63, 35, 45, 111, 138, 228, 218, 205, + 203, 221, 140, 228, 230, 153, 128, 242, 207, 195, + 193, 159, 154, 244, 202, 221, 219, 205, 156, 201, + 203, 195, 213, 139, 150, 227, 198, 220, 237, 236, + 237, 251, 174, 255, 254, 228, 225, 230, 186, 161, + 210, 245, 229, 236, 246, 242, 246, 254, 190, 240, + 250, 251, 225, 246, 228, 171, 182, 196, 224, 250, + 154, 203, 132, 134, 157, 156, 214, 205, 182, 130, + 139, 132, 198, 151, 150, 138, 156, 146, 140, 195, + 222, 187, 157, 137, 151, 220, 164, 152, 155, 146, + 206, 213, 153, 164, 189, 187, 173, 170, 246, 237, + 144, 166, 177, 180, 163, 180, 176, 140, 190, 225, + 248, 249, 157, 179, 179, 174, 183, 243, 161, 165, + 175, 237, 244, 133, 69, 88, 65, 93, 71, 64, + 66, 13, 65, 79, 79, 82, 67, 7, 86, 64, + 75, 78, 93, 74, 74, 111, 83, 78, 91, 71, + 89, 94, 88, 23, 125, 113, 48, 43, 68, 96, + 96, 100, 44, 66, 65, 76, 32, 115, 99, 118, + 113, 96, 105, 111, 84, 112, 112, 116, 60, 82, + 81, 92, 62, 49, 68, 114, 101, 96, 15, 24, + 28, 32, 10, 85, 76, 34, 16, 7, 5, 19, + 52, 2, 21, 16, 31, 8, 12, 41, 31, 13, + 29, 16, 23, 7, 21, 3, 5, 38, 1, 20, + 36, 63, 33, 61, 55, 11, 41, 43, 43, 45, + 41, 53, 47, 40, 42, 22, 63, 47, 44, 48, + 48, 56, 18, 60, 63, 54, 3, 61, 63, 39, + 36, 52, 205, 206, 251, 221, 193, 223, 224, 194, + 209, 208, 233, 213, 195, 202, 215, 241, 219, 208, + 221, 233, 204, 208, 218, 212, 198, 250, 196, 212, + 219, 196, 245, 209, 238, 226, 252, 224, 225, 225, + 237, 225, 210, 226, 242, 224, 235, 226, 240, 224, + 232, 232, 215, 235, 250, 250, 238, 238, 178, 244, + 226, 254, 227, 231, 180, 229, 134, 138, 139, 128, + 128, 136, 204, 159, 135, 146, 149, 132, 149, 147, + 171, 151, 158, 158, 138, 138, 222, 152, 142, 146, + 135, 131, 222, 209, 164, 146, 133, 128, 175, 184, + 188, 128, 170, 245, 236, 153, 167, 187, 180, 146, + 163, 179, 176, 172, 180, 188, 145, 173, 187, 178, + 157, 190, 177, 188, 165, 191, 162, 132, 177, 161, + 94, 66, 70, 78, 103, 91, 73, 64, 96, 76, + 79, 77, 67, 70, 74, 118, 95, 79, 76, 80, + 80, 88, 117, 73, 87, 94, 121, 95, 66, 82, + 83, 80, 120, 88, 109, 125, 122, 102, 98, 106, + 75, 119, 101, 108, 68, 104, 107, 105, 127, 122, + 118, 74, 105, 118, 104, 126, 122, 118, 98, 66, + 115, 99, 96, 124, 4, 12, 33, 29, 11, 2, + 56, 4, 15, 6, 58, 14, 8, 2, 41, 4, + 20, 26, 31, 28, 12, 44, 25, 9, 6, 26, + 30, 22, 63, 3, 17, 24, 30, 34, 37, 44, + 8, 61, 45, 32, 39, 0, 47, 47, 32, 46, + 35, 22, 63, 47, 44, 48, 48, 56, 21, 41, + 55, 62, 20, 48, 34, 50, 0, 60, 199, 206, + 251, 204, 218, 219, 197, 195, 197, 234, 212, 196, + 203, 247, 197, 214, 201, 204, 215, 203, 218, 236, + 217, 201, 198, 218, 222, 214, 255, 195, 209, 216, + 217, 238, 228, 236, 237, 251, 227, 255, 209, 230, + 244, 245, 239, 233, 227, 204, 238, 254, 245, 205, + 247, 242, 249, 199, 253, 253, 245, 194, 243, 227, + 224, 252, 132, 140, 161, 157, 139, 130, 184, 136, + 154, 151, 161, 147, 131, 134, 183, 128, 142, 143, + 145, 151, 153, 182, 136, 152, 159, 160, 137, 156, + 148, 152, 152, 166, 175, 191, 188, 160, 160, 168, + 133, 185, 167, 174, 144, 164, 180, 174, 171, 161, + 137, 190, 172, 173, 183, 177, 187, 148, 166, 182, + 189, 130, 162, 165, 189, 187, 77, 120, 77, 93, + 90, 70, 66, 74, 107, 87, 69, 76, 103, 68, + 80, 76, 85, 85, 107, 92, 74, 75, 85, 83, + 85, 90, 68, 84, 91, 103, 91, 92, 100, 127, + 123, 90, 107, 123, 120, 100, 108, 100, 73, 117, + 99, 106, 64, 106, 111, 121, 116, 124, 77, 122, + 104, 105, 123, 125, 119, 88, 98, 114, 121, 70, + 6, 2, 12, 12, 28, 60, 9, 25, 22, 10, + 14, 6, 47, 19, 1, 8, 41, 30, 20, 28, + 29, 11, 19, 15, 62, 28, 19, 16, 26, 30, + 14, 16, 46, 24, 45, 61, 58, 38, 34, 42, + 11, 55, 37, 44, 0, 46, 40, 32, 9, 62, + 44, 45, 55, 49, 59, 20, 38, 54, 61, 23, + 57, 57, 32, 6, 207, 223, 220, 192, 192, 200, + 229, 217, 199, 206, 236, 206, 200, 192, 247, 192, + 206, 207, 209, 215, 217, 246, 200, 216, 223, 244, + 194, 222, 195, 199, 231, 208, 254, 255, 225, 231, + 233, 198, 248, 232, 239, 192, 239, 237, 233, 245, + 215, 224, 238, 239, 241, 247, 249, 214, 232, 248, + 255, 192, 255, 228, 248, 243, 199, 240, 158, 159, + 129, 135, 137, 166, 152, 136, 143, 162, 140, 132, + 148, 147, 183, 128, 142, 143, 145, 151, 153, 182, + 136, 152, 159, 188, 177, 132, 130, 159, 167, 144, + 190, 191, 161, 167, 169, 134, 184, 168, 175, 145, + 161, 165, 175, 168, 136, 170, 185, 186, 180, 176, + 164, 186, 184, 142, 183, 167, 164, 184, 184, 176, + 157, 161, 79, 70, 108, 70, 91, 77, 64, 72, + 117, 74, 84, 73, 106, 78, 74, 78, 105, 94, + 76, 77, 87, 81, 91, 116, 70, 86, 93, 99, + 69, 68, 103, 80, 126, 127, 97, 103, 105, 70, + 120, 104, 111, 66, 108, 104, 97, 105, 105, 96, + 116, 111, 75, 124, 106, 107, 117, 115, 117, 90, + 100, 116, 123, 71, 117, 124, 24, 40, 7, 5, + 1, 29, 63, 8, 22, 23, 9, 15, 1, 46, + 16, 0, 23, 56, 23, 23, 26, 22, 8, 20, + 29, 29, 35, 20, 2, 3, 29, 27, 45, 2, + 60, 44, 35, 3, 37, 35, 39, 12, 48, 53, + 47, 40, 42, 54, 9, 62, 44, 45, 55, 49, + 59, 20, 38, 54, 61, 19, 63, 48, 0, 48, + 210, 223, 233, 219, 203, 206, 255, 200, 214, 215, + 201, 207, 193, 238, 208, 192, 215, 253, 209, 219, + 209, 209, 221, 222, 209, 218, 252, 212, 192, 210, + 216, 250, 250, 255, 225, 230, 224, 252, 223, 232, + 246, 247, 233, 239, 225, 206, 240, 224, 247, 214, + 241, 247, 241, 235, 253, 232, 224, 252, 214, 248, + 244, 248, 250, 244, 137, 136, 129, 165, 139, 153, + 137, 129, 173, 147, 148, 136, 137, 137, 151, 182, + 159, 143, 140, 144, 144, 152, 181, 137, 151, 158, + 162, 144, 152, 144, 145, 166, 175, 167, 173, 170, + 186, 160, 190, 158, 167, 183, 180, 168, 168, 160, + 141, 177, 191, 182, 154, 182, 177, 179, 185, 188, + 188, 159, 191, 178, 183, 187, 189, 175, 79, 79, + 123, 76, 90, 91, 69, 67, 69, 106, 84, 68, + 75, 100, 72, 80, 73, 79, 93, 75, 125, 80, + 80, 82, 64, 90, 94, 86, 122, 82, 66, 80, + 102, 88, 109, 125, 122, 102, 98, 106, 75, 119, + 101, 108, 73, 117, 96, 96, 104, 73, 125, 104, + 107, 122, 111, 105, 66, 114, 98, 112, 123, 114, + 96, 112, 24, 24, 59, 12, 26, 27, 5, 3, + 5, 42, 20, 4, 11, 46, 7, 10, 20, 30, + 28, 56, 29, 11, 21, 18, 28, 83, 38, 16, + 26, 2, 17, 79, 106, 34, 59, 29, 43, 34, + 60, 34, 48, 34, 50, 56, 4, 38, 54, 22, + 50, 52, 47, 28, 38, 43, 57, 51, 33, 58, + 63, 63, 5, 63, 59, 34, 239, 211, 220, 204, + 192, 220, 197, 194, 204, 239, 201, 207, 195, 244, + 204, 202, 205, 249, 217, 202, 219, 243, 217, 203, + 215, 223, 245, 201, 194, 210, 218, 198, 227, 228, + 230, 197, 235, 249, 233, 225, 199, 251, 244, 228, + 232, 244, 237, 234, 244, 217, 249, 250, 245, 220, + 243, 241, 253, 225, 213, 233, 226, 242, 250, 230, + 131, 132, 134, 171, 129, 157, 136, 136, 144, 160, + 143, 141, 137, 149, 161, 157, 142, 158, 150, 138, + 151, 144, 146, 177, 147, 145, 149, 157, 180, 150, + 135, 144, 134, 174, 190, 172, 162, 155, 169, 181, + 182, 143, 175, 162, 167, 171, 151, 177, 181, 169, + 185, 190, 187, 172, 137, 174, 183, 161, 132, 163, + 183, 179, 177, 166, 105, 74, 70, 14, 90, 15, + 74, 68, 76, 71, 0, 64, 72, 94, 4, 86, + 78, 84, 74, 88, 89, 90, 127, 92, 92, 20, + 68, 17, 85, 69, 81, 84, 126, 110, 40, 122, + 122, 96, 126, 108, 101, 102, 32, 110, 96, 39, + 112, 124, 106, 126, 34, 57, 81, 109, 120, 120, + 96, 96, 88, 120, 101, 99, 123, 103, 19, 40, + 29, 26, 26, 0, 1, 77, 17, 23, 18, 8, + 8, 0, 39, 10, 20, 31, 17, 13, 23, 16, + 18, 50, 2, 22, 2, 16, 24, 19, 55, 0, + 57, 63, 39, 36, 110, 43, 45, 57, 39, 21, + 33, 45, 51, 34, 16, 60, 42, 62, 27, 44, + 45, 43, 51, 48, 114, 32, 41, 60, 52, 56, + 56, 22, 223, 216, 220, 198, 195, 143, 205, 206, + 193, 204, 213, 207, 210, 228, 209, 214, 206, 212, + 213, 153, 205, 218, 208, 216, 209, 199, 223, 195, + 229, 210, 216, 208, 233, 255, 237, 237, 199, 251, + 233, 224, 205, 241, 228, 228, 244, 167, 244, 233, + 251, 248, 241, 247, 249, 191, 239, 233, 224, 242, + 228, 244, 241, 238, 180, 226, 152, 132, 134, 142, + 206, 140, 153, 159, 144, 134, 142, 149, 198, 148, + 144, 132, 142, 158, 171, 141, 140, 158, 136, 152, + 149, 138, 208, 151, 159, 153, 157, 134, 162, 174, + 172, 242, 231, 239, 236, 172, 182, 227, 166, 174, + 180, 231, 141, 139, 137, 143, 138, 140, 147, 154, + 146, 137, 129, 140, 131, 148, 154, 146, 151, 129, + 99, 100, 102, 118, 103, 107, 120, 68, 79, 70, + 79, 84, 82, 7, 75, 67, 26, 76, 89, 80, + 74, 86, 82, 90, 18, 82, 83, 82, 83, 68, + 71, 21, 126, 100, 99, 108, 96, 67, 99, 110, + 99, 111, 83, 117, 105, 117, 101, 98, 127, 104, + 68, 79, 113, 115, 105, 112, 119, 82, 126, 112, + 122, 110, 103, 124, 25, 59, 26, 6, 10, 26, + 15, 25, 43, 39, 49, 20, 9, 19, 13, 11, + 29, 56, 13, 11, 12, 26, 18, 30, 11, 58, + 52, 32, 3, 24, 0, 16, 14, 46, 36, 40, + 55, 30, 57, 34, 54, 42, 46, 38, 18, 62, + 52, 32, 22, 52, 44, 10, 55, 37, 57, 19, + 61, 39, 57, 62, 56, 54, 56, 3, 203, 199, + 221, 204, 253, 219, 201, 221, 234, 202, 211, 213, + 201, 213, 221, 241, 195, 203, 221, 239, 209, 211, + 201, 208, 215, 231, 201, 193, 211, 243, 209, 217, + 254, 234, 203, 232, 226, 236, 249, 225, 227, 247, + 233, 238, 232, 211, 253, 245, 255, 214, 241, 247, + 200, 240, 240, 232, 255, 246, 209, 255, 247, 251, + 237, 230, 131, 152, 188, 128, 141, 132, 191, 132, + 152, 134, 161, 141, 138, 136, 147, 166, 155, 151, + 155, 140, 146, 158, 136, 152, 160, 150, 145, 157, + 130, 158, 153, 144, 158, 162, 171, 162, 189, 142, + 160, 161, 173, 180, 131, 160, 170, 164, 177, 169, + 187, 175, 189, 139, 187, 190, 176, 169, 187, 190, + 181, 133, 164, 182, 176, 176, 89, 106, 68, 69, + 65, 88, 111, 76, 78, 64, 85, 77, 71, 83, + 65, 119, 95, 90, 84, 77, 87, 82, 89, 107, + 93, 95, 69, 92, 83, 118, 88, 89, 101, 124, + 75, 104, 98, 108, 121, 97, 99, 119, 101, 83, + 99, 102, 104, 113, 115, 118, 125, 90, 118, 126, + 114, 122, 119, 82, 124, 125, 121, 96, 85, 119, + 8, 25, 13, 31, 7, 14, 24, 8, 50, 17, + 9, 2, 3, 37, 29, 49, 19, 24, 19, 42, + 23, 5, 25, 48, 19, 7, 5, 3, 31, 3, + 13, 49, 43, 63, 45, 15, 59, 59, 57, 63, + 39, 0, 47, 47, 50, 53, 37, 38, 46, 15, + 33, 41, 59, 22, 50, 46, 38, 33, 37, 60, + 51, 57, 32, 20, 206, 207, 193, 221, 199, 192, + 194, 204, 206, 234, 206, 199, 201, 232, 194, 195, + 151, 254, 192, 218, 214, 222, 210, 218, 215, 229, + 213, 223, 210, 216, 198, 149, 226, 234, 251, 169, + 224, 224, 248, 173, 241, 246, 240, 241, 233, 245, + 240, 220, 245, 238, 234, 185, 242, 246, 255, 248, + 252, 224, 245, 177, 242, 248, 241, 230, 202, 133, + 135, 157, 206, 142, 128, 129, 141, 148, 192, 149, + 142, 142, 151, 197, 153, 148, 150, 151, 155, 156, + 136, 148, 157, 157, 165, 130, 147, 133, 176, 144, + 167, 164, 154, 172, 175, 163, 128, 162, 161, 162, + 172, 146, 178, 168, 182, 164, 189, 190, 171, 133, + 150, 182, 175, 169, 189, 161, 169, 129, 185, 164, + 157, 177, 16, 11, 4, 9, 105, 93, 67, 88, + 82, 106, 68, 27, 6, 11, 4, 102, 85, 86, + 85, 92, 80, 75, 6, 29, 98, 65, 16, 12, + 22, 99, 70, 27, 122, 121, 40, 52, 46, 91, + 126, 35, 109, 101, 102, 114, 99, 115, 36, 56, + 58, 88, 109, 106, 106, 112, 113, 94, 65, 71, + 92, 92, 66, 84, 46, 73, 45, 2, 28, 5, + 15, 13, 65, 63, 23, 13, 14, 4, 20, 59, + 6, 16, 19, 23, 28, 10, 34, 77, 31, 37, + 71, 49, 62, 61, 38, 43, 68, 41, 41, 39, + 33, 44, 32, 59, 16, 57, 39, 49, 45, 40, + 40, 38, 40, 25, 62, 62, 46, 60, 50, 48, + 44, 48, 55, 61, 36, 13, 20, 34, 39, 60, + 196, 206, 219, 218, 226, 206, 213, 200, 208, 255, + 244, 211, 199, 195, 205, 203, 221, 235, 212, 216, + 202, 217, 211, 207, 223, 157, 242, 196, 197, 222, + 218, 208, 249, 248, 196, 232, 247, 234, 254, 209, + 192, 246, 243, 232, 232, 226, 247, 246, 213, 249, + 242, 252, 253, 235, 239, 193, 221, 225, 244, 244, + 228, 195, 237, 229, 143, 152, 180, 165, 135, 130, + 133, 153, 173, 145, 132, 132, 148, 179, 157, 149, + 159, 213, 155, 138, 222, 223, 177, 146, 150, 154, + 150, 136, 214, 152, 134, 145, 175, 185, 232, 234, + 157, 187, 163, 189, 226, 175, 175, 178, 181, 231, + 180, 183, 179, 184, 189, 249, 173, 183, 179, 168, + 190, 183, 240, 179, 179, 247, 184, 176, 89, 88, + 8, 93, 70, 78, 66, 13, 78, 74, 77, 72, + 82, 7, 84, 87, 83, 88, 93, 109, 95, 84, + 89, 29, 66, 65, 95, 87, 95, 67, 20, 69, + 120, 98, 107, 108, 46, 124, 100, 98, 119, 111, + 100, 33, 100, 98, 36, 104, 117, 105, 125, 57, + 106, 119, 125, 115, 50, 127, 121, 124, 127, 99, + 52, 101, 24, 2, 11, 12, 61, 27, 3, 29, + 66, 15, 15, 18, 21, 71, 20, 23, 19, 24, + 29, 89, 13, 23, 19, 8, 30, 23, 80, 19, + 19, 87, 25, 26, 56, 46, 104, 61, 38, 46, + 34, 109, 46, 42, 45, 40, 50, 103, 52, 55, + 51, 56, 61, 13, 63, 52, 57, 125, 34, 33, + 63, 55, 63, 35, 116, 37, 216, 194, 203, 204, + 142, 220, 196, 194, 215, 207, 196, 129, 196, 194, + 132, 201, 223, 200, 203, 153, 202, 215, 221, 211, + 146, 223, 217, 220, 223, 195, 148, 197, 248, 226, + 235, 236, 195, 196, 216, 222, 246, 236, 240, 161, + 234, 232, 247, 246, 186, 235, 234, 240, 253, 250, + 188, 238, 250, 252, 229, 253, 242, 183, 246, 240, + 202, 135, 141, 154, 157, 207, 152, 133, 131, 141, + 192, 140, 135, 149, 143, 128, 142, 219, 153, 138, + 149, 223, 140, 143, 155, 144, 149, 178, 204, 171, + 179, 156, 190, 167, 169, 171, 227, 157, 185, 163, + 172, 166, 178, 157, 164, 178, 173, 169, 190, 168, + 132, 235, 189, 135, 233, 159, 156, 159, 128, 141, + 230, 139, 183, 185, 67, 78, 70, 93, 114, 91, + 73, 95, 79, 74, 78, 64, 74, 123, 64, 64, + 76, 94, 84, 86, 78, 82, 89, 83, 70, 111, + 114, 68, 69, 94, 90, 80, 121, 120, 68, 104, + 119, 106, 126, 81, 86, 113, 97, 101, 111, 105, + 99, 85, 118, 122, 108, 127, 113, 109, 113, 51, + 80, 102, 99, 120, 120, 114, 103, 102, 38, 10, + 17, 12, 28, 51, 46, 24, 17, 10, 14, 4, + 21, 20, 43, 7, 16, 30, 27, 13, 13, 35, + 51, 15, 22, 22, 2, 37, 15, 7, 17, 6, + 22, 6, 41, 59, 37, 42, 56, 2, 48, 39, + 37, 51, 18, 62, 52, 32, 116, 56, 43, 13, + 63, 52, 57, 125, 34, 33, 63, 55, 63, 35, + 116, 37, 216, 194, 203, 204, 142, 220, 196, 194, + 215, 207, 196, 129, 196, 194, 132, 200, 213, 201, + 221, 153, 202, 215, 221, 211, 146, 222, 209, 195, + 221, 210, 192, 149, 235, 248, 227, 169, 254, 253, + 229, 238, 231, 208, 244, 238, 246, 167, 232, 234, + 233, 232, 184, 233, 236, 246, 255, 248, 178, 224, + 248, 254, 227, 251, 240, 181, 136, 142, 200, 132, + 129, 157, 137, 205, 150, 139, 129, 143, 198, 138, + 133, 151, 145, 158, 140, 217, 156, 150, 152, 221, + 130, 129, 153, 146, 147, 163, 149, 158, 175, 235, + 184, 187, 161, 169, 165, 185, 226, 179, 178, 168, + 165, 162, 228, 182, 178, 180, 173, 181, 186, 255, + 190, 184, 242, 191, 181, 162, 165, 247, 160, 189, + 75, 69, 8, 68, 79, 93, 71, 72, 86, 3, + 66, 72, 66, 7, 84, 87, 83, 88, 93, 106, + 106, 111, 104, 79, 91, 84, 87, 84, 68, 23, + 68, 71, 99, 104, 109, 74, 52, 83, 75, 100, + 118, 111, 97, 99, 43, 85, 113, 107, 116, 126, + 106, 69, 124, 106, 117, 113, 118, 96, 76, 35, + 117, 79, 33, 87, 36, 39, 56, 53, 94, 51, + 15, 1, 11, 6, 14, 21, 58, 19, 1, 23, + 23, 18, 22, 24, 18, 35, 24, 24, 4, 22, + 28, 30, 6, 26, 17, 27, 62, 23, 10, 60, + 61, 38, 34, 40, 49, 48, 12, 32, 63, 34, + 54, 25, 14, 41, 57, 61, 55, 49, 59, 13, + 62, 50, 36, 55, 57, 37, 57, 123, 232, 222, + 219, 192, 192, 202, 223, 222, 238, 194, 217, 196, + 212, 251, 230, 208, 201, 210, 214, 220, 205, 204, + 243, 223, 216, 214, 211, 197, 197, 235, 251, 199, + 238, 238, 250, 221, 247, 255, 233, 254, 222, 208, + 244, 238, 246, 200, 246, 225, 255, 233, 204, 224, + 238, 250, 178, 254, 225, 192, 228, 254, 230, 183, + 248, 250, 153, 152, 200, 153, 156, 134, 143, 136, + 194, 144, 136, 142, 147, 139, 128, 197, 152, 158, + 216, 149, 155, 140, 143, 221, 134, 155, 145, 159, + 214, 131, 134, 156, 173, 172, 173, 187, 238, 191, + 190, 164, 161, 166, 148, 160, 173, 162, 228, 181, + 168, 180, 190, 176, 170, 255, 172, 175, 187, 176, + 181, 241, 165, 191, 187, 160, 70, 79, 8, 75, + 75, 15, 65, 66, 80, 70, 0, 85, 78, 70, + 74, 5, 78, 73, 81, 94, 89, 90, 78, 29, + 66, 65, 89, 82, 83, 100, 64, 90, 122, 43, + 100, 102, 125, 124, 44, 125, 112, 106, 99, 100, + 38, 116, 108, 106, 111, 119, 124, 57, 124, 122, + 60, 112, 125, 97, 117, 49, 98, 127, 117, 123, + 74, 31, 26, 0, 9, 8, 9, 31, 66, 19, + 18, 8, 5, 2, 48, 4, 17, 30, 88, 9, + 12, 16, 26, 20, 6, 83, 0, 3, 31, 20, + 17, 85, 57, 35, 39, 60, 34, 43, 108, 47, + 39, 99, 44, 36, 53, 52, 100, 49, 50, 58, + 54, 121, 42, 45, 53, 58, 53, 54, 34, 113, + 38, 37, 61, 54, 207, 255, 218, 200, 199, 195, + 197, 195, 197, 131, 243, 213, 201, 215, 240, 215, + 151, 232, 236, 203, 223, 214, 208, 212, 220, 212, + 144, 222, 208, 209, 199, 208, 254, 200, 178, 213, + 201, 230, 248, 225, 227, 225, 173, 211, 243, 233, + 234, 224, 232, 199, 250, 236, 247, 243, 248, 238, + 206, 161, 243, 201, 163, 213, 218, 217, 186, 183, + 216, 181, 141, 131, 133, 136, 140, 151, 188, 149, + 131, 149, 137, 140, 148, 154, 148, 165, 154, 154, + 138, 152, 158, 156, 128, 156, 147, 153, 128, 169, + 136, 190, 187, 160, 160, 170, 191, 190, 142, 162, + 185, 164, 180, 155, 144, 183, 187, 191, 177, 183, + 185, 143, 176, 188, 166, 181, 191, 163, 187, 249, + 150, 160, 89, 66, 70, 76, 93, 92, 96, 76, + 91, 70, 82, 125, 100, 82, 87, 76, 84, 94, + 75, 74, 113, 93, 86, 88, 81, 71, 67, 109, + 121, 69, 80, 80, 120, 95, 113, 121, 107, 124, + 80, 89, 112, 98, 105, 109, 111, 105, 99, 86, + 110, 116, 104, 86, 108, 123, 121, 111, 70, 106, + 96, 116, 56, 116, 103, 60, 67, 69, 72, 32, + 10, 79, 81, 77, 41, 2, 7, 8, 45, 0, + 72, 69, 54, 18, 22, 28, 94, 61, 14, 24, + 19, 24, 60, 24, 24, 18, 84, 23, 56, 46, + 41, 34, 110, 35, 37, 35, 39, 48, 108, 97, + 22, 40, 45, 43, 46, 40, 120, 127, 126, 25, + 53, 58, 39, 33, 53, 34, 21, 109, 8, 18, + 195, 223, 196, 200, 204, 130, 254, 216, 204, 205, + 197, 211, 250, 197, 209, 204, 214, 223, 203, 229, + 140, 220, 228, 136, 240, 253, 252, 225, 234, 135, + 232, 214, 230, 226, 237, 231, 250, 211, 248, 232, + 240, 238, 233, 239, 231, 235, 216, 225, 255, 237, + 253, 245, 241, 239, 241, 248, 252, 231, 204, 211, + 227, 228, 253, 251, 143, 152, 155, 165, 143, 150, + 137, 159, 190, 183, 146, 128, 130, 142, 138, 130, + 170, 151, 153, 141, 152, 144, 142, 144, 220, 177, + 133, 130, 159, 153, 145, 134, 185, 135, 169, 176, + 171, 189, 144, 133, 171, 176, 180, 174, 180, 190, + 152, 132, 189, 188, 170, 188, 185, 190, 168, 180, + 189, 189, 163, 141, 158, 190, 167, 161, 69, 89, + 81, 104, 73, 72, 94, 72, 69, 66, 84, 72, + 73, 73, 116, 74, 83, 85, 76, 74, 127, 81, + 88, 123, 91, 84, 69, 67, 83, 68, 26, 86, + 121, 73, 103, 113, 93, 102, 118, 104, 64, 108, + 120, 33, 117, 110, 126, 96, 74, 61, 94, 57, + 51, 63, 54, 85, 94, 80, 66, 116, 120, 124, + 123, 93, 3, 12, 0, 70, 34, 0, 27, 44, + 6, 21, 78, 65, 37, 11, 5, 22, 9, 18, + 27, 56, 26, 9, 82, 93, 58, 26, 23, 25, + 89, 59, 27, 2, 8, 57, 33, 42, 37, 111, + 63, 36, 56, 38, 1, 38, 33, 53, 33, 34, + 59, 47, 49, 54, 48, 127, 47, 41, 43, 63, + 53, 20, 46, 35, 49, 59, 217, 194, 199, 199, + 130, 143, 137, 228, 204, 213, 197, 211, 213, 206, + 203, 203, 150, 155, 157, 234, 214, 208, 203, 157, + 197, 218, 211, 218, 197, 245, 193, 220, 230, 239, + 168, 234, 251, 253, 254, 232, 236, 247, 160, 227, + 231, 245, 197, 198, 219, 211, 212, 191, 201, 221, + 249, 250, 251, 253, 170, 177, 182, 235, 180, 208, + 132, 143, 210, 201, 206, 128, 158, 137, 135, 145, + 192, 140, 137, 131, 141, 131, 131, 219, 138, 156, + 143, 138, 153, 142, 134, 211, 159, 131, 146, 146, + 134, 213, 186, 167, 169, 170, 167, 161, 171, 237, + 176, 166, 177, 180, 163, 180, 176, 135, 187, 168, + 189, 148, 191, 167, 136, 175, 179, 183, 185, 191, + 177, 134, 161, 180, 68, 95, 65, 93, 87, 126, + 89, 66, 86, 74, 78, 70, 107, 70, 92, 113, + 72, 90, 92, 80, 80, 88, 109, 72, 83, 93, + 68, 88, 66, 78, 117, 71, 104, 98, 124, 123, + 111, 104, 105, 94, 123, 110, 98, 110, 106, 116, + 71, 109, 127, 120, 115, 124, 122, 94, 112, 113, + 125, 100, 84, 120, 101, 118, 118, 121, 15, 40, + 7, 5, 1, 29, 42, 2, 16, 14, 1, 21, + 45, 14, 10, 1, 15, 15, 27, 63, 23, 29, + 19, 19, 19, 16, 19, 24, 58, 18, 2, 16, + 38, 56, 10, 40, 61, 42, 28, 40, 48, 42, + 47, 37, 102, 36, 43, 43, 46, 58, 49, 55, + 45, 127, 53, 51, 114, 22, 40, 50, 58, 34, + 48, 48, 206, 248, 220, 208, 194, 202, 223, 224, + 195, 219, 201, 204, 211, 202, 233, 204, 212, 210, + 213, 204, 211, 246, 210, 222, 192, 214, 221, 212, + 216, 195, 240, 220, 231, 238, 230, 250, 231, 224, + 226, 204, 238, 239, 239, 246, 194, 238, 247, 228, + 248, 247, 253, 218, 241, 243, 243, 239, 163, 210, + 252, 253, 249, 224, 208, 252, 153, 138, 138, 133, + 139, 172, 131, 129, 141, 145, 210, 177, 131, 149, + 141, 138, 158, 182, 141, 149, 138, 150, 140, 145, + 155, 150, 130, 209, 159, 132, 212, 153, 175, 184, + 187, 233, 186, 167, 173, 163, 226, 142, 181, 173, + 178, 174, 180, 169, 179, 190, 170, 148, 183, 177, + 181, 176, 167, 190, 240, 184, 165, 247, 185, 186, + 88, 78, 8, 93, 70, 78, 66, 13, 111, 86, + 76, 85, 79, 87, 72, 76, 95, 73, 117, 88, + 70, 86, 81, 72, 95, 113, 81, 66, 83, 103, + 81, 71, 99, 100, 108, 41, 109, 96, 98, 121, + 99, 106, 110, 114, 38, 110, 106, 37, 95, 99, + 123, 117, 107, 123, 121, 121, 66, 118, 98, 120, + 121, 115, 103, 69, 4, 7, 41, 5, 11, 29, + 24, 30, 33, 12, 14, 21, 7, 14, 10, 0, + 8, 43, 22, 21, 63, 19, 25, 15, 6, 39, + 17, 3, 17, 18, 0, 35, 43, 39, 61, 44, + 24, 46, 32, 56, 39, 48, 22, 32, 42, 50, + 33, 12, 46, 62, 53, 42, 8, 62, 48, 40, + 55, 26, 36, 52, 59, 30, 32, 48, 199, 216, + 251, 221, 203, 223, 223, 238, 205, 214, 206, 213, + 227, 201, 197, 199, 214, 222, 235, 214, 203, 209, + 216, 206, 230, 218, 221, 212, 255, 217, 224, 199, + 235, 239, 237, 202, 225, 225, 248, 236, 235, 237, + 229, 243, 210, 238, 233, 224, 211, 245, 204, 235, + 255, 251, 249, 201, 251, 254, 245, 216, 248, 196, + 241, 246, 133, 133, 140, 154, 190, 163, 168, 132, + 144, 134, 131, 149, 143, 136, 138, 177, 147, 150, + 157, 163, 145, 145, 153, 180, 156, 149, 159, 184, + 146, 181, 149, 134, 175, 158, 188, 170, 129, 169, + 170, 190, 167, 183, 132, 168, 181, 183, 168, 164, + 163, 149, 185, 180, 187, 140, 168, 188, 188, 183, + 177, 163, 178, 147, 189, 166, 90, 71, 73, 80, + 96, 78, 65, 72, 113, 66, 86, 68, 6, 85, + 65, 68, 86, 79, 81, 84, 91, 31, 72, 79, + 83, 87, 85, 17, 65, 94, 64, 93, 42, 120, + 124, 123, 111, 97, 107, 104, 34, 119, 105, 108, + 99, 61, 36, 81, 104, 122, 124, 124, 87, 123, + 60, 32, 50, 51, 68, 120, 123, 114, 52, 40, + 74, 18, 17, 16, 23, 66, 33, 32, 79, 7, + 4, 65, 46, 47, 94, 8, 23, 65, 11, 10, + 80, 25, 26, 27, 82, 31, 17, 2, 2, 35, + 6, 20, 46, 46, 12, 40, 58, 42, 108, 112, + 98, 16, 33, 55, 35, 103, 54, 32, 59, 55, + 44, 48, 51, 58, 124, 41, 32, 50, 52, 52, + 118, 32, 61, 33, 194, 139, 219, 221, 220, 206, + 194, 202, 199, 131, 212, 200, 203, 194, 158, 133, + 223, 195, 209, 202, 202, 218, 216, 233, 192, 210, + 212, 212, 197, 244, 219, 192, 228, 255, 168, 169, + 250, 253, 237, 233, 231, 240, 212, 238, 213, 230, + 242, 224, 186, 207, 240, 252, 236, 250, 188, 244, + 225, 179, 254, 254, 182, 248, 250, 240, 202, 136, + 128, 128, 130, 139, 204, 155, 135, 141, 132, 142, + 148, 170, 145, 137, 142, 146, 216, 143, 155, 145, + 152, 146, 128, 221, 208, 178, 158, 158, 152, 145, + 234, 189, 173, 167, 170, 160, 190, 237, 181, 170, + 180, 169, 230, 172, 161, 188, 250, 230, 248, 249, + 172, 186, 168, 168, 160, 189, 240, 181, 191, 164, + 183, 186, 68, 69, 77, 74, 90, 74, 72, 13, + 82, 74, 78, 70, 6, 85, 65, 86, 79, 87, + 76, 109, 76, 94, 88, 84, 92, 84, 16, 71, + 83, 89, 80, 90, 120, 43, 105, 101, 124, 106, + 109, 105, 123, 35, 114, 100, 97, 110, 119, 113, + 127, 105, 125, 125, 48, 63, 83, 115, 126, 106, + 48, 126, 120, 114, 52, 97, 24, 10, 12, 0, + 0, 8, 76, 27, 7, 13, 4, 14, 20, 71, + 7, 4, 20, 91, 26, 28, 94, 13, 25, 26, + 27, 0, 4, 20, 4, 18, 16, 91, 62, 57, + 41, 45, 39, 33, 43, 27, 39, 45, 36, 46, + 52, 49, 33, 43, 62, 52, 42, 26, 50, 48, + 47, 56, 54, 115, 32, 62, 37, 62, 32, 60, + 197, 197, 136, 202, 207, 193, 139, 217, 130, 193, + 197, 129, 197, 203, 203, 214, 223, 223, 152, 216, + 217, 222, 213, 211, 253, 213, 214, 145, 155, 151, + 241, 205, 233, 227, 233, 231, 233, 234, 220, 236, + 246, 235, 212, 238, 194, 230, 240, 228, 216, 250, + 235, 252, 206, 237, 243, 249, 231, 240, 228, 208, + 229, 228, 241, 225, 187, 158, 135, 157, 135, 129, + 139, 172, 145, 144, 133, 149, 171, 130, 151, 150, + 155, 156, 157, 170, 135, 146, 158, 146, 158, 157, + 149, 134, 184, 150, 153, 144, 234, 162, 187, 233, + 160, 186, 160, 161, 226, 172, 178, 225, 163, 170, + 180, 177, 163, 181, 189, 174, 151, 171, 185, 176, + 161, 136, 240, 250, 246, 152, 186, 185, 83, 11, + 101, 72, 92, 68, 73, 89, 2, 76, 82, 69, + 67, 85, 4, 81, 67, 75, 93, 25, 87, 76, + 28, 92, 94, 95, 95, 70, 83, 83, 68, 71, + 99, 104, 109, 68, 97, 107, 101, 107, 107, 96, + 97, 117, 105, 117, 80, 124, 106, 126, 126, 118, + 108, 124, 121, 72, 97, 118, 68, 120, 117, 124, + 103, 83, 5, 25, 32, 0, 29, 27, 3, 31, + 27, 36, 18, 14, 19, 23, 55, 0, 14, 15, + 17, 23, 25, 12, 47, 4, 28, 7, 24, 20, + 2, 30, 23, 60, 62, 46, 37, 5, 39, 34, + 37, 57, 11, 37, 20, 46, 51, 36, 44, 32, + 62, 23, 49, 52, 55, 43, 124, 52, 52, 115, + 36, 62, 35, 52, 60, 48, 206, 231, 229, 253, + 250, 236, 150, 241, 229, 202, 212, 205, 199, 197, + 137, 247, 207, 213, 214, 220, 204, 227, 222, 200, + 219, 223, 212, 194, 234, 133, 215, 237, 191, 201, + 198, 197, 222, 211, 188, 209, 225, 239, 233, 228, + 232, 243, 216, 241, 255, 233, 245, 240, 240, 254, + 240, 193, 246, 246, 230, 244, 250, 248, 228, 248, + 143, 133, 156, 181, 172, 154, 159, 132, 140, 134, + 147, 146, 170, 134, 157, 128, 136, 167, 172, 139, + 159, 155, 149, 147, 149, 163, 156, 144, 130, 145, + 155, 135, 167, 229, 138, 188, 189, 166, 162, 168, + 177, 176, 140, 160, 191, 162, 182, 153, 152, 174, + 171, 176, 176, 186, 175, 174, 157, 177, 186, 180, + 181, 163, 167, 137, 101, 89, 76, 76, 92, 123, + 85, 93, 71, 80, 124, 109, 79, 74, 77, 81, + 115, 93, 108, 86, 75, 92, 84, 88, 86, 124, + 66, 85, 83, 69, 96, 76, 122, 110, 38, 106, + 125, 120, 101, 121, 106, 35, 116, 115, 111, 96, + 99, 96, 104, 59, 104, 107, 119, 124, 121, 61, + 115, 103, 48, 92, 119, 101, 127, 112, 30, 34, + 14, 61, 1, 26, 15, 5, 7, 7, 45, 0, + 20, 12, 1, 17, 90, 18, 30, 89, 10, 16, + 9, 30, 26, 22, 20, 60, 61, 35, 32, 38, + 62, 36, 56, 105, 34, 38, 33, 36, 54, 16, + 20, 13, 5, 125, 24, 2, 51, 47, 52, 56, + 60, 114, 14, 40, 60, 61, 53, 35, 10, 53, + 33, 60, 198, 207, 219, 245, 156, 204, 244, 152, + 224, 237, 236, 241, 250, 151, 248, 198, 214, 210, + 221, 215, 202, 227, 200, 216, 192, 222, 217, 223, + 215, 219, 232, 209, 239, 253, 237, 229, 225, 255, + 225, 232, 236, 247, 220, 195, 243, 244, 237, 235, + 255, 232, 235, 213, 255, 230, 249, 239, 206, 199, + 226, 240, 242, 254, 250, 242, 186, 135, 137, 157, + 136, 128, 158, 128, 204, 161, 149, 146, 143, 137, + 129, 150, 137, 183, 153, 128, 155, 141, 160, 191, + 135, 128, 153, 159, 147, 132, 135, 186, 168, 161, + 173, 170, 186, 188, 144, 130, 176, 167, 165, 179, + 146, 190, 180, 160, 169, 135, 139, 173, 177, 175, + 144, 180, 191, 186, 164, 158, 164, 179, 177, 167, + 126, 82, 88, 76, 0, 76, 95, 94, 82, 76, + 84, 114, 95, 74, 70, 74, 86, 114, 92 + }; + + internal static string[] 5 = new string[2068]; + + private static string 6(int P_0, int P_1, int P_2) + { + string text = Encoding.UTF8.GetString(4, P_1, P_2); + 5[P_0] = text; + return text; + } + + public static string ?() + { + return 5[0] ?? 6(0, 0, 11); + } + + public static string ?() + { + return 5[1] ?? 6(1, 11, 2); + } + + public static string ?() + { + return 5[2] ?? 6(2, 13, 3); + } + + public static string ?() + { + return 5[3] ?? 6(3, 16, 27); + } + + public static string ?() + { + return 5[4] ?? 6(4, 43, 13); + } + + public static string ?() + { + return 5[5] ?? 6(5, 56, 8); + } + + public static string ?() + { + return 5[6] ?? 6(6, 64, 8); + } + + public static string ?() + { + return 5[7] ?? 6(7, 72, 17); + } + + public static string ?() + { + return 5[8] ?? 6(8, 89, 18); + } + + public static string ?() + { + return 5[9] ?? 6(9, 107, 19); + } + + public static string ?() + { + return 5[10] ?? 6(10, 126, 18); + } + + public static string ?() + { + return 5[11] ?? 6(11, 144, 16); + } + + public static string ?() + { + return 5[12] ?? 6(12, 160, 20); + } + + public static string ?() + { + return 5[13] ?? 6(13, 180, 28); + } + + public static string ?() + { + return 5[14] ?? 6(14, 208, 12); + } + + public static string ?() + { + return 5[15] ?? 6(15, 220, 39); + } + + public static string ?() + { + return 5[16] ?? 6(16, 259, 16); + } + + public static string ?() + { + return 5[17] ?? 6(17, 275, 0); + } + + public static string ?() + { + return 5[18] ?? 6(18, 275, 3); + } + + public static string ?() + { + return 5[19] ?? 6(19, 278, 8); + } + + public static string ?() + { + return 5[20] ?? 6(20, 286, 7); + } + + public static string ?() + { + return 5[21] ?? 6(21, 293, 6); + } + + public static string ?() + { + return 5[22] ?? 6(22, 299, 47); + } + + public static string ?() + { + return 5[23] ?? 6(23, 346, 9); + } + + public static string ?() + { + return 5[24] ?? 6(24, 355, 51); + } + + public static string ?() + { + return 5[25] ?? 6(25, 406, 7); + } + + public static string ?() + { + return 5[26] ?? 6(26, 413, 7); + } + + public static string ?() + { + return 5[27] ?? 6(27, 420, 1); + } + + public static string ?() + { + return 5[28] ?? 6(28, 421, 2); + } + + public static string ?() + { + return 5[29] ?? 6(29, 423, 1); + } + + public static string ?() + { + return 5[30] ?? 6(30, 424, 4); + } + + public static string ?() + { + return 5[31] ?? 6(31, 428, 44); + } + + public static string ?() + { + return 5[32] ?? 6(32, 472, 17); + } + + public static string ?() + { + return 5[33] ?? 6(33, 489, 16); + } + + public static string ?() + { + return 5[34] ?? 6(34, 505, 7); + } + + public static string ?() + { + return 5[35] ?? 6(35, 512, 42); + } + + public static string ?() + { + return 5[36] ?? 6(36, 554, 36); + } + + public static string ?() + { + return 5[37] ?? 6(37, 590, 33); + } + + public static string ?() + { + return 5[38] ?? 6(38, 623, 51); + } + + public static string ?() + { + return 5[39] ?? 6(39, 674, 9); + } + + public static string ?() + { + return 5[40] ?? 6(40, 683, 11); + } + + public static string ?() + { + return 5[41] ?? 6(41, 694, 42); + } + + public static string ?() + { + return 5[42] ?? 6(42, 736, 2); + } + + public static string ?() + { + return 5[43] ?? 6(43, 738, 26); + } + + public static string ?() + { + return 5[44] ?? 6(44, 764, 15); + } + + public static string ?() + { + return 5[45] ?? 6(45, 779, 36); + } + + public static string ?() + { + return 5[46] ?? 6(46, 815, 21); + } + + public static string ?() + { + return 5[47] ?? 6(47, 836, 16); + } + + public static string ?() + { + return 5[48] ?? 6(48, 852, 32); + } + + public static string ?() + { + return 5[49] ?? 6(49, 884, 14); + } + + public static string ?() + { + return 5[50] ?? 6(50, 898, 23); + } + + public static string ?() + { + return 5[51] ?? 6(51, 921, 21); + } + + public static string ?() + { + return 5[52] ?? 6(52, 942, 31); + } + + public static string ?() + { + return 5[53] ?? 6(53, 973, 23); + } + + public static string ?() + { + return 5[54] ?? 6(54, 996, 33); + } + + public static string ?() + { + return 5[55] ?? 6(55, 1029, 26); + } + + public static string ?() + { + return 5[56] ?? 6(56, 1055, 14); + } + + public static string ?() + { + return 5[57] ?? 6(57, 1069, 9); + } + + public static string ?() + { + return 5[58] ?? 6(58, 1078, 27); + } + + public static string ?() + { + return 5[59] ?? 6(59, 1105, 28); + } + + public static string ?() + { + return 5[60] ?? 6(60, 1133, 26); + } + + public static string ?() + { + return 5[61] ?? 6(61, 1159, 45); + } + + public static string ?() + { + return 5[62] ?? 6(62, 1204, 15); + } + + public static string ?() + { + return 5[63] ?? 6(63, 1219, 8); + } + + public static string ?() + { + return 5[64] ?? 6(64, 1227, 26); + } + + public static string ?() + { + return 5[65] ?? 6(65, 1253, 28); + } + + public static string ?() + { + return 5[66] ?? 6(66, 1281, 22); + } + + public static string ?() + { + return 5[67] ?? 6(67, 1303, 23); + } + + public static string ?() + { + return 5[68] ?? 6(68, 1326, 11); + } + + public static string ?() + { + return 5[69] ?? 6(69, 1337, 6); + } + + public static string ?() + { + return 5[70] ?? 6(70, 1343, 22); + } + + public static string ?() + { + return 5[71] ?? 6(71, 1365, 23); + } + + public static string ?() + { + return 5[72] ?? 6(72, 1388, 33); + } + + public static string ?() + { + return 5[73] ?? 6(73, 1421, 15); + } + + public static string ?() + { + return 5[74] ?? 6(74, 1436, 27); + } + + public static string ?() + { + return 5[75] ?? 6(75, 1463, 38); + } + + public static string ?() + { + return 5[76] ?? 6(76, 1501, 13); + } + + public static string ?() + { + return 5[77] ?? 6(77, 1514, 23); + } + + public static string ?() + { + return 5[78] ?? 6(78, 1537, 53); + } + + public static string ?() + { + return 5[79] ?? 6(79, 1590, 6); + } + + public static string ?() + { + return 5[80] ?? 6(80, 1596, 13); + } + + public static string ?() + { + return 5[81] ?? 6(81, 1609, 34); + } + + public static string ?() + { + return 5[82] ?? 6(82, 1643, 18); + } + + public static string ?() + { + return 5[83] ?? 6(83, 1661, 20); + } + + public static string ?() + { + return 5[84] ?? 6(84, 1681, 23); + } + + public static string ?() + { + return 5[85] ?? 6(85, 1704, 10); + } + + public static string ?() + { + return 5[86] ?? 6(86, 1714, 31); + } + + public static string ?() + { + return 5[87] ?? 6(87, 1745, 21); + } + + public static string ?() + { + return 5[88] ?? 6(88, 1766, 16); + } + + public static string ?() + { + return 5[89] ?? 6(89, 1782, 16); + } + + public static string ?() + { + return 5[90] ?? 6(90, 1798, 23); + } + + public static string ?() + { + return 5[91] ?? 6(91, 1821, 12); + } + + public static string ?() + { + return 5[92] ?? 6(92, 1833, 23); + } + + public static string ?() + { + return 5[93] ?? 6(93, 1856, 21); + } + + public static string ?() + { + return 5[94] ?? 6(94, 1877, 23); + } + + public static string ?() + { + return 5[95] ?? 6(95, 1900, 13); + } + + public static string ?() + { + return 5[96] ?? 6(96, 1913, 5); + } + + public static string ?() + { + return 5[97] ?? 6(97, 1918, 28); + } + + public static string ?() + { + return 5[98] ?? 6(98, 1946, 41); + } + + public static string ?() + { + return 5[99] ?? 6(99, 1987, 18); + } + + public static string ?() + { + return 5[100] ?? 6(100, 2005, 26); + } + + public static string ?() + { + return 5[101] ?? 6(101, 2031, 10); + } + + public static string ?() + { + return 5[102] ?? 6(102, 2041, 6); + } + + public static string ?() + { + return 5[103] ?? 6(103, 2047, 17); + } + + public static string ?() + { + return 5[104] ?? 6(104, 2064, 5); + } + + public static string ?() + { + return 5[105] ?? 6(105, 2069, 12); + } + + public static string ?() + { + return 5[106] ?? 6(106, 2081, 18); + } + + public static string ?() + { + return 5[107] ?? 6(107, 2099, 37); + } + + public static string ?() + { + return 5[108] ?? 6(108, 2136, 18); + } + + public static string ?() + { + return 5[109] ?? 6(109, 2154, 18); + } + + public static string ?() + { + return 5[110] ?? 6(110, 2172, 20); + } + + public static string ?() + { + return 5[111] ?? 6(111, 2192, 20); + } + + public static string ?() + { + return 5[112] ?? 6(112, 2212, 20); + } + + public static string ?() + { + return 5[113] ?? 6(113, 2232, 9); + } + + public static string ?() + { + return 5[114] ?? 6(114, 2241, 14); + } + + public static string ?() + { + return 5[115] ?? 6(115, 2255, 18); + } + + public static string ?() + { + return 5[116] ?? 6(116, 2273, 8); + } + + public static string ?() + { + return 5[117] ?? 6(117, 2281, 19); + } + + public static string ?() + { + return 5[118] ?? 6(118, 2300, 27); + } + + public static string ?() + { + return 5[119] ?? 6(119, 2327, 17); + } + + public static string ?() + { + return 5[120] ?? 6(120, 2344, 16); + } + + public static string ?() + { + return 5[121] ?? 6(121, 2360, 13); + } + + public static string ?() + { + return 5[122] ?? 6(122, 2373, 13); + } + + public static string ?() + { + return 5[123] ?? 6(123, 2386, 28); + } + + public static string ?() + { + return 5[124] ?? 6(124, 2414, 17); + } + + public static string ?() + { + return 5[125] ?? 6(125, 2431, 6); + } + + public static string ?() + { + return 5[126] ?? 6(126, 2437, 21); + } + + public static string ?() + { + return 5[127] ?? 6(127, 2458, 16); + } + + public static string ??() + { + return 5[128] ?? 6(128, 2474, 10); + } + + public static string ??() + { + return 5[129] ?? 6(129, 2484, 23); + } + + public static string ??() + { + return 5[130] ?? 6(130, 2507, 18); + } + + public static string ??() + { + return 5[131] ?? 6(131, 2525, 24); + } + + public static string ??() + { + return 5[132] ?? 6(132, 2549, 31); + } + + public static string ??() + { + return 5[133] ?? 6(133, 2580, 5); + } + + public static string ??() + { + return 5[134] ?? 6(134, 2585, 5); + } + + public static string ??() + { + return 5[135] ?? 6(135, 2590, 6); + } + + public static string ??() + { + return 5[136] ?? 6(136, 2596, 11); + } + + public static string ??() + { + return 5[137] ?? 6(137, 2607, 7); + } + + public static string ??() + { + return 5[138] ?? 6(138, 2614, 19); + } + + public static string ??() + { + return 5[139] ?? 6(139, 2633, 15); + } + + public static string ??() + { + return 5[140] ?? 6(140, 2648, 16); + } + + public static string ??() + { + return 5[141] ?? 6(141, 2664, 25); + } + + public static string ??() + { + return 5[142] ?? 6(142, 2689, 15); + } + + public static string ??() + { + return 5[143] ?? 6(143, 2704, 34); + } + + public static string ??() + { + return 5[144] ?? 6(144, 2738, 30); + } + + public static string ??() + { + return 5[145] ?? 6(145, 2768, 27); + } + + public static string ??() + { + return 5[146] ?? 6(146, 2795, 15); + } + + public static string ??() + { + return 5[147] ?? 6(147, 2810, 15); + } + + public static string ??() + { + return 5[148] ?? 6(148, 2825, 17); + } + + public static string ??() + { + return 5[149] ?? 6(149, 2842, 15); + } + + public static string ??() + { + return 5[150] ?? 6(150, 2857, 9); + } + + public static string ??() + { + return 5[151] ?? 6(151, 2866, 16); + } + + public static string ??() + { + return 5[152] ?? 6(152, 2882, 28); + } + + public static string ??() + { + return 5[153] ?? 6(153, 2910, 36); + } + + public static string ??() + { + return 5[154] ?? 6(154, 2946, 10); + } + + public static string ??() + { + return 5[155] ?? 6(155, 2956, 9); + } + + public static string ??() + { + return 5[156] ?? 6(156, 2965, 9); + } + + public static string ??() + { + return 5[157] ?? 6(157, 2974, 8); + } + + public static string ??() + { + return 5[158] ?? 6(158, 2982, 10); + } + + public static string ??() + { + return 5[159] ?? 6(159, 2992, 9); + } + + public static string ??() + { + return 5[160] ?? 6(160, 3001, 13); + } + + public static string ??() + { + return 5[161] ?? 6(161, 3014, 26); + } + + public static string ??() + { + return 5[162] ?? 6(162, 3040, 9); + } + + public static string ??() + { + return 5[163] ?? 6(163, 3049, 26); + } + + public static string ??() + { + return 5[164] ?? 6(164, 3075, 35); + } + + public static string ??() + { + return 5[165] ?? 6(165, 3110, 28); + } + + public static string ??() + { + return 5[166] ?? 6(166, 3138, 27); + } + + public static string ??() + { + return 5[167] ?? 6(167, 3165, 28); + } + + public static string ??() + { + return 5[168] ?? 6(168, 3193, 37); + } + + public static string ??() + { + return 5[169] ?? 6(169, 3230, 30); + } + + public static string ??() + { + return 5[170] ?? 6(170, 3260, 29); + } + + public static string ??() + { + return 5[171] ?? 6(171, 3289, 27); + } + + public static string ??() + { + return 5[172] ?? 6(172, 3316, 36); + } + + public static string ??() + { + return 5[173] ?? 6(173, 3352, 29); + } + + public static string ??() + { + return 5[174] ?? 6(174, 3381, 28); + } + + public static string ??() + { + return 5[175] ?? 6(175, 3409, 21); + } + + public static string ??() + { + return 5[176] ?? 6(176, 3430, 9); + } + + public static string ??() + { + return 5[177] ?? 6(177, 3439, 16); + } + + public static string ??() + { + return 5[178] ?? 6(178, 3455, 21); + } + + public static string ??() + { + return 5[179] ?? 6(179, 3476, 11); + } + + public static string ??() + { + return 5[180] ?? 6(180, 3487, 14); + } + + public static string ??() + { + return 5[181] ?? 6(181, 3501, 12); + } + + public static string ??() + { + return 5[182] ?? 6(182, 3513, 3); + } + + public static string ??() + { + return 5[183] ?? 6(183, 3516, 11); + } + + public static string ??() + { + return 5[184] ?? 6(184, 3527, 35); + } + + public static string ??() + { + return 5[185] ?? 6(185, 3562, 42); + } + + public static string ??() + { + return 5[186] ?? 6(186, 3604, 13); + } + + public static string ??() + { + return 5[187] ?? 6(187, 3617, 44); + } + + public static string ??() + { + return 5[188] ?? 6(188, 3661, 51); + } + + public static string ??() + { + return 5[189] ?? 6(189, 3712, 29); + } + + public static string ??() + { + return 5[190] ?? 6(190, 3741, 1); + } + + public static string ??() + { + return 5[191] ?? 6(191, 3742, 1); + } + + public static string ??() + { + return 5[192] ?? 6(192, 3743, 1); + } + + public static string ??() + { + return 5[193] ?? 6(193, 3744, 4); + } + + public static string ??() + { + return 5[194] ?? 6(194, 3748, 8); + } + + public static string ??() + { + return 5[195] ?? 6(195, 3756, 6); + } + + public static string ??() + { + return 5[196] ?? 6(196, 3762, 4); + } + + public static string ??() + { + return 5[197] ?? 6(197, 3766, 34); + } + + public static string ??() + { + return 5[198] ?? 6(198, 3800, 41); + } + + public static string ??() + { + return 5[199] ?? 6(199, 3841, 12); + } + + public static string ??() + { + return 5[200] ?? 6(200, 3853, 8); + } + + public static string ??() + { + return 5[201] ?? 6(201, 3861, 8); + } + + public static string ??() + { + return 5[202] ?? 6(202, 3869, 3); + } + + public static string ??() + { + return 5[203] ?? 6(203, 3872, 22); + } + + public static string ??() + { + return 5[204] ?? 6(204, 3894, 19); + } + + public static string ??() + { + return 5[205] ?? 6(205, 3913, 23); + } + + public static string ??() + { + return 5[206] ?? 6(206, 3936, 13); + } + + public static string ??() + { + return 5[207] ?? 6(207, 3949, 55); + } + + public static string ??() + { + return 5[208] ?? 6(208, 4004, 13); + } + + public static string ??() + { + return 5[209] ?? 6(209, 4017, 5); + } + + public static string ??() + { + return 5[210] ?? 6(210, 4022, 51); + } + + public static string ??() + { + return 5[211] ?? 6(211, 4073, 49); + } + + public static string ??() + { + return 5[212] ?? 6(212, 4122, 18); + } + + public static string ??() + { + return 5[213] ?? 6(213, 4140, 43); + } + + public static string ??() + { + return 5[214] ?? 6(214, 4183, 44); + } + + public static string ??() + { + return 5[215] ?? 6(215, 4227, 12); + } + + public static string ??() + { + return 5[216] ?? 6(216, 4239, 9); + } + + public static string ??() + { + return 5[217] ?? 6(217, 4248, 41); + } + + public static string ??() + { + return 5[218] ?? 6(218, 4289, 18); + } + + public static string ??() + { + return 5[219] ?? 6(219, 4307, 50); + } + + public static string ??() + { + return 5[220] ?? 6(220, 4357, 15); + } + + public static string ??() + { + return 5[221] ?? 6(221, 4372, 24); + } + + public static string ??() + { + return 5[222] ?? 6(222, 4396, 56); + } + + public static string ??() + { + return 5[223] ?? 6(223, 4452, 33); + } + + public static string ??() + { + return 5[224] ?? 6(224, 4485, 34); + } + + public static string ??() + { + return 5[225] ?? 6(225, 4519, 43); + } + + public static string ??() + { + return 5[226] ?? 6(226, 4562, 53); + } + + public static string ??() + { + return 5[227] ?? 6(227, 4615, 45); + } + + public static string ??() + { + return 5[228] ?? 6(228, 4660, 46); + } + + public static string ??() + { + return 5[229] ?? 6(229, 4706, 43); + } + + public static string ??() + { + return 5[230] ?? 6(230, 4749, 62); + } + + public static string ??() + { + return 5[231] ?? 6(231, 4811, 54); + } + + public static string ??() + { + return 5[232] ?? 6(232, 4865, 62); + } + + public static string ??() + { + return 5[233] ?? 6(233, 4927, 54); + } + + public static string ??() + { + return 5[234] ?? 6(234, 4981, 55); + } + + public static string ??() + { + return 5[235] ?? 6(235, 5036, 47); + } + + public static string ??() + { + return 5[236] ?? 6(236, 5083, 48); + } + + public static string ??() + { + return 5[237] ?? 6(237, 5131, 45); + } + + public static string ??() + { + return 5[238] ?? 6(238, 5176, 37); + } + + public static string ??() + { + return 5[239] ?? 6(239, 5213, 75); + } + + public static string ??() + { + return 5[240] ?? 6(240, 5288, 41); + } + + public static string ??() + { + return 5[241] ?? 6(241, 5329, 11); + } + + public static string ??() + { + return 5[242] ?? 6(242, 5340, 32); + } + + public static string ??() + { + return 5[243] ?? 6(243, 5372, 8); + } + + public static string ??() + { + return 5[244] ?? 6(244, 5380, 19); + } + + public static string ??() + { + return 5[245] ?? 6(245, 5399, 34); + } + + public static string ??() + { + return 5[246] ?? 6(246, 5433, 24); + } + + public static string ??() + { + return 5[247] ?? 6(247, 5457, 24); + } + + public static string ??() + { + return 5[248] ?? 6(248, 5481, 7); + } + + public static string ??() + { + return 5[249] ?? 6(249, 5488, 6); + } + + public static string ??() + { + return 5[250] ?? 6(250, 5494, 41); + } + + public static string ??() + { + return 5[251] ?? 6(251, 5535, 44); + } + + public static string ??() + { + return 5[252] ?? 6(252, 5579, 35); + } + + public static string ??() + { + return 5[253] ?? 6(253, 5614, 37); + } + + public static string ??() + { + return 5[254] ?? 6(254, 5651, 14); + } + + public static string ??() + { + return 5[255] ?? 6(255, 5665, 48); + } + + public static string ??() + { + return 5[256] ?? 6(256, 5713, 9); + } + + public static string ??() + { + return 5[257] ?? 6(257, 5722, 21); + } + + public static string ??() + { + return 5[258] ?? 6(258, 5743, 50); + } + + public static string ??() + { + return 5[259] ?? 6(259, 5793, 9); + } + + public static string ??() + { + return 5[260] ?? 6(260, 5802, 23); + } + + public static string ??() + { + return 5[261] ?? 6(261, 5825, 27); + } + + public static string ??() + { + return 5[262] ?? 6(262, 5852, 21); + } + + public static string ??() + { + return 5[263] ?? 6(263, 5873, 3); + } + + public static string ??() + { + return 5[264] ?? 6(264, 5876, 7); + } + + public static string ??() + { + return 5[265] ?? 6(265, 5883, 12); + } + + public static string ??() + { + return 5[266] ?? 6(266, 5895, 10); + } + + public static string ??() + { + return 5[267] ?? 6(267, 5905, 28); + } + + public static string ??() + { + return 5[268] ?? 6(268, 5933, 40); + } + + public static string ??() + { + return 5[269] ?? 6(269, 5973, 25); + } + + public static string ??() + { + return 5[270] ?? 6(270, 5998, 14); + } + + public static string ??() + { + return 5[271] ?? 6(271, 6012, 32); + } + + public static string ??() + { + return 5[272] ?? 6(272, 6044, 33); + } + + public static string ??() + { + return 5[273] ?? 6(273, 6077, 27); + } + + public static string ??() + { + return 5[274] ?? 6(274, 6104, 19); + } + + public static string ??() + { + return 5[275] ?? 6(275, 6123, 22); + } + + public static string ??() + { + return 5[276] ?? 6(276, 6145, 8); + } + + public static string ??() + { + return 5[277] ?? 6(277, 6153, 29); + } + + public static string ??() + { + return 5[278] ?? 6(278, 6182, 19); + } + + public static string ??() + { + return 5[279] ?? 6(279, 6201, 4); + } + + public static string ??() + { + return 5[280] ?? 6(280, 6205, 12); + } + + public static string ??() + { + return 5[281] ?? 6(281, 6217, 40); + } + + public static string ??() + { + return 5[282] ?? 6(282, 6257, 5); + } + + public static string ??() + { + return 5[283] ?? 6(283, 6262, 6); + } + + public static string ??() + { + return 5[284] ?? 6(284, 6268, 10); + } + + public static string ??() + { + return 5[285] ?? 6(285, 6278, 6); + } + + public static string ??() + { + return 5[286] ?? 6(286, 6284, 1); + } + + public static string ??() + { + return 5[287] ?? 6(287, 6285, 1); + } + + public static string ??() + { + return 5[288] ?? 6(288, 6286, 1); + } + + public static string ??() + { + return 5[289] ?? 6(289, 6287, 1); + } + + public static string ??() + { + return 5[290] ?? 6(290, 6288, 1); + } + + public static string ??() + { + return 5[291] ?? 6(291, 6289, 1); + } + + public static string ??() + { + return 5[292] ?? 6(292, 6290, 14); + } + + public static string ??() + { + return 5[293] ?? 6(293, 6304, 4); + } + + public static string ??() + { + return 5[294] ?? 6(294, 6308, 1); + } + + public static string ??() + { + return 5[295] ?? 6(295, 6309, 1); + } + + public static string ??() + { + return 5[296] ?? 6(296, 6310, 18); + } + + public static string ??() + { + return 5[297] ?? 6(297, 6328, 5); + } + + public static string ??() + { + return 5[298] ?? 6(298, 6333, 58); + } + + public static string ??() + { + return 5[299] ?? 6(299, 6391, 33); + } + + public static string ??() + { + return 5[300] ?? 6(300, 6424, 2); + } + + public static string ??() + { + return 5[301] ?? 6(301, 6426, 61); + } + + public static string ??() + { + return 5[302] ?? 6(302, 6487, 10); + } + + public static string ??() + { + return 5[303] ?? 6(303, 6497, 32); + } + + public static string ??() + { + return 5[304] ?? 6(304, 6529, 13); + } + + public static string ??() + { + return 5[305] ?? 6(305, 6542, 1); + } + + public static string ??() + { + return 5[306] ?? 6(306, 6543, 1); + } + + public static string ??() + { + return 5[307] ?? 6(307, 6544, 12); + } + + public static string ??() + { + return 5[308] ?? 6(308, 6556, 13); + } + + public static string ??() + { + return 5[309] ?? 6(309, 6569, 21); + } + + public static string ??() + { + return 5[310] ?? 6(310, 6590, 10); + } + + public static string ??() + { + return 5[311] ?? 6(311, 6600, 7); + } + + public static string ??() + { + return 5[312] ?? 6(312, 6607, 6); + } + + public static string ??() + { + return 5[313] ?? 6(313, 6613, 11); + } + + public static string ??() + { + return 5[314] ?? 6(314, 6624, 6); + } + + public static string ??() + { + return 5[315] ?? 6(315, 6630, 4); + } + + public static string ??() + { + return 5[316] ?? 6(316, 6634, 7); + } + + public static string ??() + { + return 5[317] ?? 6(317, 6641, 8); + } + + public static string ??() + { + return 5[318] ?? 6(318, 6649, 31); + } + + public static string ??() + { + return 5[319] ?? 6(319, 6680, 18); + } + + public static string ??() + { + return 5[320] ?? 6(320, 6698, 25); + } + + public static string ??() + { + return 5[321] ?? 6(321, 6723, 1); + } + + public static string ??() + { + return 5[322] ?? 6(322, 6724, 9); + } + + public static string ??() + { + return 5[323] ?? 6(323, 6733, 11); + } + + public static string ??() + { + return 5[324] ?? 6(324, 6744, 8); + } + + public static string ??() + { + return 5[325] ?? 6(325, 6752, 13); + } + + public static string ??() + { + return 5[326] ?? 6(326, 6765, 6); + } + + public static string ??() + { + return 5[327] ?? 6(327, 6771, 3); + } + + public static string ??() + { + return 5[328] ?? 6(328, 6774, 5); + } + + public static string ??() + { + return 5[329] ?? 6(329, 6779, 23); + } + + public static string ??() + { + return 5[330] ?? 6(330, 6802, 1); + } + + public static string ??() + { + return 5[331] ?? 6(331, 6803, 1); + } + + public static string ??() + { + return 5[332] ?? 6(332, 6804, 2); + } + + public static string ??() + { + return 5[333] ?? 6(333, 6806, 5); + } + + public static string ??() + { + return 5[334] ?? 6(334, 6811, 8); + } + + public static string ??() + { + return 5[335] ?? 6(335, 6819, 8); + } + + public static string ??() + { + return 5[336] ?? 6(336, 6827, 11); + } + + public static string ??() + { + return 5[337] ?? 6(337, 6838, 28); + } + + public static string ??() + { + return 5[338] ?? 6(338, 6866, 35); + } + + public static string ??() + { + return 5[339] ?? 6(339, 6901, 1); + } + + public static string ??() + { + return 5[340] ?? 6(340, 6902, 1); + } + + public static string ??() + { + return 5[341] ?? 6(341, 6903, 2); + } + + public static string ??() + { + return 5[342] ?? 6(342, 6905, 6); + } + + public static string ??() + { + return 5[343] ?? 6(343, 6911, 1); + } + + public static string ??() + { + return 5[344] ?? 6(344, 6912, 6); + } + + public static string ??() + { + return 5[345] ?? 6(345, 6918, 8); + } + + public static string ??() + { + return 5[346] ?? 6(346, 6926, 10); + } + + public static string ??() + { + return 5[347] ?? 6(347, 6936, 10); + } + + public static string ??() + { + return 5[348] ?? 6(348, 6946, 12); + } + + public static string ??() + { + return 5[349] ?? 6(349, 6958, 14); + } + + public static string ??() + { + return 5[350] ?? 6(350, 6972, 6); + } + + public static string ??() + { + return 5[351] ?? 6(351, 6978, 8); + } + + public static string ??() + { + return 5[352] ?? 6(352, 6986, 10); + } + + public static string ??() + { + return 5[353] ?? 6(353, 6996, 10); + } + + public static string ??() + { + return 5[354] ?? 6(354, 7006, 12); + } + + public static string ??() + { + return 5[355] ?? 6(355, 7018, 14); + } + + public static string ??() + { + return 5[356] ?? 6(356, 7032, 57); + } + + public static string ??() + { + return 5[357] ?? 6(357, 7089, 24); + } + + public static string ??() + { + return 5[358] ?? 6(358, 7113, 5); + } + + public static string ??() + { + return 5[359] ?? 6(359, 7118, 3); + } + + public static string ??() + { + return 5[360] ?? 6(360, 7121, 6); + } + + public static string ??() + { + return 5[361] ?? 6(361, 7127, 2); + } + + public static string ??() + { + return 5[362] ?? 6(362, 7129, 13); + } + + public static string ??() + { + return 5[363] ?? 6(363, 7142, 22); + } + + public static string ??() + { + return 5[364] ?? 6(364, 7164, 19); + } + + public static string ??() + { + return 5[365] ?? 6(365, 7183, 14); + } + + public static string ??() + { + return 5[366] ?? 6(366, 7197, 42); + } + + public static string ??() + { + return 5[367] ?? 6(367, 7239, 50); + } + + public static string ??() + { + return 5[368] ?? 6(368, 7289, 22); + } + + public static string ??() + { + return 5[369] ?? 6(369, 7311, 6); + } + + public static string ??() + { + return 5[370] ?? 6(370, 7317, 7); + } + + public static string ??() + { + return 5[371] ?? 6(371, 7324, 16); + } + + public static string ??() + { + return 5[372] ?? 6(372, 7340, 16); + } + + public static string ??() + { + return 5[373] ?? 6(373, 7356, 6); + } + + public static string ??() + { + return 5[374] ?? 6(374, 7362, 6); + } + + public static string ??() + { + return 5[375] ?? 6(375, 7368, 9); + } + + public static string ??() + { + return 5[376] ?? 6(376, 7377, 14); + } + + public static string ??() + { + return 5[377] ?? 6(377, 7391, 22); + } + + public static string ??() + { + return 5[378] ?? 6(378, 7413, 3); + } + + public static string ??() + { + return 5[379] ?? 6(379, 7416, 2); + } + + public static string ??() + { + return 5[380] ?? 6(380, 7418, 12); + } + + public static string ??() + { + return 5[381] ?? 6(381, 7430, 16); + } + + public static string ??() + { + return 5[382] ?? 6(382, 7446, 15); + } + + public static string ??() + { + return 5[383] ?? 6(383, 7461, 13); + } + + public static string ??() + { + return 5[384] ?? 6(384, 7474, 44); + } + + public static string ??() + { + return 5[385] ?? 6(385, 7518, 40); + } + + public static string ??() + { + return 5[386] ?? 6(386, 7558, 35); + } + + public static string ??() + { + return 5[387] ?? 6(387, 7593, 39); + } + + public static string ??() + { + return 5[388] ?? 6(388, 7632, 15); + } + + public static string ??() + { + return 5[389] ?? 6(389, 7647, 8); + } + + public static string ??() + { + return 5[390] ?? 6(390, 7655, 4); + } + + public static string ??() + { + return 5[391] ?? 6(391, 7659, 5); + } + + public static string ??() + { + return 5[392] ?? 6(392, 7664, 6); + } + + public static string ??() + { + return 5[393] ?? 6(393, 7670, 19); + } + + public static string ??() + { + return 5[394] ?? 6(394, 7689, 4); + } + + public static string ??() + { + return 5[395] ?? 6(395, 7693, 14); + } + + public static string ??() + { + return 5[396] ?? 6(396, 7707, 66); + } + + public static string ??() + { + return 5[397] ?? 6(397, 7773, 54); + } + + public static string ??() + { + return 5[398] ?? 6(398, 7827, 16); + } + + public static string ??() + { + return 5[399] ?? 6(399, 7843, 8); + } + + public static string ??() + { + return 5[400] ?? 6(400, 7851, 9); + } + + public static string ??() + { + return 5[401] ?? 6(401, 7860, 7); + } + + public static string ??() + { + return 5[402] ?? 6(402, 7867, 14); + } + + public static string ??() + { + return 5[403] ?? 6(403, 7881, 15); + } + + public static string ??() + { + return 5[404] ?? 6(404, 7896, 8); + } + + public static string ??() + { + return 5[405] ?? 6(405, 7904, 7); + } + + public static string ??() + { + return 5[406] ?? 6(406, 7911, 11); + } + + public static string ??() + { + return 5[407] ?? 6(407, 7922, 10); + } + + public static string ??() + { + return 5[408] ?? 6(408, 7932, 10); + } + + public static string ??() + { + return 5[409] ?? 6(409, 7942, 20); + } + + public static string ??() + { + return 5[410] ?? 6(410, 7962, 7); + } + + public static string ??() + { + return 5[411] ?? 6(411, 7969, 3); + } + + public static string ??() + { + return 5[412] ?? 6(412, 7972, 4); + } + + public static string ??() + { + return 5[413] ?? 6(413, 7976, 5); + } + + public static string ??() + { + return 5[414] ?? 6(414, 7981, 10); + } + + public static string ??() + { + return 5[415] ?? 6(415, 7991, 10); + } + + public static string ??() + { + return 5[416] ?? 6(416, 8001, 22); + } + + public static string ??() + { + return 5[417] ?? 6(417, 8023, 19); + } + + public static string ??() + { + return 5[418] ?? 6(418, 8042, 15); + } + + public static string ??() + { + return 5[419] ?? 6(419, 8057, 31); + } + + public static string ??() + { + return 5[420] ?? 6(420, 8088, 12); + } + + public static string ??() + { + return 5[421] ?? 6(421, 8100, 14); + } + + public static string ??() + { + return 5[422] ?? 6(422, 8114, 15); + } + + public static string ??() + { + return 5[423] ?? 6(423, 8129, 13); + } + + public static string ??() + { + return 5[424] ?? 6(424, 8142, 16); + } + + public static string ??() + { + return 5[425] ?? 6(425, 8158, 22); + } + + public static string ??() + { + return 5[426] ?? 6(426, 8180, 18); + } + + public static string ??() + { + return 5[427] ?? 6(427, 8198, 16); + } + + public static string ??() + { + return 5[428] ?? 6(428, 8214, 15); + } + + public static string ??() + { + return 5[429] ?? 6(429, 8229, 17); + } + + public static string ??() + { + return 5[430] ?? 6(430, 8246, 18); + } + + public static string ??() + { + return 5[431] ?? 6(431, 8264, 16); + } + + public static string ??() + { + return 5[432] ?? 6(432, 8280, 10); + } + + public static string ??() + { + return 5[433] ?? 6(433, 8290, 5); + } + + public static string ??() + { + return 5[434] ?? 6(434, 8295, 2); + } + + public static string ??() + { + return 5[435] ?? 6(435, 8297, 8); + } + + public static string ??() + { + return 5[436] ?? 6(436, 8305, 8); + } + + public static string ??() + { + return 5[437] ?? 6(437, 8313, 6); + } + + public static string ??() + { + return 5[438] ?? 6(438, 8319, 3); + } + + public static string ??() + { + return 5[439] ?? 6(439, 8322, 2); + } + + public static string ??() + { + return 5[440] ?? 6(440, 8324, 2); + } + + public static string ??() + { + return 5[441] ?? 6(441, 8326, 2); + } + + public static string ??() + { + return 5[442] ?? 6(442, 8328, 1); + } + + public static string ??() + { + return 5[443] ?? 6(443, 8329, 10); + } + + public static string ??() + { + return 5[444] ?? 6(444, 8339, 14); + } + + public static string ??() + { + return 5[445] ?? 6(445, 8353, 12); + } + + public static string ??() + { + return 5[446] ?? 6(446, 8365, 20); + } + + public static string ??() + { + return 5[447] ?? 6(447, 8385, 13); + } + + public static string ??() + { + return 5[448] ?? 6(448, 8398, 14); + } + + public static string ??() + { + return 5[449] ?? 6(449, 8412, 14); + } + + public static string ??() + { + return 5[450] ?? 6(450, 8426, 20); + } + + public static string ??() + { + return 5[451] ?? 6(451, 8446, 20); + } + + public static string ??() + { + return 5[452] ?? 6(452, 8466, 19); + } + + public static string ??() + { + return 5[453] ?? 6(453, 8485, 15); + } + + public static string ??() + { + return 5[454] ?? 6(454, 8500, 15); + } + + public static string ??() + { + return 5[455] ?? 6(455, 8515, 16); + } + + public static string ??() + { + return 5[456] ?? 6(456, 8531, 22); + } + + public static string ??() + { + return 5[457] ?? 6(457, 8553, 18); + } + + public static string ??() + { + return 5[458] ?? 6(458, 8571, 17); + } + + public static string ??() + { + return 5[459] ?? 6(459, 8588, 17); + } + + public static string ??() + { + return 5[460] ?? 6(460, 8605, 8); + } + + public static string ??() + { + return 5[461] ?? 6(461, 8613, 12); + } + + public static string ??() + { + return 5[462] ?? 6(462, 8625, 25); + } + + public static string ??() + { + return 5[463] ?? 6(463, 8650, 26); + } + + public static string ??() + { + return 5[464] ?? 6(464, 8676, 28); + } + + public static string ??() + { + return 5[465] ?? 6(465, 8704, 37); + } + + public static string ??() + { + return 5[466] ?? 6(466, 8741, 23); + } + + public static string ??() + { + return 5[467] ?? 6(467, 8764, 5); + } + + public static string ??() + { + return 5[468] ?? 6(468, 8769, 14); + } + + public static string ??() + { + return 5[469] ?? 6(469, 8783, 19); + } + + public static string ??() + { + return 5[470] ?? 6(470, 8802, 17); + } + + public static string ??() + { + return 5[471] ?? 6(471, 8819, 12); + } + + public static string ??() + { + return 5[472] ?? 6(472, 8831, 10); + } + + public static string ??() + { + return 5[473] ?? 6(473, 8841, 15); + } + + public static string ??() + { + return 5[474] ?? 6(474, 8856, 12); + } + + public static string ??() + { + return 5[475] ?? 6(475, 8868, 11); + } + + public static string ??() + { + return 5[476] ?? 6(476, 8879, 10); + } + + public static string ??() + { + return 5[477] ?? 6(477, 8889, 9); + } + + public static string ??() + { + return 5[478] ?? 6(478, 8898, 14); + } + + public static string ??() + { + return 5[479] ?? 6(479, 8912, 8); + } + + public static string ??() + { + return 5[480] ?? 6(480, 8920, 4); + } + + public static string ??() + { + return 5[481] ?? 6(481, 8924, 14); + } + + public static string ??() + { + return 5[482] ?? 6(482, 8938, 15); + } + + public static string ??() + { + return 5[483] ?? 6(483, 8953, 14); + } + + public static string ??() + { + return 5[484] ?? 6(484, 8967, 27); + } + + public static string ??() + { + return 5[485] ?? 6(485, 8994, 18); + } + + public static string ??() + { + return 5[486] ?? 6(486, 9012, 40); + } + + public static string ??() + { + return 5[487] ?? 6(487, 9052, 30); + } + + public static string ??() + { + return 5[488] ?? 6(488, 9082, 39); + } + + public static string ??() + { + return 5[489] ?? 6(489, 9121, 17); + } + + public static string ??() + { + return 5[490] ?? 6(490, 9138, 24); + } + + public static string ??() + { + return 5[491] ?? 6(491, 9162, 10); + } + + public static string ??() + { + return 5[492] ?? 6(492, 9172, 1); + } + + public static string ??() + { + return 5[493] ?? 6(493, 9173, 2); + } + + public static string ??() + { + return 5[494] ?? 6(494, 9175, 3); + } + + public static string ??() + { + return 5[495] ?? 6(495, 9178, 9); + } + + public static string ??() + { + return 5[496] ?? 6(496, 9187, 8); + } + + public static string ??() + { + return 5[497] ?? 6(497, 9195, 4); + } + + public static string ??() + { + return 5[498] ?? 6(498, 9199, 32); + } + + public static string ??() + { + return 5[499] ?? 6(499, 9231, 3); + } + + public static string ??() + { + return 5[500] ?? 6(500, 9234, 5); + } + + public static string ??() + { + return 5[501] ?? 6(501, 9239, 7); + } + + public static string ??() + { + return 5[502] ?? 6(502, 9246, 7); + } + + public static string ??() + { + return 5[503] ?? 6(503, 9253, 15); + } + + public static string ??() + { + return 5[504] ?? 6(504, 9268, 12); + } + + public static string ??() + { + return 5[505] ?? 6(505, 9280, 5); + } + + public static string ??() + { + return 5[506] ?? 6(506, 9285, 1); + } + + public static string ??() + { + return 5[507] ?? 6(507, 9286, 7); + } + + public static string ??() + { + return 5[508] ?? 6(508, 9293, 12); + } + + public static string ??() + { + return 5[509] ?? 6(509, 9305, 10); + } + + public static string ??() + { + return 5[510] ?? 6(510, 9315, 15); + } + + public static string ??() + { + return 5[511] ?? 6(511, 9330, 15); + } + + public static string ??() + { + return 5[512] ?? 6(512, 9345, 22); + } + + public static string ??() + { + return 5[513] ?? 6(513, 9367, 2); + } + + public static string ??() + { + return 5[514] ?? 6(514, 9369, 6); + } + + public static string ??() + { + return 5[515] ?? 6(515, 9375, 3); + } + + public static string ??() + { + return 5[516] ?? 6(516, 9378, 11); + } + + public static string ??() + { + return 5[517] ?? 6(517, 9389, 18); + } + + public static string ??() + { + return 5[518] ?? 6(518, 9407, 7); + } + + public static string ??() + { + return 5[519] ?? 6(519, 9414, 33); + } + + public static string ??() + { + return 5[520] ?? 6(520, 9447, 8); + } + + public static string ??() + { + return 5[521] ?? 6(521, 9455, 5); + } + + public static string ??() + { + return 5[522] ?? 6(522, 9460, 7); + } + + public static string ??() + { + return 5[523] ?? 6(523, 9467, 7); + } + + public static string ??() + { + return 5[524] ?? 6(524, 9474, 7); + } + + public static string ??() + { + return 5[525] ?? 6(525, 9481, 17); + } + + public static string ??() + { + return 5[526] ?? 6(526, 9498, 7); + } + + public static string ??() + { + return 5[527] ?? 6(527, 9505, 7); + } + + public static string ??() + { + return 5[528] ?? 6(528, 9512, 7); + } + + public static string ??() + { + return 5[529] ?? 6(529, 9519, 7); + } + + public static string ??() + { + return 5[530] ?? 6(530, 9526, 17); + } + + public static string ??() + { + return 5[531] ?? 6(531, 9543, 7); + } + + public static string ??() + { + return 5[532] ?? 6(532, 9550, 7); + } + + public static string ??() + { + return 5[533] ?? 6(533, 9557, 7); + } + + public static string ??() + { + return 5[534] ?? 6(534, 9564, 7); + } + + public static string ??() + { + return 5[535] ?? 6(535, 9571, 7); + } + + public static string ??() + { + return 5[536] ?? 6(536, 9578, 7); + } + + public static string ??() + { + return 5[537] ?? 6(537, 9585, 7); + } + + public static string ??() + { + return 5[538] ?? 6(538, 9592, 7); + } + + public static string ??() + { + return 5[539] ?? 6(539, 9599, 7); + } + + public static string ??() + { + return 5[540] ?? 6(540, 9606, 7); + } + + public static string ??() + { + return 5[541] ?? 6(541, 9613, 7); + } + + public static string ??() + { + return 5[542] ?? 6(542, 9620, 7); + } + + public static string ??() + { + return 5[543] ?? 6(543, 9627, 7); + } + + public static string ??() + { + return 5[544] ?? 6(544, 9634, 7); + } + + public static string ??() + { + return 5[545] ?? 6(545, 9641, 7); + } + + public static string ??() + { + return 5[546] ?? 6(546, 9648, 7); + } + + public static string ??() + { + return 5[547] ?? 6(547, 9655, 7); + } + + public static string ??() + { + return 5[548] ?? 6(548, 9662, 7); + } + + public static string ??() + { + return 5[549] ?? 6(549, 9669, 7); + } + + public static string ??() + { + return 5[550] ?? 6(550, 9676, 7); + } + + public static string ??() + { + return 5[551] ?? 6(551, 9683, 7); + } + + public static string ??() + { + return 5[552] ?? 6(552, 9690, 7); + } + + public static string ??() + { + return 5[553] ?? 6(553, 9697, 7); + } + + public static string ??() + { + return 5[554] ?? 6(554, 9704, 7); + } + + public static string ??() + { + return 5[555] ?? 6(555, 9711, 7); + } + + public static string ??() + { + return 5[556] ?? 6(556, 9718, 7); + } + + public static string ??() + { + return 5[557] ?? 6(557, 9725, 17); + } + + public static string ??() + { + return 5[558] ?? 6(558, 9742, 7); + } + + public static string ??() + { + return 5[559] ?? 6(559, 9749, 7); + } + + public static string ??() + { + return 5[560] ?? 6(560, 9756, 7); + } + + public static string ??() + { + return 5[561] ?? 6(561, 9763, 7); + } + + public static string ??() + { + return 5[562] ?? 6(562, 9770, 7); + } + + public static string ??() + { + return 5[563] ?? 6(563, 9777, 7); + } + + public static string ??() + { + return 5[564] ?? 6(564, 9784, 7); + } + + public static string ??() + { + return 5[565] ?? 6(565, 9791, 7); + } + + public static string ??() + { + return 5[566] ?? 6(566, 9798, 7); + } + + public static string ??() + { + return 5[567] ?? 6(567, 9805, 7); + } + + public static string ??() + { + return 5[568] ?? 6(568, 9812, 7); + } + + public static string ??() + { + return 5[569] ?? 6(569, 9819, 7); + } + + public static string ??() + { + return 5[570] ?? 6(570, 9826, 7); + } + + public static string ??() + { + return 5[571] ?? 6(571, 9833, 7); + } + + public static string ??() + { + return 5[572] ?? 6(572, 9840, 7); + } + + public static string ??() + { + return 5[573] ?? 6(573, 9847, 7); + } + + public static string ??() + { + return 5[574] ?? 6(574, 9854, 7); + } + + public static string ??() + { + return 5[575] ?? 6(575, 9861, 17); + } + + public static string ??() + { + return 5[576] ?? 6(576, 9878, 7); + } + + public static string ??() + { + return 5[577] ?? 6(577, 9885, 7); + } + + public static string ??() + { + return 5[578] ?? 6(578, 9892, 7); + } + + public static string ??() + { + return 5[579] ?? 6(579, 9899, 7); + } + + public static string ??() + { + return 5[580] ?? 6(580, 9906, 7); + } + + public static string ??() + { + return 5[581] ?? 6(581, 9913, 7); + } + + public static string ??() + { + return 5[582] ?? 6(582, 9920, 7); + } + + public static string ??() + { + return 5[583] ?? 6(583, 9927, 7); + } + + public static string ??() + { + return 5[584] ?? 6(584, 9934, 7); + } + + public static string ??() + { + return 5[585] ?? 6(585, 9941, 7); + } + + public static string ??() + { + return 5[586] ?? 6(586, 9948, 7); + } + + public static string ??() + { + return 5[587] ?? 6(587, 9955, 7); + } + + public static string ??() + { + return 5[588] ?? 6(588, 9962, 7); + } + + public static string ??() + { + return 5[589] ?? 6(589, 9969, 7); + } + + public static string ??() + { + return 5[590] ?? 6(590, 9976, 7); + } + + public static string ??() + { + return 5[591] ?? 6(591, 9983, 17); + } + + public static string ??() + { + return 5[592] ?? 6(592, 10000, 7); + } + + public static string ??() + { + return 5[593] ?? 6(593, 10007, 7); + } + + public static string ??() + { + return 5[594] ?? 6(594, 10014, 7); + } + + public static string ??() + { + return 5[595] ?? 6(595, 10021, 7); + } + + public static string ??() + { + return 5[596] ?? 6(596, 10028, 7); + } + + public static string ??() + { + return 5[597] ?? 6(597, 10035, 7); + } + + public static string ??() + { + return 5[598] ?? 6(598, 10042, 7); + } + + public static string ??() + { + return 5[599] ?? 6(599, 10049, 7); + } + + public static string ??() + { + return 5[600] ?? 6(600, 10056, 17); + } + + public static string ??() + { + return 5[601] ?? 6(601, 10073, 7); + } + + public static string ??() + { + return 5[602] ?? 6(602, 10080, 7); + } + + public static string ??() + { + return 5[603] ?? 6(603, 10087, 7); + } + + public static string ??() + { + return 5[604] ?? 6(604, 10094, 7); + } + + public static string ??() + { + return 5[605] ?? 6(605, 10101, 7); + } + + public static string ??() + { + return 5[606] ?? 6(606, 10108, 7); + } + + public static string ??() + { + return 5[607] ?? 6(607, 10115, 7); + } + + public static string ??() + { + return 5[608] ?? 6(608, 10122, 7); + } + + public static string ??() + { + return 5[609] ?? 6(609, 10129, 7); + } + + public static string ??() + { + return 5[610] ?? 6(610, 10136, 7); + } + + public static string ??() + { + return 5[611] ?? 6(611, 10143, 7); + } + + public static string ??() + { + return 5[612] ?? 6(612, 10150, 7); + } + + public static string ??() + { + return 5[613] ?? 6(613, 10157, 7); + } + + public static string ??() + { + return 5[614] ?? 6(614, 10164, 7); + } + + public static string ??() + { + return 5[615] ?? 6(615, 10171, 8); + } + + public static string ??() + { + return 5[616] ?? 6(616, 10179, 8); + } + + public static string ??() + { + return 5[617] ?? 6(617, 10187, 8); + } + + public static string ??() + { + return 5[618] ?? 6(618, 10195, 8); + } + + public static string ??() + { + return 5[619] ?? 6(619, 10203, 8); + } + + public static string ??() + { + return 5[620] ?? 6(620, 10211, 8); + } + + public static string ??() + { + return 5[621] ?? 6(621, 10219, 8); + } + + public static string ??() + { + return 5[622] ?? 6(622, 10227, 8); + } + + public static string ??() + { + return 5[623] ?? 6(623, 10235, 8); + } + + public static string ??() + { + return 5[624] ?? 6(624, 10243, 11); + } + + public static string ??() + { + return 5[625] ?? 6(625, 10254, 10); + } + + public static string ??() + { + return 5[626] ?? 6(626, 10264, 10); + } + + public static string ??() + { + return 5[627] ?? 6(627, 10274, 10); + } + + public static string ??() + { + return 5[628] ?? 6(628, 10284, 10); + } + + public static string ??() + { + return 5[629] ?? 6(629, 10294, 10); + } + + public static string ??() + { + return 5[630] ?? 6(630, 10304, 10); + } + + public static string ??() + { + return 5[631] ?? 6(631, 10314, 10); + } + + public static string ??() + { + return 5[632] ?? 6(632, 10324, 10); + } + + public static string ??() + { + return 5[633] ?? 6(633, 10334, 10); + } + + public static string ??() + { + return 5[634] ?? 6(634, 10344, 7); + } + + public static string ??() + { + return 5[635] ?? 6(635, 10351, 7); + } + + public static string ??() + { + return 5[636] ?? 6(636, 10358, 7); + } + + public static string ??() + { + return 5[637] ?? 6(637, 10365, 7); + } + + public static string ??() + { + return 5[638] ?? 6(638, 10372, 7); + } + + public static string ??() + { + return 5[639] ?? 6(639, 10379, 7); + } + + public static string ??() + { + return 5[640] ?? 6(640, 10386, 7); + } + + public static string ??() + { + return 5[641] ?? 6(641, 10393, 6); + } + + public static string ??() + { + return 5[642] ?? 6(642, 10399, 13); + } + + public static string ??() + { + return 5[643] ?? 6(643, 10412, 9); + } + + public static string ??() + { + return 5[644] ?? 6(644, 10421, 6); + } + + public static string ??() + { + return 5[645] ?? 6(645, 10427, 5); + } + + public static string ??() + { + return 5[646] ?? 6(646, 10432, 9); + } + + public static string ??() + { + return 5[647] ?? 6(647, 10441, 7); + } + + public static string ??() + { + return 5[648] ?? 6(648, 10448, 5); + } + + public static string ??() + { + return 5[649] ?? 6(649, 10453, 9); + } + + public static string ??() + { + return 5[650] ?? 6(650, 10462, 5); + } + + public static string ??() + { + return 5[651] ?? 6(651, 10467, 10); + } + + public static string ??() + { + return 5[652] ?? 6(652, 10477, 17); + } + + public static string ??() + { + return 5[653] ?? 6(653, 10494, 20); + } + + public static string ??() + { + return 5[654] ?? 6(654, 10514, 5); + } + + public static string ??() + { + return 5[655] ?? 6(655, 10519, 12); + } + + public static string ??() + { + return 5[656] ?? 6(656, 10531, 12); + } + + public static string ??() + { + return 5[657] ?? 6(657, 10543, 8); + } + + public static string ??() + { + return 5[658] ?? 6(658, 10551, 5); + } + + public static string ??() + { + return 5[659] ?? 6(659, 10556, 6); + } + + public static string ??() + { + return 5[660] ?? 6(660, 10562, 9); + } + + public static string ??() + { + return 5[661] ?? 6(661, 10571, 19); + } + + public static string ??() + { + return 5[662] ?? 6(662, 10590, 6); + } + + public static string ??() + { + return 5[663] ?? 6(663, 10596, 5); + } + + public static string ??() + { + return 5[664] ?? 6(664, 10601, 14); + } + + public static string ??() + { + return 5[665] ?? 6(665, 10615, 12); + } + + public static string ??() + { + return 5[666] ?? 6(666, 10627, 8); + } + + public static string ??() + { + return 5[667] ?? 6(667, 10635, 6); + } + + public static string ??() + { + return 5[668] ?? 6(668, 10641, 5); + } + + public static string ??() + { + return 5[669] ?? 6(669, 10646, 5); + } + + public static string ??() + { + return 5[670] ?? 6(670, 10651, 8); + } + + public static string ??() + { + return 5[671] ?? 6(671, 10659, 12); + } + + public static string ??() + { + return 5[672] ?? 6(672, 10671, 5); + } + + public static string ??() + { + return 5[673] ?? 6(673, 10676, 6); + } + + public static string ??() + { + return 5[674] ?? 6(674, 10682, 11); + } + + public static string ??() + { + return 5[675] ?? 6(675, 10693, 4); + } + + public static string ??() + { + return 5[676] ?? 6(676, 10697, 10); + } + + public static string ??() + { + return 5[677] ?? 6(677, 10707, 12); + } + + public static string ??() + { + return 5[678] ?? 6(678, 10719, 10); + } + + public static string ??() + { + return 5[679] ?? 6(679, 10729, 17); + } + + public static string ??() + { + return 5[680] ?? 6(680, 10746, 11); + } + + public static string ??() + { + return 5[681] ?? 6(681, 10757, 18); + } + + public static string ??() + { + return 5[682] ?? 6(682, 10775, 13); + } + + public static string ??() + { + return 5[683] ?? 6(683, 10788, 14); + } + + public static string ??() + { + return 5[684] ?? 6(684, 10802, 21); + } + + public static string ??() + { + return 5[685] ?? 6(685, 10823, 4); + } + + public static string ??() + { + return 5[686] ?? 6(686, 10827, 15); + } + + public static string ??() + { + return 5[687] ?? 6(687, 10842, 4); + } + + public static string ??() + { + return 5[688] ?? 6(688, 10846, 4); + } + + public static string ??() + { + return 5[689] ?? 6(689, 10850, 11); + } + + public static string ??() + { + return 5[690] ?? 6(690, 10861, 16); + } + + public static string ??() + { + return 5[691] ?? 6(691, 10877, 21); + } + + public static string ??() + { + return 5[692] ?? 6(692, 10898, 6); + } + + public static string ??() + { + return 5[693] ?? 6(693, 10904, 13); + } + + public static string ??() + { + return 5[694] ?? 6(694, 10917, 18); + } + + public static string ??() + { + return 5[695] ?? 6(695, 10935, 4); + } + + public static string ??() + { + return 5[696] ?? 6(696, 10939, 11); + } + + public static string ??() + { + return 5[697] ?? 6(697, 10950, 9); + } + + public static string ??() + { + return 5[698] ?? 6(698, 10959, 8); + } + + public static string ??() + { + return 5[699] ?? 6(699, 10967, 8); + } + + public static string ??() + { + return 5[700] ?? 6(700, 10975, 5); + } + + public static string ??() + { + return 5[701] ?? 6(701, 10980, 15); + } + + public static string ??() + { + return 5[702] ?? 6(702, 10995, 15); + } + + public static string ??() + { + return 5[703] ?? 6(703, 11010, 25); + } + + public static string ??() + { + return 5[704] ?? 6(704, 11035, 21); + } + + public static string ??() + { + return 5[705] ?? 6(705, 11056, 5); + } + + public static string ??() + { + return 5[706] ?? 6(706, 11061, 5); + } + + public static string ??() + { + return 5[707] ?? 6(707, 11066, 14); + } + + public static string ??() + { + return 5[708] ?? 6(708, 11080, 5); + } + + public static string ??() + { + return 5[709] ?? 6(709, 11085, 5); + } + + public static string ??() + { + return 5[710] ?? 6(710, 11090, 8); + } + + public static string ??() + { + return 5[711] ?? 6(711, 11098, 7); + } + + public static string ??() + { + return 5[712] ?? 6(712, 11105, 4); + } + + public static string ??() + { + return 5[713] ?? 6(713, 11109, 5); + } + + public static string ??() + { + return 5[714] ?? 6(714, 11114, 7); + } + + public static string ??() + { + return 5[715] ?? 6(715, 11121, 6); + } + + public static string ??() + { + return 5[716] ?? 6(716, 11127, 13); + } + + public static string ??() + { + return 5[717] ?? 6(717, 11140, 12); + } + + public static string ??() + { + return 5[718] ?? 6(718, 11152, 12); + } + + public static string ??() + { + return 5[719] ?? 6(719, 11164, 9); + } + + public static string ??() + { + return 5[720] ?? 6(720, 11173, 8); + } + + public static string ??() + { + return 5[721] ?? 6(721, 11181, 7); + } + + public static string ??() + { + return 5[722] ?? 6(722, 11188, 7); + } + + public static string ??() + { + return 5[723] ?? 6(723, 11195, 7); + } + + public static string ??() + { + return 5[724] ?? 6(724, 11202, 7); + } + + public static string ??() + { + return 5[725] ?? 6(725, 11209, 7); + } + + public static string ??() + { + return 5[726] ?? 6(726, 11216, 37); + } + + public static string ??() + { + return 5[727] ?? 6(727, 11253, 33); + } + + public static string ??() + { + return 5[728] ?? 6(728, 11286, 34); + } + + public static string ??() + { + return 5[729] ?? 6(729, 11320, 44); + } + + public static string ??() + { + return 5[730] ?? 6(730, 11364, 38); + } + + public static string ??() + { + return 5[731] ?? 6(731, 11402, 40); + } + + public static string ??() + { + return 5[732] ?? 6(732, 11442, 38); + } + + public static string ??() + { + return 5[733] ?? 6(733, 11480, 31); + } + + public static string ??() + { + return 5[734] ?? 6(734, 11511, 41); + } + + public static string ??() + { + return 5[735] ?? 6(735, 11552, 31); + } + + public static string ??() + { + return 5[736] ?? 6(736, 11583, 36); + } + + public static string ??() + { + return 5[737] ?? 6(737, 11619, 32); + } + + public static string ??() + { + return 5[738] ?? 6(738, 11651, 36); + } + + public static string ??() + { + return 5[739] ?? 6(739, 11687, 32); + } + + public static string ??() + { + return 5[740] ?? 6(740, 11719, 28); + } + + public static string ??() + { + return 5[741] ?? 6(741, 11747, 34); + } + + public static string ??() + { + return 5[742] ?? 6(742, 11781, 26); + } + + public static string ??() + { + return 5[743] ?? 6(743, 11807, 24); + } + + public static string ??() + { + return 5[744] ?? 6(744, 11831, 20); + } + + public static string ??() + { + return 5[745] ?? 6(745, 11851, 21); + } + + public static string ??() + { + return 5[746] ?? 6(746, 11872, 21); + } + + public static string ??() + { + return 5[747] ?? 6(747, 11893, 22); + } + + public static string ??() + { + return 5[748] ?? 6(748, 11915, 25); + } + + public static string ??() + { + return 5[749] ?? 6(749, 11940, 25); + } + + public static string ??() + { + return 5[750] ?? 6(750, 11965, 21); + } + + public static string ??() + { + return 5[751] ?? 6(751, 11986, 21); + } + + public static string ??() + { + return 5[752] ?? 6(752, 12007, 24); + } + + public static string ??() + { + return 5[753] ?? 6(753, 12031, 27); + } + + public static string ??() + { + return 5[754] ?? 6(754, 12058, 21); + } + + public static string ??() + { + return 5[755] ?? 6(755, 12079, 21); + } + + public static string ??() + { + return 5[756] ?? 6(756, 12100, 22); + } + + public static string ??() + { + return 5[757] ?? 6(757, 12122, 22); + } + + public static string ??() + { + return 5[758] ?? 6(758, 12144, 25); + } + + public static string ??() + { + return 5[759] ?? 6(759, 12169, 21); + } + + public static string ??() + { + return 5[760] ?? 6(760, 12190, 18); + } + + public static string ??() + { + return 5[761] ?? 6(761, 12208, 28); + } + + public static string ??() + { + return 5[762] ?? 6(762, 12236, 27); + } + + public static string ??() + { + return 5[763] ?? 6(763, 12263, 35); + } + + public static string ??() + { + return 5[764] ?? 6(764, 12298, 33); + } + + public static string ??() + { + return 5[765] ?? 6(765, 12331, 29); + } + + public static string ??() + { + return 5[766] ?? 6(766, 12360, 30); + } + + public static string ??() + { + return 5[767] ?? 6(767, 12390, 30); + } + + public static string ??() + { + return 5[768] ?? 6(768, 12420, 34); + } + + public static string ??() + { + return 5[769] ?? 6(769, 12454, 34); + } + + public static string ??() + { + return 5[770] ?? 6(770, 12488, 30); + } + + public static string ??() + { + return 5[771] ?? 6(771, 12518, 30); + } + + public static string ??() + { + return 5[772] ?? 6(772, 12548, 33); + } + + public static string ??() + { + return 5[773] ?? 6(773, 12581, 36); + } + + public static string ??() + { + return 5[774] ?? 6(774, 12617, 30); + } + + public static string ??() + { + return 5[775] ?? 6(775, 12647, 31); + } + + public static string ??() + { + return 5[776] ?? 6(776, 12678, 34); + } + + public static string ??() + { + return 5[777] ?? 6(777, 12712, 30); + } + + public static string ??() + { + return 5[778] ?? 6(778, 12742, 27); + } + + public static string ??() + { + return 5[779] ?? 6(779, 12769, 37); + } + + public static string ??() + { + return 5[780] ?? 6(780, 12806, 36); + } + + public static string ??() + { + return 5[781] ?? 6(781, 12842, 33); + } + + public static string ??() + { + return 5[782] ?? 6(782, 12875, 33); + } + + public static string ??() + { + return 5[783] ?? 6(783, 12908, 38); + } + + public static string ??() + { + return 5[784] ?? 6(784, 12946, 34); + } + + public static string ??() + { + return 5[785] ?? 6(785, 12980, 39); + } + + public static string ??() + { + return 5[786] ?? 6(786, 13019, 35); + } + + public static string ??() + { + return 5[787] ?? 6(787, 13054, 39); + } + + public static string ??() + { + return 5[788] ?? 6(788, 13093, 32); + } + + public static string ??() + { + return 5[789] ?? 6(789, 13125, 32); + } + + public static string ??() + { + return 5[790] ?? 6(790, 13157, 37); + } + + public static string ??() + { + return 5[791] ?? 6(791, 13194, 33); + } + + public static string ??() + { + return 5[792] ?? 6(792, 13227, 29); + } + + public static string ??() + { + return 5[793] ?? 6(793, 13256, 29); + } + + public static string ??() + { + return 5[794] ?? 6(794, 13285, 25); + } + + public static string ??() + { + return 5[795] ?? 6(795, 13310, 35); + } + + public static string ??() + { + return 5[796] ?? 6(796, 13345, 26); + } + + public static string ??() + { + return 5[797] ?? 6(797, 13371, 26); + } + + public static string ??() + { + return 5[798] ?? 6(798, 13397, 26); + } + + public static string ??() + { + return 5[799] ?? 6(799, 13423, 30); + } + + public static string ??() + { + return 5[800] ?? 6(800, 13453, 26); + } + + public static string ??() + { + return 5[801] ?? 6(801, 13479, 30); + } + + public static string ??() + { + return 5[802] ?? 6(802, 13509, 32); + } + + public static string ??() + { + return 5[803] ?? 6(803, 13541, 26); + } + + public static string ??() + { + return 5[804] ?? 6(804, 13567, 36); + } + + public static string ??() + { + return 5[805] ?? 6(805, 13603, 26); + } + + public static string ??() + { + return 5[806] ?? 6(806, 13629, 29); + } + + public static string ??() + { + return 5[807] ?? 6(807, 13658, 26); + } + + public static string ??() + { + return 5[808] ?? 6(808, 13684, 26); + } + + public static string ??() + { + return 5[809] ?? 6(809, 13710, 27); + } + + public static string ??() + { + return 5[810] ?? 6(810, 13737, 33); + } + + public static string ??() + { + return 5[811] ?? 6(811, 13770, 27); + } + + public static string ??() + { + return 5[812] ?? 6(812, 13797, 30); + } + + public static string ??() + { + return 5[813] ?? 6(813, 13827, 23); + } + + public static string ??() + { + return 5[814] ?? 6(814, 13850, 26); + } + + public static string ??() + { + return 5[815] ?? 6(815, 13876, 32); + } + + public static string ??() + { + return 5[816] ?? 6(816, 13908, 35); + } + + public static string ??() + { + return 5[817] ?? 6(817, 13943, 21); + } + + public static string ??() + { + return 5[818] ?? 6(818, 13964, 23); + } + + public static string ??() + { + return 5[819] ?? 6(819, 13987, 26); + } + + public static string ??() + { + return 5[820] ?? 6(820, 14013, 24); + } + + public static string ??() + { + return 5[821] ?? 6(821, 14037, 20); + } + + public static string ??() + { + return 5[822] ?? 6(822, 14057, 13); + } + + public static string ??() + { + return 5[823] ?? 6(823, 14070, 22); + } + + public static string ??() + { + return 5[824] ?? 6(824, 14092, 25); + } + + public static string ??() + { + return 5[825] ?? 6(825, 14117, 21); + } + + public static string ??() + { + return 5[826] ?? 6(826, 14138, 27); + } + + public static string ??() + { + return 5[827] ?? 6(827, 14165, 25); + } + + public static string ??() + { + return 5[828] ?? 6(828, 14190, 15); + } + + public static string ??() + { + return 5[829] ?? 6(829, 14205, 28); + } + + public static string ??() + { + return 5[830] ?? 6(830, 14233, 26); + } + + public static string ??() + { + return 5[831] ?? 6(831, 14259, 16); + } + + public static string ??() + { + return 5[832] ?? 6(832, 14275, 15); + } + + public static string ??() + { + return 5[833] ?? 6(833, 14290, 16); + } + + public static string ??() + { + return 5[834] ?? 6(834, 14306, 27); + } + + public static string ??() + { + return 5[835] ?? 6(835, 14333, 23); + } + + public static string ??() + { + return 5[836] ?? 6(836, 14356, 29); + } + + public static string ??() + { + return 5[837] ?? 6(837, 14385, 27); + } + + public static string ??() + { + return 5[838] ?? 6(838, 14412, 11); + } + + public static string ??() + { + return 5[839] ?? 6(839, 14423, 9); + } + + public static string ??() + { + return 5[840] ?? 6(840, 14432, 14); + } + + public static string ??() + { + return 5[841] ?? 6(841, 14446, 13); + } + + public static string ??() + { + return 5[842] ?? 6(842, 14459, 41); + } + + public static string ??() + { + return 5[843] ?? 6(843, 14500, 37); + } + + public static string ??() + { + return 5[844] ?? 6(844, 14537, 40); + } + + public static string ??() + { + return 5[845] ?? 6(845, 14577, 12); + } + + public static string ??() + { + return 5[846] ?? 6(846, 14589, 38); + } + + public static string ??() + { + return 5[847] ?? 6(847, 14627, 34); + } + + public static string ??() + { + return 5[848] ?? 6(848, 14661, 45); + } + + public static string ??() + { + return 5[849] ?? 6(849, 14706, 36); + } + + public static string ??() + { + return 5[850] ?? 6(850, 14742, 32); + } + + public static string ??() + { + return 5[851] ?? 6(851, 14774, 33); + } + + public static string ??() + { + return 5[852] ?? 6(852, 14807, 32); + } + + public static string ??() + { + return 5[853] ?? 6(853, 14839, 37); + } + + public static string ??() + { + return 5[854] ?? 6(854, 14876, 42); + } + + public static string ??() + { + return 5[855] ?? 6(855, 14918, 42); + } + + public static string ??() + { + return 5[856] ?? 6(856, 14960, 46); + } + + public static string ??() + { + return 5[857] ?? 6(857, 15006, 35); + } + + public static string ??() + { + return 5[858] ?? 6(858, 15041, 38); + } + + public static string ??() + { + return 5[859] ?? 6(859, 15079, 39); + } + + public static string ??() + { + return 5[860] ?? 6(860, 15118, 42); + } + + public static string ??() + { + return 5[861] ?? 6(861, 15160, 36); + } + + public static string ??() + { + return 5[862] ?? 6(862, 15196, 46); + } + + public static string ??() + { + return 5[863] ?? 6(863, 15242, 34); + } + + public static string ??() + { + return 5[864] ?? 6(864, 15276, 23); + } + + public static string ??() + { + return 5[865] ?? 6(865, 15299, 40); + } + + public static string ??() + { + return 5[866] ?? 6(866, 15339, 27); + } + + public static string ??() + { + return 5[867] ?? 6(867, 15366, 33); + } + + public static string ??() + { + return 5[868] ?? 6(868, 15399, 33); + } + + public static string ??() + { + return 5[869] ?? 6(869, 15432, 41); + } + + public static string ??() + { + return 5[870] ?? 6(870, 15473, 22); + } + + public static string ??() + { + return 5[871] ?? 6(871, 15495, 15); + } + + public static string ??() + { + return 5[872] ?? 6(872, 15510, 39); + } + + public static string ??() + { + return 5[873] ?? 6(873, 15549, 34); + } + + public static string ??() + { + return 5[874] ?? 6(874, 15583, 34); + } + + public static string ??() + { + return 5[875] ?? 6(875, 15617, 21); + } + + public static string ??() + { + return 5[876] ?? 6(876, 15638, 37); + } + + public static string ??() + { + return 5[877] ?? 6(877, 15675, 40); + } + + public static string ??() + { + return 5[878] ?? 6(878, 15715, 35); + } + + public static string ??() + { + return 5[879] ?? 6(879, 15750, 33); + } + + public static string ??() + { + return 5[880] ?? 6(880, 15783, 38); + } + + public static string ??() + { + return 5[881] ?? 6(881, 15821, 36); + } + + public static string ??() + { + return 5[882] ?? 6(882, 15857, 41); + } + + public static string ??() + { + return 5[883] ?? 6(883, 15898, 42); + } + + public static string ??() + { + return 5[884] ?? 6(884, 15940, 38); + } + + public static string ??() + { + return 5[885] ?? 6(885, 15978, 43); + } + + public static string ??() + { + return 5[886] ?? 6(886, 16021, 7); + } + + public static string ??() + { + return 5[887] ?? 6(887, 16028, 17); + } + + public static string ??() + { + return 5[888] ?? 6(888, 16045, 16); + } + + public static string ??() + { + return 5[889] ?? 6(889, 16061, 9); + } + + public static string ??() + { + return 5[890] ?? 6(890, 16070, 21); + } + + public static string ??() + { + return 5[891] ?? 6(891, 16091, 26); + } + + public static string ??() + { + return 5[892] ?? 6(892, 16117, 31); + } + + public static string ??() + { + return 5[893] ?? 6(893, 16148, 11); + } + + public static string ??() + { + return 5[894] ?? 6(894, 16159, 23); + } + + public static string ??() + { + return 5[895] ?? 6(895, 16182, 28); + } + + public static string ??() + { + return 5[896] ?? 6(896, 16210, 16); + } + + public static string ??() + { + return 5[897] ?? 6(897, 16226, 23); + } + + public static string ??() + { + return 5[898] ?? 6(898, 16249, 23); + } + + public static string ??() + { + return 5[899] ?? 6(899, 16272, 22); + } + + public static string ??() + { + return 5[900] ?? 6(900, 16294, 20); + } + + public static string ??() + { + return 5[901] ?? 6(901, 16314, 17); + } + + public static string ??() + { + return 5[902] ?? 6(902, 16331, 25); + } + + public static string ??() + { + return 5[903] ?? 6(903, 16356, 25); + } + + public static string ??() + { + return 5[904] ?? 6(904, 16381, 35); + } + + public static string ??() + { + return 5[905] ?? 6(905, 16416, 31); + } + + public static string ??() + { + return 5[906] ?? 6(906, 16447, 17); + } + + public static string ??() + { + return 5[907] ?? 6(907, 16464, 17); + } + + public static string ??() + { + return 5[908] ?? 6(908, 16481, 15); + } + + public static string ??() + { + return 5[909] ?? 6(909, 16496, 17); + } + + public static string ??() + { + return 5[910] ?? 6(910, 16513, 15); + } + + public static string ??() + { + return 5[911] ?? 6(911, 16528, 25); + } + + public static string ??() + { + return 5[912] ?? 6(912, 16553, 24); + } + + public static string ??() + { + return 5[913] ?? 6(913, 16577, 9); + } + + public static string ??() + { + return 5[914] ?? 6(914, 16586, 26); + } + + public static string ??() + { + return 5[915] ?? 6(915, 16612, 19); + } + + public static string ??() + { + return 5[916] ?? 6(916, 16631, 16); + } + + public static string ??() + { + return 5[917] ?? 6(917, 16647, 31); + } + + public static string ??() + { + return 5[918] ?? 6(918, 16678, 31); + } + + public static string ??() + { + return 5[919] ?? 6(919, 16709, 32); + } + + public static string ??() + { + return 5[920] ?? 6(920, 16741, 22); + } + + public static string ??() + { + return 5[921] ?? 6(921, 16763, 15); + } + + public static string ??() + { + return 5[922] ?? 6(922, 16778, 20); + } + + public static string ??() + { + return 5[923] ?? 6(923, 16798, 21); + } + + public static string ??() + { + return 5[924] ?? 6(924, 16819, 20); + } + + public static string ??() + { + return 5[925] ?? 6(925, 16839, 19); + } + + public static string ??() + { + return 5[926] ?? 6(926, 16858, 20); + } + + public static string ??() + { + return 5[927] ?? 6(927, 16878, 28); + } + + public static string ??() + { + return 5[928] ?? 6(928, 16906, 32); + } + + public static string ??() + { + return 5[929] ?? 6(929, 16938, 6); + } + + public static string ??() + { + return 5[930] ?? 6(930, 16944, 64); + } + + public static string ??() + { + return 5[931] ?? 6(931, 17008, 15); + } + + public static string ??() + { + return 5[932] ?? 6(932, 17023, 23); + } + + public static string ??() + { + return 5[933] ?? 6(933, 17046, 17); + } + + public static string ??() + { + return 5[934] ?? 6(934, 17063, 54); + } + + public static string ??() + { + return 5[935] ?? 6(935, 17117, 56); + } + + public static string ??() + { + return 5[936] ?? 6(936, 17173, 36); + } + + public static string ??() + { + return 5[937] ?? 6(937, 17209, 37); + } + + public static string ??() + { + return 5[938] ?? 6(938, 17246, 39); + } + + public static string ??() + { + return 5[939] ?? 6(939, 17285, 5); + } + + public static string ??() + { + return 5[940] ?? 6(940, 17290, 9); + } + + public static string ??() + { + return 5[941] ?? 6(941, 17299, 10); + } + + public static string ??() + { + return 5[942] ?? 6(942, 17309, 13); + } + + public static string ??() + { + return 5[943] ?? 6(943, 17322, 17); + } + + public static string ??() + { + return 5[944] ?? 6(944, 17339, 20); + } + + public static string ??() + { + return 5[945] ?? 6(945, 17359, 32); + } + + public static string ??() + { + return 5[946] ?? 6(946, 17391, 3); + } + + public static string ??() + { + return 5[947] ?? 6(947, 17394, 51); + } + + public static string ??() + { + return 5[948] ?? 6(948, 17445, 1); + } + + public static string ??() + { + return 5[949] ?? 6(949, 17446, 30); + } + + public static string ??() + { + return 5[950] ?? 6(950, 17476, 52); + } + + public static string ??() + { + return 5[951] ?? 6(951, 17528, 25); + } + + public static string ??() + { + return 5[952] ?? 6(952, 17553, 26); + } + + public static string ??() + { + return 5[953] ?? 6(953, 17579, 40); + } + + public static string ??() + { + return 5[954] ?? 6(954, 17619, 40); + } + + public static string ??() + { + return 5[955] ?? 6(955, 17659, 4); + } + + public static string ??() + { + return 5[956] ?? 6(956, 17663, 24); + } + + public static string ??() + { + return 5[957] ?? 6(957, 17687, 12); + } + + public static string ??() + { + return 5[958] ?? 6(958, 17699, 2); + } + + public static string ??() + { + return 5[959] ?? 6(959, 17701, 9); + } + + public static string ??() + { + return 5[960] ?? 6(960, 17710, 9); + } + + public static string ??() + { + return 5[961] ?? 6(961, 17719, 7); + } + + public static string ??() + { + return 5[962] ?? 6(962, 17726, 10); + } + + public static string ??() + { + return 5[963] ?? 6(963, 17736, 8); + } + + public static string ??() + { + return 5[964] ?? 6(964, 17744, 13); + } + + public static string ??() + { + return 5[965] ?? 6(965, 17757, 13); + } + + public static string ??() + { + return 5[966] ?? 6(966, 17770, 7); + } + + public static string ??() + { + return 5[967] ?? 6(967, 17777, 6); + } + + public static string ??() + { + return 5[968] ?? 6(968, 17783, 5); + } + + public static string ??() + { + return 5[969] ?? 6(969, 17788, 10); + } + + public static string ??() + { + return 5[970] ?? 6(970, 17798, 12); + } + + public static string ??() + { + return 5[971] ?? 6(971, 17810, 11); + } + + public static string ??() + { + return 5[972] ?? 6(972, 17821, 22); + } + + public static string ??() + { + return 5[973] ?? 6(973, 17843, 24); + } + + public static string ??() + { + return 5[974] ?? 6(974, 17867, 6); + } + + public static string ??() + { + return 5[975] ?? 6(975, 17873, 7); + } + + public static string ??() + { + return 5[976] ?? 6(976, 17880, 1); + } + + public static string ??() + { + return 5[977] ?? 6(977, 17881, 6); + } + + public static string ??() + { + return 5[978] ?? 6(978, 17887, 11); + } + + public static string ??() + { + return 5[979] ?? 6(979, 17898, 10); + } + + public static string ??() + { + return 5[980] ?? 6(980, 17908, 8); + } + + public static string ??() + { + return 5[981] ?? 6(981, 17916, 4); + } + + public static string ??() + { + return 5[982] ?? 6(982, 17920, 12); + } + + public static string ??() + { + return 5[983] ?? 6(983, 17932, 44); + } + + public static string ??() + { + return 5[984] ?? 6(984, 17976, 6); + } + + public static string ??() + { + return 5[985] ?? 6(985, 17982, 11); + } + + public static string ??() + { + return 5[986] ?? 6(986, 17993, 4); + } + + public static string ??() + { + return 5[987] ?? 6(987, 17997, 7); + } + + public static string ??() + { + return 5[988] ?? 6(988, 18004, 8); + } + + public static string ??() + { + return 5[989] ?? 6(989, 18012, 4); + } + + public static string ??() + { + return 5[990] ?? 6(990, 18016, 9); + } + + public static string ??() + { + return 5[991] ?? 6(991, 18025, 9); + } + + public static string ??() + { + return 5[992] ?? 6(992, 18034, 8); + } + + public static string ??() + { + return 5[993] ?? 6(993, 18042, 4); + } + + public static string ??() + { + return 5[994] ?? 6(994, 18046, 9); + } + + public static string ??() + { + return 5[995] ?? 6(995, 18055, 12); + } + + public static string ??() + { + return 5[996] ?? 6(996, 18067, 18); + } + + public static string ??() + { + return 5[997] ?? 6(997, 18085, 7); + } + + public static string ??() + { + return 5[998] ?? 6(998, 18092, 18); + } + + public static string ??() + { + return 5[999] ?? 6(999, 18110, 13); + } + + public static string ??() + { + return 5[1000] ?? 6(1000, 18123, 2); + } + + public static string ??() + { + return 5[1001] ?? 6(1001, 18125, 38); + } + + public static string ??() + { + return 5[1002] ?? 6(1002, 18163, 16); + } + + public static string ??() + { + return 5[1003] ?? 6(1003, 18179, 14); + } + + public static string ??() + { + return 5[1004] ?? 6(1004, 18193, 20); + } + + public static string ??() + { + return 5[1005] ?? 6(1005, 18213, 4); + } + + public static string ??() + { + return 5[1006] ?? 6(1006, 18217, 13); + } + + public static string ??() + { + return 5[1007] ?? 6(1007, 18230, 4); + } + + public static string ??() + { + return 5[1008] ?? 6(1008, 18234, 2); + } + + public static string ??() + { + return 5[1009] ?? 6(1009, 18236, 2); + } + + public static string ??() + { + return 5[1010] ?? 6(1010, 18238, 5); + } + + public static string ??() + { + return 5[1011] ?? 6(1011, 18243, 8); + } + + public static string ??() + { + return 5[1012] ?? 6(1012, 18251, 16); + } + + public static string ??() + { + return 5[1013] ?? 6(1013, 18267, 8); + } + + public static string ??() + { + return 5[1014] ?? 6(1014, 18275, 6); + } + + public static string ??() + { + return 5[1015] ?? 6(1015, 18281, 10); + } + + public static string ??() + { + return 5[1016] ?? 6(1016, 18291, 18); + } + + public static string ??() + { + return 5[1017] ?? 6(1017, 18309, 5); + } + + public static string ??() + { + return 5[1018] ?? 6(1018, 18314, 16); + } + + public static string ??() + { + return 5[1019] ?? 6(1019, 18330, 10); + } + + public static string ??() + { + return 5[1020] ?? 6(1020, 18340, 18); + } + + public static string ??() + { + return 5[1021] ?? 6(1021, 18358, 2); + } + + public static string ??() + { + return 5[1022] ?? 6(1022, 18360, 3); + } + + public static string ??() + { + return 5[1023] ?? 6(1023, 18363, 12); + } + + public static string ??() + { + return 5[1024] ?? 6(1024, 18375, 10); + } + + public static string ??() + { + return 5[1025] ?? 6(1025, 18385, 11); + } + + public static string ??() + { + return 5[1026] ?? 6(1026, 18396, 17); + } + + public static string ??() + { + return 5[1027] ?? 6(1027, 18413, 8); + } + + public static string ??() + { + return 5[1028] ?? 6(1028, 18421, 8); + } + + public static string ??() + { + return 5[1029] ?? 6(1029, 18429, 9); + } + + public static string ??() + { + return 5[1030] ?? 6(1030, 18438, 22); + } + + public static string ??() + { + return 5[1031] ?? 6(1031, 18460, 17); + } + + public static string ??() + { + return 5[1032] ?? 6(1032, 18477, 14); + } + + public static string ??() + { + return 5[1033] ?? 6(1033, 18491, 28); + } + + public static string ??() + { + return 5[1034] ?? 6(1034, 18519, 19); + } + + public static string ??() + { + return 5[1035] ?? 6(1035, 18538, 132); + } + + public static string ??() + { + return 5[1036] ?? 6(1036, 18670, 20); + } + + public static string ??() + { + return 5[1037] ?? 6(1037, 18690, 24); + } + + public static string ??() + { + return 5[1038] ?? 6(1038, 18714, 22); + } + + public static string ??() + { + return 5[1039] ?? 6(1039, 18736, 17); + } + + public static string ??() + { + return 5[1040] ?? 6(1040, 18753, 19); + } + + public static string ??() + { + return 5[1041] ?? 6(1041, 18772, 24); + } + + public static string ??() + { + return 5[1042] ?? 6(1042, 18796, 18); + } + + public static string ??() + { + return 5[1043] ?? 6(1043, 18814, 16); + } + + public static string ??() + { + return 5[1044] ?? 6(1044, 18830, 20); + } + + public static string ??() + { + return 5[1045] ?? 6(1045, 18850, 27); + } + + public static string ??() + { + return 5[1046] ?? 6(1046, 18877, 18); + } + + public static string ??() + { + return 5[1047] ?? 6(1047, 18895, 17); + } + + public static string ??() + { + return 5[1048] ?? 6(1048, 18912, 29); + } + + public static string ??() + { + return 5[1049] ?? 6(1049, 18941, 26); + } + + public static string ??() + { + return 5[1050] ?? 6(1050, 18967, 22); + } + + public static string ??() + { + return 5[1051] ?? 6(1051, 18989, 10); + } + + public static string ??() + { + return 5[1052] ?? 6(1052, 18999, 18); + } + + public static string ??() + { + return 5[1053] ?? 6(1053, 19017, 14); + } + + public static string ??() + { + return 5[1054] ?? 6(1054, 19031, 23); + } + + public static string ??() + { + return 5[1055] ?? 6(1055, 19054, 23); + } + + public static string ??() + { + return 5[1056] ?? 6(1056, 19077, 9); + } + + public static string ??() + { + return 5[1057] ?? 6(1057, 19086, 54); + } + + public static string ??() + { + return 5[1058] ?? 6(1058, 19140, 36); + } + + public static string ??() + { + return 5[1059] ?? 6(1059, 19176, 58); + } + + public static string ??() + { + return 5[1060] ?? 6(1060, 19234, 15); + } + + public static string ??() + { + return 5[1061] ?? 6(1061, 19249, 25); + } + + public static string ??() + { + return 5[1062] ?? 6(1062, 19274, 28); + } + + public static string ??() + { + return 5[1063] ?? 6(1063, 19302, 17); + } + + public static string ??() + { + return 5[1064] ?? 6(1064, 19319, 7); + } + + public static string ??() + { + return 5[1065] ?? 6(1065, 19326, 9); + } + + public static string ??() + { + return 5[1066] ?? 6(1066, 19335, 13); + } + + public static string ??() + { + return 5[1067] ?? 6(1067, 19348, 13); + } + + public static string ??() + { + return 5[1068] ?? 6(1068, 19361, 10); + } + + public static string ??() + { + return 5[1069] ?? 6(1069, 19371, 11); + } + + public static string ??() + { + return 5[1070] ?? 6(1070, 19382, 12); + } + + public static string ??() + { + return 5[1071] ?? 6(1071, 19394, 9); + } + + public static string ??() + { + return 5[1072] ?? 6(1072, 19403, 45); + } + + public static string ??() + { + return 5[1073] ?? 6(1073, 19448, 4); + } + + public static string ??() + { + return 5[1074] ?? 6(1074, 19452, 19); + } + + public static string ??() + { + return 5[1075] ?? 6(1075, 19471, 12); + } + + public static string ??() + { + return 5[1076] ?? 6(1076, 19483, 18); + } + + public static string ??() + { + return 5[1077] ?? 6(1077, 19501, 13); + } + + public static string ??() + { + return 5[1078] ?? 6(1078, 19514, 17); + } + + public static string ??() + { + return 5[1079] ?? 6(1079, 19531, 13); + } + + public static string ??() + { + return 5[1080] ?? 6(1080, 19544, 17); + } + + public static string ??() + { + return 5[1081] ?? 6(1081, 19561, 29); + } + + public static string ??() + { + return 5[1082] ?? 6(1082, 19590, 27); + } + + public static string ??() + { + return 5[1083] ?? 6(1083, 19617, 14); + } + + public static string ??() + { + return 5[1084] ?? 6(1084, 19631, 18); + } + + public static string ??() + { + return 5[1085] ?? 6(1085, 19649, 25); + } + + public static string ??() + { + return 5[1086] ?? 6(1086, 19674, 34); + } + + public static string ??() + { + return 5[1087] ?? 6(1087, 19708, 13); + } + + public static string ??() + { + return 5[1088] ?? 6(1088, 19721, 21); + } + + public static string ??() + { + return 5[1089] ?? 6(1089, 19742, 47); + } + + public static string ??() + { + return 5[1090] ?? 6(1090, 19789, 8); + } + + public static string ??() + { + return 5[1091] ?? 6(1091, 19797, 7); + } + + public static string ??() + { + return 5[1092] ?? 6(1092, 19804, 5); + } + + public static string ??() + { + return 5[1093] ?? 6(1093, 19809, 10); + } + + public static string ??() + { + return 5[1094] ?? 6(1094, 19819, 4); + } + + public static string ??() + { + return 5[1095] ?? 6(1095, 19823, 7); + } + + public static string ??() + { + return 5[1096] ?? 6(1096, 19830, 8); + } + + public static string ??() + { + return 5[1097] ?? 6(1097, 19838, 12); + } + + public static string ??() + { + return 5[1098] ?? 6(1098, 19850, 2); + } + + public static string ??() + { + return 5[1099] ?? 6(1099, 19852, 4); + } + + public static string ??() + { + return 5[1100] ?? 6(1100, 19856, 30); + } + + public static string ??() + { + return 5[1101] ?? 6(1101, 19886, 8); + } + + public static string ??() + { + return 5[1102] ?? 6(1102, 19894, 16); + } + + public static string ??() + { + return 5[1103] ?? 6(1103, 19910, 18); + } + + public static string ??() + { + return 5[1104] ?? 6(1104, 19928, 12); + } + + public static string ??() + { + return 5[1105] ?? 6(1105, 19940, 14); + } + + public static string ??() + { + return 5[1106] ?? 6(1106, 19954, 6); + } + + public static string ??() + { + return 5[1107] ?? 6(1107, 19960, 5); + } + + public static string ??() + { + return 5[1108] ?? 6(1108, 19965, 49); + } + + public static string ??() + { + return 5[1109] ?? 6(1109, 20014, 48); + } + + public static string ??() + { + return 5[1110] ?? 6(1110, 20062, 52); + } + + public static string ??() + { + return 5[1111] ?? 6(1111, 20114, 51); + } + + public static string ??() + { + return 5[1112] ?? 6(1112, 20165, 54); + } + + public static string ??() + { + return 5[1113] ?? 6(1113, 20219, 53); + } + + public static string ??() + { + return 5[1114] ?? 6(1114, 20272, 44); + } + + public static string ??() + { + return 5[1115] ?? 6(1115, 20316, 42); + } + + public static string ??() + { + return 5[1116] ?? 6(1116, 20358, 13); + } + + public static string ??() + { + return 5[1117] ?? 6(1117, 20371, 17); + } + + public static string ??() + { + return 5[1118] ?? 6(1118, 20388, 26); + } + + public static string ??() + { + return 5[1119] ?? 6(1119, 20414, 15); + } + + public static string ??() + { + return 5[1120] ?? 6(1120, 20429, 29); + } + + public static string ??() + { + return 5[1121] ?? 6(1121, 20458, 15); + } + + public static string ??() + { + return 5[1122] ?? 6(1122, 20473, 10); + } + + public static string ??() + { + return 5[1123] ?? 6(1123, 20483, 11); + } + + public static string ??() + { + return 5[1124] ?? 6(1124, 20494, 15); + } + + public static string ??() + { + return 5[1125] ?? 6(1125, 20509, 12); + } + + public static string ??() + { + return 5[1126] ?? 6(1126, 20521, 6); + } + + public static string ??() + { + return 5[1127] ?? 6(1127, 20527, 9); + } + + public static string ??() + { + return 5[1128] ?? 6(1128, 20536, 11); + } + + public static string ??() + { + return 5[1129] ?? 6(1129, 20547, 30); + } + + public static string ??() + { + return 5[1130] ?? 6(1130, 20577, 37); + } + + public static string ??() + { + return 5[1131] ?? 6(1131, 20614, 10); + } + + public static string ??() + { + return 5[1132] ?? 6(1132, 20624, 48); + } + + public static string ??() + { + return 5[1133] ?? 6(1133, 20672, 13); + } + + public static string ??() + { + return 5[1134] ?? 6(1134, 20685, 49); + } + + public static string ??() + { + return 5[1135] ?? 6(1135, 20734, 14); + } + + public static string ??() + { + return 5[1136] ?? 6(1136, 20748, 38); + } + + public static string ??() + { + return 5[1137] ?? 6(1137, 20786, 7); + } + + public static string ??() + { + return 5[1138] ?? 6(1138, 20793, 23); + } + + public static string ??() + { + return 5[1139] ?? 6(1139, 20816, 32); + } + + public static string ??() + { + return 5[1140] ?? 6(1140, 20848, 30); + } + + public static string ??() + { + return 5[1141] ?? 6(1141, 20878, 11); + } + + public static string ??() + { + return 5[1142] ?? 6(1142, 20889, 24); + } + + public static string ??() + { + return 5[1143] ?? 6(1143, 20913, 31); + } + + public static string ??() + { + return 5[1144] ?? 6(1144, 20944, 97); + } + + public static string ??() + { + return 5[1145] ?? 6(1145, 21041, 10); + } + + public static string ??() + { + return 5[1146] ?? 6(1146, 21051, 17); + } + + public static string ??() + { + return 5[1147] ?? 6(1147, 21068, 34); + } + + public static string ??() + { + return 5[1148] ?? 6(1148, 21102, 107); + } + + public static string ??() + { + return 5[1149] ?? 6(1149, 21209, 11); + } + + public static string ??() + { + return 5[1150] ?? 6(1150, 21220, 7); + } + + public static string ??() + { + return 5[1151] ?? 6(1151, 21227, 12); + } + + public static string ??() + { + return 5[1152] ?? 6(1152, 21239, 12); + } + + public static string ??() + { + return 5[1153] ?? 6(1153, 21251, 11); + } + + public static string ??() + { + return 5[1154] ?? 6(1154, 21262, 100); + } + + public static string ??() + { + return 5[1155] ?? 6(1155, 21362, 22); + } + + public static string ??() + { + return 5[1156] ?? 6(1156, 21384, 5); + } + + public static string ??() + { + return 5[1157] ?? 6(1157, 21389, 14); + } + + public static string ??() + { + return 5[1158] ?? 6(1158, 21403, 16); + } + + public static string ??() + { + return 5[1159] ?? 6(1159, 21419, 13); + } + + public static string ??() + { + return 5[1160] ?? 6(1160, 21432, 4); + } + + public static string ??() + { + return 5[1161] ?? 6(1161, 21436, 9); + } + + public static string ??() + { + return 5[1162] ?? 6(1162, 21445, 7); + } + + public static string ??() + { + return 5[1163] ?? 6(1163, 21452, 6); + } + + public static string ??() + { + return 5[1164] ?? 6(1164, 21458, 7); + } + + public static string ??() + { + return 5[1165] ?? 6(1165, 21465, 8); + } + + public static string ??() + { + return 5[1166] ?? 6(1166, 21473, 18); + } + + public static string ??() + { + return 5[1167] ?? 6(1167, 21491, 5); + } + + public static string ??() + { + return 5[1168] ?? 6(1168, 21496, 15); + } + + public static string ??() + { + return 5[1169] ?? 6(1169, 21511, 7); + } + + public static string ??() + { + return 5[1170] ?? 6(1170, 21518, 18); + } + + public static string ??() + { + return 5[1171] ?? 6(1171, 21536, 8); + } + + public static string ??() + { + return 5[1172] ?? 6(1172, 21544, 8); + } + + public static string ??() + { + return 5[1173] ?? 6(1173, 21552, 13); + } + + public static string ??() + { + return 5[1174] ?? 6(1174, 21565, 17); + } + + public static string ??() + { + return 5[1175] ?? 6(1175, 21582, 111); + } + + public static string ??() + { + return 5[1176] ?? 6(1176, 21693, 114); + } + + public static string ??() + { + return 5[1177] ?? 6(1177, 21807, 165); + } + + public static string ??() + { + return 5[1178] ?? 6(1178, 21972, 8); + } + + public static string ??() + { + return 5[1179] ?? 6(1179, 21980, 4); + } + + public static string ??() + { + return 5[1180] ?? 6(1180, 21984, 10); + } + + public static string ??() + { + return 5[1181] ?? 6(1181, 21994, 11); + } + + public static string ??() + { + return 5[1182] ?? 6(1182, 22005, 4); + } + + public static string ??() + { + return 5[1183] ?? 6(1183, 22009, 8); + } + + public static string ??() + { + return 5[1184] ?? 6(1184, 22017, 9); + } + + public static string ??() + { + return 5[1185] ?? 6(1185, 22026, 2); + } + + public static string ??() + { + return 5[1186] ?? 6(1186, 22028, 12); + } + + public static string ??() + { + return 5[1187] ?? 6(1187, 22040, 10); + } + + public static string ??() + { + return 5[1188] ?? 6(1188, 22050, 8); + } + + public static string ??() + { + return 5[1189] ?? 6(1189, 22058, 11); + } + + public static string ??() + { + return 5[1190] ?? 6(1190, 22069, 8); + } + + public static string ??() + { + return 5[1191] ?? 6(1191, 22077, 12); + } + + public static string ??() + { + return 5[1192] ?? 6(1192, 22089, 8); + } + + public static string ??() + { + return 5[1193] ?? 6(1193, 22097, 8); + } + + public static string ??() + { + return 5[1194] ?? 6(1194, 22105, 17); + } + + public static string ??() + { + return 5[1195] ?? 6(1195, 22122, 11); + } + + public static string ??() + { + return 5[1196] ?? 6(1196, 22133, 43); + } + + public static string ??() + { + return 5[1197] ?? 6(1197, 22176, 21); + } + + public static string ??() + { + return 5[1198] ?? 6(1198, 22197, 5); + } + + public static string ??() + { + return 5[1199] ?? 6(1199, 22202, 5); + } + + public static string ??() + { + return 5[1200] ?? 6(1200, 22207, 8); + } + + public static string ??() + { + return 5[1201] ?? 6(1201, 22215, 46); + } + + public static string ??() + { + return 5[1202] ?? 6(1202, 22261, 46); + } + + public static string ??() + { + return 5[1203] ?? 6(1203, 22307, 11); + } + + public static string ??() + { + return 5[1204] ?? 6(1204, 22318, 4); + } + + public static string ??() + { + return 5[1205] ?? 6(1205, 22322, 45); + } + + public static string ??() + { + return 5[1206] ?? 6(1206, 22367, 4); + } + + public static string ??() + { + return 5[1207] ?? 6(1207, 22371, 23); + } + + public static string ??() + { + return 5[1208] ?? 6(1208, 22394, 27); + } + + public static string ??() + { + return 5[1209] ?? 6(1209, 22421, 36); + } + + public static string ??() + { + return 5[1210] ?? 6(1210, 22457, 45); + } + + public static string ??() + { + return 5[1211] ?? 6(1211, 22502, 3); + } + + public static string ??() + { + return 5[1212] ?? 6(1212, 22505, 28); + } + + public static string ??() + { + return 5[1213] ?? 6(1213, 22533, 16); + } + + public static string ??() + { + return 5[1214] ?? 6(1214, 22549, 19); + } + + public static string ??() + { + return 5[1215] ?? 6(1215, 22568, 124); + } + + public static string ??() + { + return 5[1216] ?? 6(1216, 22692, 1); + } + + public static string ??() + { + return 5[1217] ?? 6(1217, 22693, 1); + } + + public static string ??() + { + return 5[1218] ?? 6(1218, 22694, 1); + } + + public static string ??() + { + return 5[1219] ?? 6(1219, 22695, 1); + } + + public static string ??() + { + return 5[1220] ?? 6(1220, 22696, 1); + } + + public static string ??() + { + return 5[1221] ?? 6(1221, 22697, 10); + } + + public static string ??() + { + return 5[1222] ?? 6(1222, 22707, 16); + } + + public static string ??() + { + return 5[1223] ?? 6(1223, 22723, 16); + } + + public static string ??() + { + return 5[1224] ?? 6(1224, 22739, 133); + } + + public static string ??() + { + return 5[1225] ?? 6(1225, 22872, 15); + } + + public static string ??() + { + return 5[1226] ?? 6(1226, 22887, 14); + } + + public static string ??() + { + return 5[1227] ?? 6(1227, 22901, 16); + } + + public static string ??() + { + return 5[1228] ?? 6(1228, 22917, 9); + } + + public static string ??() + { + return 5[1229] ?? 6(1229, 22926, 65); + } + + public static string ??() + { + return 5[1230] ?? 6(1230, 22991, 31); + } + + public static string ??() + { + return 5[1231] ?? 6(1231, 23022, 48); + } + + public static string ??() + { + return 5[1232] ?? 6(1232, 23070, 8); + } + + public static string ??() + { + return 5[1233] ?? 6(1233, 23078, 70); + } + + public static string ??() + { + return 5[1234] ?? 6(1234, 23148, 36); + } + + public static string ??() + { + return 5[1235] ?? 6(1235, 23184, 9); + } + + public static string ??() + { + return 5[1236] ?? 6(1236, 23193, 26); + } + + public static string ??() + { + return 5[1237] ?? 6(1237, 23219, 4); + } + + public static string ??() + { + return 5[1238] ?? 6(1238, 23223, 14); + } + + public static string ??() + { + return 5[1239] ?? 6(1239, 23237, 30); + } + + public static string ??() + { + return 5[1240] ?? 6(1240, 23267, 4); + } + + public static string ??() + { + return 5[1241] ?? 6(1241, 23271, 2); + } + + public static string ??() + { + return 5[1242] ?? 6(1242, 23273, 30); + } + + public static string ??() + { + return 5[1243] ?? 6(1243, 23303, 11); + } + + public static string ??() + { + return 5[1244] ?? 6(1244, 23314, 11); + } + + public static string ??() + { + return 5[1245] ?? 6(1245, 23325, 21); + } + + public static string ??() + { + return 5[1246] ?? 6(1246, 23346, 14); + } + + public static string ??() + { + return 5[1247] ?? 6(1247, 23360, 8); + } + + public static string ??() + { + return 5[1248] ?? 6(1248, 23368, 14); + } + + public static string ??() + { + return 5[1249] ?? 6(1249, 23382, 8); + } + + public static string ??() + { + return 5[1250] ?? 6(1250, 23390, 12); + } + + public static string ??() + { + return 5[1251] ?? 6(1251, 23402, 14); + } + + public static string ??() + { + return 5[1252] ?? 6(1252, 23416, 12); + } + + public static string ??() + { + return 5[1253] ?? 6(1253, 23428, 17); + } + + public static string ??() + { + return 5[1254] ?? 6(1254, 23445, 19); + } + + public static string ??() + { + return 5[1255] ?? 6(1255, 23464, 16); + } + + public static string ??() + { + return 5[1256] ?? 6(1256, 23480, 20); + } + + public static string ??() + { + return 5[1257] ?? 6(1257, 23500, 9); + } + + public static string ??() + { + return 5[1258] ?? 6(1258, 23509, 11); + } + + public static string ??() + { + return 5[1259] ?? 6(1259, 23520, 14); + } + + public static string ??() + { + return 5[1260] ?? 6(1260, 23534, 15); + } + + public static string ??() + { + return 5[1261] ?? 6(1261, 23549, 15); + } + + public static string ??() + { + return 5[1262] ?? 6(1262, 23564, 71); + } + + public static string ??() + { + return 5[1263] ?? 6(1263, 23635, 78); + } + + public static string ??() + { + return 5[1264] ?? 6(1264, 23713, 80); + } + + public static string ??() + { + return 5[1265] ?? 6(1265, 23793, 77); + } + + public static string ??() + { + return 5[1266] ?? 6(1266, 23870, 80); + } + + public static string ??() + { + return 5[1267] ?? 6(1267, 23950, 4); + } + + public static string ??() + { + return 5[1268] ?? 6(1268, 23954, 93); + } + + public static string ??() + { + return 5[1269] ?? 6(1269, 24047, 17); + } + + public static string ??() + { + return 5[1270] ?? 6(1270, 24064, 9); + } + + public static string ??() + { + return 5[1271] ?? 6(1271, 24073, 12); + } + + public static string ??() + { + return 5[1272] ?? 6(1272, 24085, 9); + } + + public static string ??() + { + return 5[1273] ?? 6(1273, 24094, 43); + } + + public static string ??() + { + return 5[1274] ?? 6(1274, 24137, 29); + } + + public static string ??() + { + return 5[1275] ?? 6(1275, 24166, 38); + } + + public static string ??() + { + return 5[1276] ?? 6(1276, 24204, 22); + } + + public static string ??() + { + return 5[1277] ?? 6(1277, 24226, 127); + } + + public static string ??() + { + return 5[1278] ?? 6(1278, 24353, 39); + } + + public static string ??() + { + return 5[1279] ?? 6(1279, 24392, 29); + } + + public static string ??() + { + return 5[1280] ?? 6(1280, 24421, 30); + } + + public static string ??() + { + return 5[1281] ?? 6(1281, 24451, 153); + } + + public static string ??() + { + return 5[1282] ?? 6(1282, 24604, 53); + } + + public static string ??() + { + return 5[1283] ?? 6(1283, 24657, 21); + } + + public static string ??() + { + return 5[1284] ?? 6(1284, 24678, 38); + } + + public static string ??() + { + return 5[1285] ?? 6(1285, 24716, 15); + } + + public static string ??() + { + return 5[1286] ?? 6(1286, 24731, 21); + } + + public static string ??() + { + return 5[1287] ?? 6(1287, 24752, 38); + } + + public static string ??() + { + return 5[1288] ?? 6(1288, 24790, 2); + } + + public static string ??() + { + return 5[1289] ?? 6(1289, 24792, 21); + } + + public static string ??() + { + return 5[1290] ?? 6(1290, 24813, 32); + } + + public static string ??() + { + return 5[1291] ?? 6(1291, 24845, 10); + } + + public static string ??() + { + return 5[1292] ?? 6(1292, 24855, 4); + } + + public static string ??() + { + return 5[1293] ?? 6(1293, 24859, 1); + } + + public static string ??() + { + return 5[1294] ?? 6(1294, 24860, 20); + } + + public static string ??() + { + return 5[1295] ?? 6(1295, 24880, 24); + } + + public static string ??() + { + return 5[1296] ?? 6(1296, 24904, 5); + } + + public static string ??() + { + return 5[1297] ?? 6(1297, 24909, 9); + } + + public static string ??() + { + return 5[1298] ?? 6(1298, 24918, 11); + } + + public static string ??() + { + return 5[1299] ?? 6(1299, 24929, 47); + } + + public static string ??() + { + return 5[1300] ?? 6(1300, 24976, 18); + } + + public static string ??() + { + return 5[1301] ?? 6(1301, 24994, 36); + } + + public static string ??() + { + return 5[1302] ?? 6(1302, 25030, 20); + } + + public static string ??() + { + return 5[1303] ?? 6(1303, 25050, 39); + } + + public static string ??() + { + return 5[1304] ?? 6(1304, 25089, 23); + } + + public static string ??() + { + return 5[1305] ?? 6(1305, 25112, 48); + } + + public static string ??() + { + return 5[1306] ?? 6(1306, 25160, 23); + } + + public static string ??() + { + return 5[1307] ?? 6(1307, 25183, 41); + } + + public static string ??() + { + return 5[1308] ?? 6(1308, 25224, 11); + } + + public static string ??() + { + return 5[1309] ?? 6(1309, 25235, 39); + } + + public static string ??() + { + return 5[1310] ?? 6(1310, 25274, 9); + } + + public static string ??() + { + return 5[1311] ?? 6(1311, 25283, 9); + } + + public static string ??() + { + return 5[1312] ?? 6(1312, 25292, 6); + } + + public static string ??() + { + return 5[1313] ?? 6(1313, 25298, 6); + } + + public static string ??() + { + return 5[1314] ?? 6(1314, 25304, 34); + } + + public static string ??() + { + return 5[1315] ?? 6(1315, 25338, 36); + } + + public static string ??() + { + return 5[1316] ?? 6(1316, 25374, 2); + } + + public static string ??() + { + return 5[1317] ?? 6(1317, 25376, 10); + } + + public static string ??() + { + return 5[1318] ?? 6(1318, 25386, 12); + } + + public static string ??() + { + return 5[1319] ?? 6(1319, 25398, 24); + } + + public static string ??() + { + return 5[1320] ?? 6(1320, 25422, 1); + } + + public static string ??() + { + return 5[1321] ?? 6(1321, 25423, 66); + } + + public static string ??() + { + return 5[1322] ?? 6(1322, 25489, 8); + } + + public static string ??() + { + return 5[1323] ?? 6(1323, 25497, 11); + } + + public static string ??() + { + return 5[1324] ?? 6(1324, 25508, 6); + } + + public static string ??() + { + return 5[1325] ?? 6(1325, 25514, 9); + } + + public static string ??() + { + return 5[1326] ?? 6(1326, 25523, 4); + } + + public static string ??() + { + return 5[1327] ?? 6(1327, 25527, 6); + } + + public static string ??() + { + return 5[1328] ?? 6(1328, 25533, 25); + } + + public static string ??() + { + return 5[1329] ?? 6(1329, 25558, 5); + } + + public static string ??() + { + return 5[1330] ?? 6(1330, 25563, 7); + } + + public static string ??() + { + return 5[1331] ?? 6(1331, 25570, 15); + } + + public static string ??() + { + return 5[1332] ?? 6(1332, 25585, 11); + } + + public static string ??() + { + return 5[1333] ?? 6(1333, 25596, 18); + } + + public static string ??() + { + return 5[1334] ?? 6(1334, 25614, 6); + } + + public static string ??() + { + return 5[1335] ?? 6(1335, 25620, 10); + } + + public static string ??() + { + return 5[1336] ?? 6(1336, 25630, 24); + } + + public static string ??() + { + return 5[1337] ?? 6(1337, 25654, 18); + } + + public static string ??() + { + return 5[1338] ?? 6(1338, 25672, 14); + } + + public static string ??() + { + return 5[1339] ?? 6(1339, 25686, 19); + } + + public static string ??() + { + return 5[1340] ?? 6(1340, 25705, 11); + } + + public static string ??() + { + return 5[1341] ?? 6(1341, 25716, 2); + } + + public static string ??() + { + return 5[1342] ?? 6(1342, 25718, 15); + } + + public static string ??() + { + return 5[1343] ?? 6(1343, 25733, 7); + } + + public static string ??() + { + return 5[1344] ?? 6(1344, 25740, 10); + } + + public static string ??() + { + return 5[1345] ?? 6(1345, 25750, 9); + } + + public static string ??() + { + return 5[1346] ?? 6(1346, 25759, 25); + } + + public static string ??() + { + return 5[1347] ?? 6(1347, 25784, 26); + } + + public static string ??() + { + return 5[1348] ?? 6(1348, 25810, 10); + } + + public static string ??() + { + return 5[1349] ?? 6(1349, 25820, 10); + } + + public static string ??() + { + return 5[1350] ?? 6(1350, 25830, 15); + } + + public static string ??() + { + return 5[1351] ?? 6(1351, 25845, 15); + } + + public static string ??() + { + return 5[1352] ?? 6(1352, 25860, 4); + } + + public static string ??() + { + return 5[1353] ?? 6(1353, 25864, 7); + } + + public static string ??() + { + return 5[1354] ?? 6(1354, 25871, 13); + } + + public static string ??() + { + return 5[1355] ?? 6(1355, 25884, 9); + } + + public static string ??() + { + return 5[1356] ?? 6(1356, 25893, 23); + } + + public static string ??() + { + return 5[1357] ?? 6(1357, 25916, 9); + } + + public static string ??() + { + return 5[1358] ?? 6(1358, 25925, 9); + } + + public static string ??() + { + return 5[1359] ?? 6(1359, 25934, 15); + } + + public static string ??() + { + return 5[1360] ?? 6(1360, 25949, 14); + } + + public static string ??() + { + return 5[1361] ?? 6(1361, 25963, 5); + } + + public static string ??() + { + return 5[1362] ?? 6(1362, 25968, 5); + } + + public static string ??() + { + return 5[1363] ?? 6(1363, 25973, 5); + } + + public static string ??() + { + return 5[1364] ?? 6(1364, 25978, 6); + } + + public static string ??() + { + return 5[1365] ?? 6(1365, 25984, 13); + } + + public static string ??() + { + return 5[1366] ?? 6(1366, 25997, 13); + } + + public static string ??() + { + return 5[1367] ?? 6(1367, 26010, 14); + } + + public static string ??() + { + return 5[1368] ?? 6(1368, 26024, 13); + } + + public static string ??() + { + return 5[1369] ?? 6(1369, 26037, 13); + } + + public static string ??() + { + return 5[1370] ?? 6(1370, 26050, 7); + } + + public static string ??() + { + return 5[1371] ?? 6(1371, 26057, 13); + } + + public static string ??() + { + return 5[1372] ?? 6(1372, 26070, 9); + } + + public static string ??() + { + return 5[1373] ?? 6(1373, 26079, 9); + } + + public static string ??() + { + return 5[1374] ?? 6(1374, 26088, 4); + } + + public static string ??() + { + return 5[1375] ?? 6(1375, 26092, 2); + } + + public static string ??() + { + return 5[1376] ?? 6(1376, 26094, 14); + } + + public static string ??() + { + return 5[1377] ?? 6(1377, 26108, 5); + } + + public static string ??() + { + return 5[1378] ?? 6(1378, 26113, 9); + } + + public static string ??() + { + return 5[1379] ?? 6(1379, 26122, 9); + } + + public static string ??() + { + return 5[1380] ?? 6(1380, 26131, 16); + } + + public static string ??() + { + return 5[1381] ?? 6(1381, 26147, 21); + } + + public static string ??() + { + return 5[1382] ?? 6(1382, 26168, 15); + } + + public static string ??() + { + return 5[1383] ?? 6(1383, 26183, 5); + } + + public static string ??() + { + return 5[1384] ?? 6(1384, 26188, 11); + } + + public static string ??() + { + return 5[1385] ?? 6(1385, 26199, 12); + } + + public static string ??() + { + return 5[1386] ?? 6(1386, 26211, 11); + } + + public static string ??() + { + return 5[1387] ?? 6(1387, 26222, 9); + } + + public static string ??() + { + return 5[1388] ?? 6(1388, 26231, 4); + } + + public static string ??() + { + return 5[1389] ?? 6(1389, 26235, 12); + } + + public static string ??() + { + return 5[1390] ?? 6(1390, 26247, 9); + } + + public static string ??() + { + return 5[1391] ?? 6(1391, 26256, 8); + } + + public static string ??() + { + return 5[1392] ?? 6(1392, 26264, 11); + } + + public static string ??() + { + return 5[1393] ?? 6(1393, 26275, 21); + } + + public static string ??() + { + return 5[1394] ?? 6(1394, 26296, 45); + } + + public static string ??() + { + return 5[1395] ?? 6(1395, 26341, 6); + } + + public static string ??() + { + return 5[1396] ?? 6(1396, 26347, 58); + } + + public static string ??() + { + return 5[1397] ?? 6(1397, 26405, 11); + } + + public static string ??() + { + return 5[1398] ?? 6(1398, 26416, 53); + } + + public static string ??() + { + return 5[1399] ?? 6(1399, 26469, 7); + } + + public static string ??() + { + return 5[1400] ?? 6(1400, 26476, 8); + } + + public static string ??() + { + return 5[1401] ?? 6(1401, 26484, 3); + } + + public static string ??() + { + return 5[1402] ?? 6(1402, 26487, 7); + } + + public static string ??() + { + return 5[1403] ?? 6(1403, 26494, 150); + } + + public static string ??() + { + return 5[1404] ?? 6(1404, 26644, 6); + } + + public static string ??() + { + return 5[1405] ?? 6(1405, 26650, 5); + } + + public static string ??() + { + return 5[1406] ?? 6(1406, 26655, 12); + } + + public static string ??() + { + return 5[1407] ?? 6(1407, 26667, 57); + } + + public static string ??() + { + return 5[1408] ?? 6(1408, 26724, 56); + } + + public static string ??() + { + return 5[1409] ?? 6(1409, 26780, 11); + } + + public static string ??() + { + return 5[1410] ?? 6(1410, 26791, 9); + } + + public static string ??() + { + return 5[1411] ?? 6(1411, 26800, 7); + } + + public static string ??() + { + return 5[1412] ?? 6(1412, 26807, 23); + } + + public static string ??() + { + return 5[1413] ?? 6(1413, 26830, 9); + } + + public static string ??() + { + return 5[1414] ?? 6(1414, 26839, 8); + } + + public static string ??() + { + return 5[1415] ?? 6(1415, 26847, 13); + } + + public static string ??() + { + return 5[1416] ?? 6(1416, 26860, 8); + } + + public static string ??() + { + return 5[1417] ?? 6(1417, 26868, 8); + } + + public static string ??() + { + return 5[1418] ?? 6(1418, 26876, 14); + } + + public static string ??() + { + return 5[1419] ?? 6(1419, 26890, 19); + } + + public static string ??() + { + return 5[1420] ?? 6(1420, 26909, 19); + } + + public static string ??() + { + return 5[1421] ?? 6(1421, 26928, 17); + } + + public static string ??() + { + return 5[1422] ?? 6(1422, 26945, 20); + } + + public static string ??() + { + return 5[1423] ?? 6(1423, 26965, 21); + } + + public static string ??() + { + return 5[1424] ?? 6(1424, 26986, 21); + } + + public static string ??() + { + return 5[1425] ?? 6(1425, 27007, 29); + } + + public static string ??() + { + return 5[1426] ?? 6(1426, 27036, 27); + } + + public static string ??() + { + return 5[1427] ?? 6(1427, 27063, 58); + } + + public static string ??() + { + return 5[1428] ?? 6(1428, 27121, 35); + } + + public static string ??() + { + return 5[1429] ?? 6(1429, 27156, 25); + } + + public static string ??() + { + return 5[1430] ?? 6(1430, 27181, 27); + } + + public static string ??() + { + return 5[1431] ?? 6(1431, 27208, 27); + } + + public static string ??() + { + return 5[1432] ?? 6(1432, 27235, 24); + } + + public static string ??() + { + return 5[1433] ?? 6(1433, 27259, 33); + } + + public static string ??() + { + return 5[1434] ?? 6(1434, 27292, 19); + } + + public static string ??() + { + return 5[1435] ?? 6(1435, 27311, 47); + } + + public static string ??() + { + return 5[1436] ?? 6(1436, 27358, 47); + } + + public static string ??() + { + return 5[1437] ?? 6(1437, 27405, 40); + } + + public static string ??() + { + return 5[1438] ?? 6(1438, 27445, 42); + } + + public static string ??() + { + return 5[1439] ?? 6(1439, 27487, 34); + } + + public static string ??() + { + return 5[1440] ?? 6(1440, 27521, 27); + } + + public static string ??() + { + return 5[1441] ?? 6(1441, 27548, 39); + } + + public static string ??() + { + return 5[1442] ?? 6(1442, 27587, 32); + } + + public static string ??() + { + return 5[1443] ?? 6(1443, 27619, 43); + } + + public static string ??() + { + return 5[1444] ?? 6(1444, 27662, 28); + } + + public static string ??() + { + return 5[1445] ?? 6(1445, 27690, 35); + } + + public static string ??() + { + return 5[1446] ?? 6(1446, 27725, 7); + } + + public static string ??() + { + return 5[1447] ?? 6(1447, 27732, 12); + } + + public static string ??() + { + return 5[1448] ?? 6(1448, 27744, 34); + } + + public static string ??() + { + return 5[1449] ?? 6(1449, 27778, 6); + } + + public static string ??() + { + return 5[1450] ?? 6(1450, 27784, 17); + } + + public static string ??() + { + return 5[1451] ?? 6(1451, 27801, 39); + } + + public static string ??() + { + return 5[1452] ?? 6(1452, 27840, 33); + } + + public static string ??() + { + return 5[1453] ?? 6(1453, 27873, 31); + } + + public static string ??() + { + return 5[1454] ?? 6(1454, 27904, 6); + } + + public static string ??() + { + return 5[1455] ?? 6(1455, 27910, 7); + } + + public static string ??() + { + return 5[1456] ?? 6(1456, 27917, 14); + } + + public static string ??() + { + return 5[1457] ?? 6(1457, 27931, 14); + } + + public static string ??() + { + return 5[1458] ?? 6(1458, 27945, 17); + } + + public static string ??() + { + return 5[1459] ?? 6(1459, 27962, 36); + } + + public static string ??() + { + return 5[1460] ?? 6(1460, 27998, 53); + } + + public static string ??() + { + return 5[1461] ?? 6(1461, 28051, 23); + } + + public static string ??() + { + return 5[1462] ?? 6(1462, 28074, 47); + } + + public static string ??() + { + return 5[1463] ?? 6(1463, 28121, 3); + } + + public static string ??() + { + return 5[1464] ?? 6(1464, 28124, 7); + } + + public static string ??() + { + return 5[1465] ?? 6(1465, 28131, 4); + } + + public static string ??() + { + return 5[1466] ?? 6(1466, 28135, 33); + } + + public static string ??() + { + return 5[1467] ?? 6(1467, 28168, 9); + } + + public static string ??() + { + return 5[1468] ?? 6(1468, 28177, 17); + } + + public static string ??() + { + return 5[1469] ?? 6(1469, 28194, 15); + } + + public static string ??() + { + return 5[1470] ?? 6(1470, 28209, 11); + } + + public static string ??() + { + return 5[1471] ?? 6(1471, 28220, 8); + } + + public static string ??() + { + return 5[1472] ?? 6(1472, 28228, 9); + } + + public static string ??() + { + return 5[1473] ?? 6(1473, 28237, 165); + } + + public static string ??() + { + return 5[1474] ?? 6(1474, 28402, 15); + } + + public static string ??() + { + return 5[1475] ?? 6(1475, 28417, 8); + } + + public static string ??() + { + return 5[1476] ?? 6(1476, 28425, 5); + } + + public static string ??() + { + return 5[1477] ?? 6(1477, 28430, 36); + } + + public static string ??() + { + return 5[1478] ?? 6(1478, 28466, 9); + } + + public static string ??() + { + return 5[1479] ?? 6(1479, 28475, 34); + } + + public static string ??() + { + return 5[1480] ?? 6(1480, 28509, 20); + } + + public static string ??() + { + return 5[1481] ?? 6(1481, 28529, 16); + } + + public static string ??() + { + return 5[1482] ?? 6(1482, 28545, 17); + } + + public static string ??() + { + return 5[1483] ?? 6(1483, 28562, 2); + } + + public static string ??() + { + return 5[1484] ?? 6(1484, 28564, 24); + } + + public static string ??() + { + return 5[1485] ?? 6(1485, 28588, 43); + } + + public static string ??() + { + return 5[1486] ?? 6(1486, 28631, 6); + } + + public static string ??() + { + return 5[1487] ?? 6(1487, 28637, 9); + } + + public static string ??() + { + return 5[1488] ?? 6(1488, 28646, 8); + } + + public static string ??() + { + return 5[1489] ?? 6(1489, 28654, 7); + } + + public static string ??() + { + return 5[1490] ?? 6(1490, 28661, 12); + } + + public static string ??() + { + return 5[1491] ?? 6(1491, 28673, 7); + } + + public static string ??() + { + return 5[1492] ?? 6(1492, 28680, 14); + } + + public static string ??() + { + return 5[1493] ?? 6(1493, 28694, 13); + } + + public static string ??() + { + return 5[1494] ?? 6(1494, 28707, 18); + } + + public static string ??() + { + return 5[1495] ?? 6(1495, 28725, 16); + } + + public static string ??() + { + return 5[1496] ?? 6(1496, 28741, 26); + } + + public static string ??() + { + return 5[1497] ?? 6(1497, 28767, 18); + } + + public static string ??() + { + return 5[1498] ?? 6(1498, 28785, 12); + } + + public static string ??() + { + return 5[1499] ?? 6(1499, 28797, 6); + } + + public static string ??() + { + return 5[1500] ?? 6(1500, 28803, 8); + } + + public static string ??() + { + return 5[1501] ?? 6(1501, 28811, 11); + } + + public static string ??() + { + return 5[1502] ?? 6(1502, 28822, 14); + } + + public static string ??() + { + return 5[1503] ?? 6(1503, 28836, 7); + } + + public static string ??() + { + return 5[1504] ?? 6(1504, 28843, 7); + } + + public static string ??() + { + return 5[1505] ?? 6(1505, 28850, 11); + } + + public static string ??() + { + return 5[1506] ?? 6(1506, 28861, 21); + } + + public static string ??() + { + return 5[1507] ?? 6(1507, 28882, 11); + } + + public static string ??() + { + return 5[1508] ?? 6(1508, 28893, 13); + } + + public static string ??() + { + return 5[1509] ?? 6(1509, 28906, 3); + } + + public static string ??() + { + return 5[1510] ?? 6(1510, 28909, 9); + } + + public static string ??() + { + return 5[1511] ?? 6(1511, 28918, 12); + } + + public static string ??() + { + return 5[1512] ?? 6(1512, 28930, 16); + } + + public static string ??() + { + return 5[1513] ?? 6(1513, 28946, 15); + } + + public static string ??() + { + return 5[1514] ?? 6(1514, 28961, 10); + } + + public static string ??() + { + return 5[1515] ?? 6(1515, 28971, 10); + } + + public static string ??() + { + return 5[1516] ?? 6(1516, 28981, 4); + } + + public static string ??() + { + return 5[1517] ?? 6(1517, 28985, 6); + } + + public static string ??() + { + return 5[1518] ?? 6(1518, 28991, 11); + } + + public static string ??() + { + return 5[1519] ?? 6(1519, 29002, 7); + } + + public static string ??() + { + return 5[1520] ?? 6(1520, 29009, 15); + } + + public static string ??() + { + return 5[1521] ?? 6(1521, 29024, 10); + } + + public static string ??() + { + return 5[1522] ?? 6(1522, 29034, 12); + } + + public static string ??() + { + return 5[1523] ?? 6(1523, 29046, 19); + } + + public static string ??() + { + return 5[1524] ?? 6(1524, 29065, 25); + } + + public static string ??() + { + return 5[1525] ?? 6(1525, 29090, 8); + } + + public static string ??() + { + return 5[1526] ?? 6(1526, 29098, 6); + } + + public static string ??() + { + return 5[1527] ?? 6(1527, 29104, 12); + } + + public static string ??() + { + return 5[1528] ?? 6(1528, 29116, 10); + } + + public static string ??() + { + return 5[1529] ?? 6(1529, 29126, 9); + } + + public static string ??() + { + return 5[1530] ?? 6(1530, 29135, 8); + } + + public static string ??() + { + return 5[1531] ?? 6(1531, 29143, 8); + } + + public static string ??() + { + return 5[1532] ?? 6(1532, 29151, 16); + } + + public static string ??() + { + return 5[1533] ?? 6(1533, 29167, 7); + } + + public static string ??() + { + return 5[1534] ?? 6(1534, 29174, 7); + } + + public static string ??() + { + return 5[1535] ?? 6(1535, 29181, 10); + } + + public static string ??() + { + return 5[1536] ?? 6(1536, 29191, 13); + } + + public static string ??() + { + return 5[1537] ?? 6(1537, 29204, 14); + } + + public static string ??() + { + return 5[1538] ?? 6(1538, 29218, 4); + } + + public static string ??() + { + return 5[1539] ?? 6(1539, 29222, 7); + } + + public static string ??() + { + return 5[1540] ?? 6(1540, 29229, 14); + } + + public static string ??() + { + return 5[1541] ?? 6(1541, 29243, 11); + } + + public static string ??() + { + return 5[1542] ?? 6(1542, 29254, 11); + } + + public static string ??() + { + return 5[1543] ?? 6(1543, 29265, 14); + } + + public static string ??() + { + return 5[1544] ?? 6(1544, 29279, 12); + } + + public static string ??() + { + return 5[1545] ?? 6(1545, 29291, 11); + } + + public static string ??() + { + return 5[1546] ?? 6(1546, 29302, 14); + } + + public static string ??() + { + return 5[1547] ?? 6(1547, 29316, 19); + } + + public static string ??() + { + return 5[1548] ?? 6(1548, 29335, 14); + } + + public static string ??() + { + return 5[1549] ?? 6(1549, 29349, 19); + } + + public static string ??() + { + return 5[1550] ?? 6(1550, 29368, 9); + } + + public static string ??() + { + return 5[1551] ?? 6(1551, 29377, 11); + } + + public static string ??() + { + return 5[1552] ?? 6(1552, 29388, 16); + } + + public static string ??() + { + return 5[1553] ?? 6(1553, 29404, 8); + } + + public static string ??() + { + return 5[1554] ?? 6(1554, 29412, 10); + } + + public static string ??() + { + return 5[1555] ?? 6(1555, 29422, 7); + } + + public static string ??() + { + return 5[1556] ?? 6(1556, 29429, 18); + } + + public static string ??() + { + return 5[1557] ?? 6(1557, 29447, 14); + } + + public static string ??() + { + return 5[1558] ?? 6(1558, 29461, 9); + } + + public static string ??() + { + return 5[1559] ?? 6(1559, 29470, 9); + } + + public static string ??() + { + return 5[1560] ?? 6(1560, 29479, 8); + } + + public static string ??() + { + return 5[1561] ?? 6(1561, 29487, 12); + } + + public static string ??() + { + return 5[1562] ?? 6(1562, 29499, 24); + } + + public static string ??() + { + return 5[1563] ?? 6(1563, 29523, 7); + } + + public static string ??() + { + return 5[1564] ?? 6(1564, 29530, 6); + } + + public static string ??() + { + return 5[1565] ?? 6(1565, 29536, 6); + } + + public static string ??() + { + return 5[1566] ?? 6(1566, 29542, 13); + } + + public static string ??() + { + return 5[1567] ?? 6(1567, 29555, 16); + } + + public static string ??() + { + return 5[1568] ?? 6(1568, 29571, 16); + } + + public static string ??() + { + return 5[1569] ?? 6(1569, 29587, 13); + } + + public static string ??() + { + return 5[1570] ?? 6(1570, 29600, 10); + } + + public static string ??() + { + return 5[1571] ?? 6(1571, 29610, 11); + } + + public static string ??() + { + return 5[1572] ?? 6(1572, 29621, 15); + } + + public static string ??() + { + return 5[1573] ?? 6(1573, 29636, 16); + } + + public static string ??() + { + return 5[1574] ?? 6(1574, 29652, 7); + } + + public static string ??() + { + return 5[1575] ?? 6(1575, 29659, 7); + } + + public static string ??() + { + return 5[1576] ?? 6(1576, 29666, 12); + } + + public static string ??() + { + return 5[1577] ?? 6(1577, 29678, 8); + } + + public static string ??() + { + return 5[1578] ?? 6(1578, 29686, 14); + } + + public static string ??() + { + return 5[1579] ?? 6(1579, 29700, 16); + } + + public static string ??() + { + return 5[1580] ?? 6(1580, 29716, 170); + } + + public static string ??() + { + return 5[1581] ?? 6(1581, 29886, 14); + } + + public static string ??() + { + return 5[1582] ?? 6(1582, 29900, 16); + } + + public static string ??() + { + return 5[1583] ?? 6(1583, 29916, 11); + } + + public static string ??() + { + return 5[1584] ?? 6(1584, 29927, 12); + } + + public static string ??() + { + return 5[1585] ?? 6(1585, 29939, 12); + } + + public static string ??() + { + return 5[1586] ?? 6(1586, 29951, 18); + } + + public static string ??() + { + return 5[1587] ?? 6(1587, 29969, 19); + } + + public static string ??() + { + return 5[1588] ?? 6(1588, 29988, 26); + } + + public static string ??() + { + return 5[1589] ?? 6(1589, 30014, 11); + } + + public static string ??() + { + return 5[1590] ?? 6(1590, 30025, 18); + } + + public static string ??() + { + return 5[1591] ?? 6(1591, 30043, 16); + } + + public static string ??() + { + return 5[1592] ?? 6(1592, 30059, 24); + } + + public static string ??() + { + return 5[1593] ?? 6(1593, 30083, 13); + } + + public static string ??() + { + return 5[1594] ?? 6(1594, 30096, 22); + } + + public static string ??() + { + return 5[1595] ?? 6(1595, 30118, 13); + } + + public static string ??() + { + return 5[1596] ?? 6(1596, 30131, 22); + } + + public static string ??() + { + return 5[1597] ?? 6(1597, 30153, 14); + } + + public static string ??() + { + return 5[1598] ?? 6(1598, 30167, 16); + } + + public static string ??() + { + return 5[1599] ?? 6(1599, 30183, 12); + } + + public static string ??() + { + return 5[1600] ?? 6(1600, 30195, 18); + } + + public static string ??() + { + return 5[1601] ?? 6(1601, 30213, 18); + } + + public static string ??() + { + return 5[1602] ?? 6(1602, 30231, 5); + } + + public static string ??() + { + return 5[1603] ?? 6(1603, 30236, 15); + } + + public static string ??() + { + return 5[1604] ?? 6(1604, 30251, 1); + } + + public static string ??() + { + return 5[1605] ?? 6(1605, 30252, 2); + } + + public static string ??() + { + return 5[1606] ?? 6(1606, 30254, 39); + } + + public static string ??() + { + return 5[1607] ?? 6(1607, 30293, 11); + } + + public static string ??() + { + return 5[1608] ?? 6(1608, 30304, 36); + } + + public static string ??() + { + return 5[1609] ?? 6(1609, 30340, 23); + } + + public static string ??() + { + return 5[1610] ?? 6(1610, 30363, 5); + } + + public static string ??() + { + return 5[1611] ?? 6(1611, 30368, 56); + } + + public static string ??() + { + return 5[1612] ?? 6(1612, 30424, 10); + } + + public static string ??() + { + return 5[1613] ?? 6(1613, 30434, 8); + } + + public static string ??() + { + return 5[1614] ?? 6(1614, 30442, 10); + } + + public static string ??() + { + return 5[1615] ?? 6(1615, 30452, 3); + } + + public static string ??() + { + return 5[1616] ?? 6(1616, 30455, 11); + } + + public static string ??() + { + return 5[1617] ?? 6(1617, 30466, 15); + } + + public static string ??() + { + return 5[1618] ?? 6(1618, 30481, 9); + } + + public static string ??() + { + return 5[1619] ?? 6(1619, 30490, 13); + } + + public static string ??() + { + return 5[1620] ?? 6(1620, 30503, 13); + } + + public static string ??() + { + return 5[1621] ?? 6(1621, 30516, 11); + } + + public static string ??() + { + return 5[1622] ?? 6(1622, 30527, 9); + } + + public static string ??() + { + return 5[1623] ?? 6(1623, 30536, 6); + } + + public static string ??() + { + return 5[1624] ?? 6(1624, 30542, 13); + } + + public static string ??() + { + return 5[1625] ?? 6(1625, 30555, 146); + } + + public static string ??() + { + return 5[1626] ?? 6(1626, 30701, 10); + } + + public static string ??() + { + return 5[1627] ?? 6(1627, 30711, 3); + } + + public static string ??() + { + return 5[1628] ?? 6(1628, 30714, 4); + } + + public static string ??() + { + return 5[1629] ?? 6(1629, 30718, 4); + } + + public static string ??() + { + return 5[1630] ?? 6(1630, 30722, 7); + } + + public static string ??() + { + return 5[1631] ?? 6(1631, 30729, 7); + } + + public static string ??() + { + return 5[1632] ?? 6(1632, 30736, 1); + } + + public static string ??() + { + return 5[1633] ?? 6(1633, 30737, 6); + } + + public static string ??() + { + return 5[1634] ?? 6(1634, 30743, 10); + } + + public static string ??() + { + return 5[1635] ?? 6(1635, 30753, 3); + } + + public static string ??() + { + return 5[1636] ?? 6(1636, 30756, 10); + } + + public static string ??() + { + return 5[1637] ?? 6(1637, 30766, 9); + } + + public static string ??() + { + return 5[1638] ?? 6(1638, 30775, 9); + } + + public static string ??() + { + return 5[1639] ?? 6(1639, 30784, 3); + } + + public static string ??() + { + return 5[1640] ?? 6(1640, 30787, 8); + } + + public static string ??() + { + return 5[1641] ?? 6(1641, 30795, 1); + } + + public static string ??() + { + return 5[1642] ?? 6(1642, 30796, 5); + } + + public static string ??() + { + return 5[1643] ?? 6(1643, 30801, 6); + } + + public static string ??() + { + return 5[1644] ?? 6(1644, 30807, 8); + } + + public static string ??() + { + return 5[1645] ?? 6(1645, 30815, 24); + } + + public static string ??() + { + return 5[1646] ?? 6(1646, 30839, 2); + } + + public static string ??() + { + return 5[1647] ?? 6(1647, 30841, 2); + } + + public static string ??() + { + return 5[1648] ?? 6(1648, 30843, 3); + } + + public static string ??() + { + return 5[1649] ?? 6(1649, 30846, 2); + } + + public static string ??() + { + return 5[1650] ?? 6(1650, 30848, 1); + } + + public static string ??() + { + return 5[1651] ?? 6(1651, 30849, 4); + } + + public static string ??() + { + return 5[1652] ?? 6(1652, 30853, 6); + } + + public static string ??() + { + return 5[1653] ?? 6(1653, 30859, 8); + } + + public static string ??() + { + return 5[1654] ?? 6(1654, 30867, 4); + } + + public static string ??() + { + return 5[1655] ?? 6(1655, 30871, 10); + } + + public static string ??() + { + return 5[1656] ?? 6(1656, 30881, 19); + } + + public static string ??() + { + return 5[1657] ?? 6(1657, 30900, 4); + } + + public static string ??() + { + return 5[1658] ?? 6(1658, 30904, 36); + } + + public static string ??() + { + return 5[1659] ?? 6(1659, 30940, 13); + } + + public static string ??() + { + return 5[1660] ?? 6(1660, 30953, 10); + } + + public static string ??() + { + return 5[1661] ?? 6(1661, 30963, 7); + } + + public static string ??() + { + return 5[1662] ?? 6(1662, 30970, 7); + } + + public static string ??() + { + return 5[1663] ?? 6(1663, 30977, 16); + } + + public static string ??() + { + return 5[1664] ?? 6(1664, 30993, 10); + } + + public static string ??() + { + return 5[1665] ?? 6(1665, 31003, 11); + } + + public static string ??() + { + return 5[1666] ?? 6(1666, 31014, 5); + } + + public static string ??() + { + return 5[1667] ?? 6(1667, 31019, 14); + } + + public static string ??() + { + return 5[1668] ?? 6(1668, 31033, 17); + } + + public static string ??() + { + return 5[1669] ?? 6(1669, 31050, 18); + } + + public static string ??() + { + return 5[1670] ?? 6(1670, 31068, 13); + } + + public static string ??() + { + return 5[1671] ?? 6(1671, 31081, 7); + } + + public static string ??() + { + return 5[1672] ?? 6(1672, 31088, 11); + } + + public static string ??() + { + return 5[1673] ?? 6(1673, 31099, 18); + } + + public static string ??() + { + return 5[1674] ?? 6(1674, 31117, 11); + } + + public static string ??() + { + return 5[1675] ?? 6(1675, 31128, 11); + } + + public static string ??() + { + return 5[1676] ?? 6(1676, 31139, 4); + } + + public static string ??() + { + return 5[1677] ?? 6(1677, 31143, 4); + } + + public static string ??() + { + return 5[1678] ?? 6(1678, 31147, 3); + } + + public static string ??() + { + return 5[1679] ?? 6(1679, 31150, 3); + } + + public static string ??() + { + return 5[1680] ?? 6(1680, 31153, 8); + } + + public static string ??() + { + return 5[1681] ?? 6(1681, 31161, 159); + } + + public static string ??() + { + return 5[1682] ?? 6(1682, 31320, 6); + } + + public static string ??() + { + return 5[1683] ?? 6(1683, 31326, 10); + } + + public static string ??() + { + return 5[1684] ?? 6(1684, 31336, 12); + } + + public static string ??() + { + return 5[1685] ?? 6(1685, 31348, 6); + } + + public static string ??() + { + return 5[1686] ?? 6(1686, 31354, 24); + } + + public static string ??() + { + return 5[1687] ?? 6(1687, 31378, 10); + } + + public static string ??() + { + return 5[1688] ?? 6(1688, 31388, 5); + } + + public static string ??() + { + return 5[1689] ?? 6(1689, 31393, 8); + } + + public static string ??() + { + return 5[1690] ?? 6(1690, 31401, 6); + } + + public static string ??() + { + return 5[1691] ?? 6(1691, 31407, 15); + } + + public static string ??() + { + return 5[1692] ?? 6(1692, 31422, 16); + } + + public static string ??() + { + return 5[1693] ?? 6(1693, 31438, 157); + } + + public static string ??() + { + return 5[1694] ?? 6(1694, 31595, 7); + } + + public static string ??() + { + return 5[1695] ?? 6(1695, 31602, 6); + } + + public static string ??() + { + return 5[1696] ?? 6(1696, 31608, 23); + } + + public static string ??() + { + return 5[1697] ?? 6(1697, 31631, 9); + } + + public static string ??() + { + return 5[1698] ?? 6(1698, 31640, 8); + } + + public static string ??() + { + return 5[1699] ?? 6(1699, 31648, 167); + } + + public static string ??() + { + return 5[1700] ?? 6(1700, 31815, 4); + } + + public static string ??() + { + return 5[1701] ?? 6(1701, 31819, 15); + } + + public static string ??() + { + return 5[1702] ?? 6(1702, 31834, 14); + } + + public static string ??() + { + return 5[1703] ?? 6(1703, 31848, 12); + } + + public static string ??() + { + return 5[1704] ?? 6(1704, 31860, 4); + } + + public static string ??() + { + return 5[1705] ?? 6(1705, 31864, 8); + } + + public static string ??() + { + return 5[1706] ?? 6(1706, 31872, 5); + } + + public static string ??() + { + return 5[1707] ?? 6(1707, 31877, 20); + } + + public static string ??() + { + return 5[1708] ?? 6(1708, 31897, 27); + } + + public static string ??() + { + return 5[1709] ?? 6(1709, 31924, 61); + } + + public static string ??() + { + return 5[1710] ?? 6(1710, 31985, 5); + } + + public static string ??() + { + return 5[1711] ?? 6(1711, 31990, 8); + } + + public static string ??() + { + return 5[1712] ?? 6(1712, 31998, 24); + } + + public static string ??() + { + return 5[1713] ?? 6(1713, 32022, 31); + } + + public static string ??() + { + return 5[1714] ?? 6(1714, 32053, 16); + } + + public static string ??() + { + return 5[1715] ?? 6(1715, 32069, 9); + } + + public static string ??() + { + return 5[1716] ?? 6(1716, 32078, 2); + } + + public static string ??() + { + return 5[1717] ?? 6(1717, 32080, 6); + } + + public static string ??() + { + return 5[1718] ?? 6(1718, 32086, 5); + } + + public static string ??() + { + return 5[1719] ?? 6(1719, 32091, 5); + } + + public static string ??() + { + return 5[1720] ?? 6(1720, 32096, 5); + } + + public static string ??() + { + return 5[1721] ?? 6(1721, 32101, 4); + } + + public static string ??() + { + return 5[1722] ?? 6(1722, 32105, 2); + } + + public static string ??() + { + return 5[1723] ?? 6(1723, 32107, 10); + } + + public static string ??() + { + return 5[1724] ?? 6(1724, 32117, 12); + } + + public static string ??() + { + return 5[1725] ?? 6(1725, 32129, 6); + } + + public static string ??() + { + return 5[1726] ?? 6(1726, 32135, 7); + } + + public static string ??() + { + return 5[1727] ?? 6(1727, 32142, 7); + } + + public static string ??() + { + return 5[1728] ?? 6(1728, 32149, 8); + } + + public static string ??() + { + return 5[1729] ?? 6(1729, 32157, 4); + } + + public static string ??() + { + return 5[1730] ?? 6(1730, 32161, 4); + } + + public static string ??() + { + return 5[1731] ?? 6(1731, 32165, 3); + } + + public static string ??() + { + return 5[1732] ?? 6(1732, 32168, 13); + } + + public static string ??() + { + return 5[1733] ?? 6(1733, 32181, 6); + } + + public static string ??() + { + return 5[1734] ?? 6(1734, 32187, 16); + } + + public static string ??() + { + return 5[1735] ?? 6(1735, 32203, 4); + } + + public static string ??() + { + return 5[1736] ?? 6(1736, 32207, 4); + } + + public static string ??() + { + return 5[1737] ?? 6(1737, 32211, 8); + } + + public static string ??() + { + return 5[1738] ?? 6(1738, 32219, 6); + } + + public static string ??() + { + return 5[1739] ?? 6(1739, 32225, 10); + } + + public static string ??() + { + return 5[1740] ?? 6(1740, 32235, 7); + } + + public static string ??() + { + return 5[1741] ?? 6(1741, 32242, 7); + } + + public static string ??() + { + return 5[1742] ?? 6(1742, 32249, 11); + } + + public static string ??() + { + return 5[1743] ?? 6(1743, 32260, 11); + } + + public static string ??() + { + return 5[1744] ?? 6(1744, 32271, 16); + } + + public static string ??() + { + return 5[1745] ?? 6(1745, 32287, 138); + } + + public static string ??() + { + return 5[1746] ?? 6(1746, 32425, 5); + } + + public static string ??() + { + return 5[1747] ?? 6(1747, 32430, 17); + } + + public static string ??() + { + return 5[1748] ?? 6(1748, 32447, 11); + } + + public static string ??() + { + return 5[1749] ?? 6(1749, 32458, 22); + } + + public static string ??() + { + return 5[1750] ?? 6(1750, 32480, 6); + } + + public static string ??() + { + return 5[1751] ?? 6(1751, 32486, 7); + } + + public static string ??() + { + return 5[1752] ?? 6(1752, 32493, 12); + } + + public static string ??() + { + return 5[1753] ?? 6(1753, 32505, 10); + } + + public static string ??() + { + return 5[1754] ?? 6(1754, 32515, 10); + } + + public static string ??() + { + return 5[1755] ?? 6(1755, 32525, 9); + } + + public static string ??() + { + return 5[1756] ?? 6(1756, 32534, 23); + } + + public static string ??() + { + return 5[1757] ?? 6(1757, 32557, 9); + } + + public static string ??() + { + return 5[1758] ?? 6(1758, 32566, 14); + } + + public static string ??() + { + return 5[1759] ?? 6(1759, 32580, 8); + } + + public static string ??() + { + return 5[1760] ?? 6(1760, 32588, 10); + } + + public static string ??() + { + return 5[1761] ?? 6(1761, 32598, 9); + } + + public static string ??() + { + return 5[1762] ?? 6(1762, 32607, 16); + } + + public static string ??() + { + return 5[1763] ?? 6(1763, 32623, 20); + } + + public static string ??() + { + return 5[1764] ?? 6(1764, 32643, 36); + } + + public static string ??() + { + return 5[1765] ?? 6(1765, 32679, 10); + } + + public static string ??() + { + return 5[1766] ?? 6(1766, 32689, 16); + } + + public static string ??() + { + return 5[1767] ?? 6(1767, 32705, 12); + } + + public static string ??() + { + return 5[1768] ?? 6(1768, 32717, 6); + } + + public static string ??() + { + return 5[1769] ?? 6(1769, 32723, 12); + } + + public static string ??() + { + return 5[1770] ?? 6(1770, 32735, 13); + } + + public static string ??() + { + return 5[1771] ?? 6(1771, 32748, 137); + } + + public static string ??() + { + return 5[1772] ?? 6(1772, 32885, 7); + } + + public static string ??() + { + return 5[1773] ?? 6(1773, 32892, 62); + } + + public static string ??() + { + return 5[1774] ?? 6(1774, 32954, 4); + } + + public static string ??() + { + return 5[1775] ?? 6(1775, 32958, 8); + } + + public static string ??() + { + return 5[1776] ?? 6(1776, 32966, 3); + } + + public static string ??() + { + return 5[1777] ?? 6(1777, 32969, 62); + } + + public static string ??() + { + return 5[1778] ?? 6(1778, 33031, 21); + } + + public static string ??() + { + return 5[1779] ?? 6(1779, 33052, 23); + } + + public static string ??() + { + return 5[1780] ?? 6(1780, 33075, 11); + } + + public static string ??() + { + return 5[1781] ?? 6(1781, 33086, 19); + } + + public static string ??() + { + return 5[1782] ?? 6(1782, 33105, 61); + } + + public static string ??() + { + return 5[1783] ?? 6(1783, 33166, 5); + } + + public static string ??() + { + return 5[1784] ?? 6(1784, 33171, 23); + } + + public static string ??() + { + return 5[1785] ?? 6(1785, 33194, 62); + } + + public static string ??() + { + return 5[1786] ?? 6(1786, 33256, 6); + } + + public static string ??() + { + return 5[1787] ?? 6(1787, 33262, 67); + } + + public static string ??() + { + return 5[1788] ?? 6(1788, 33329, 8); + } + + public static string ??() + { + return 5[1789] ?? 6(1789, 33337, 23); + } + + public static string ??() + { + return 5[1790] ?? 6(1790, 33360, 62); + } + + public static string ??() + { + return 5[1791] ?? 6(1791, 33422, 12); + } + + public static string ??() + { + return 5[1792] ?? 6(1792, 33434, 13); + } + + public static string ??() + { + return 5[1793] ?? 6(1793, 33447, 12); + } + + public static string ??() + { + return 5[1794] ?? 6(1794, 33459, 5); + } + + public static string ??() + { + return 5[1795] ?? 6(1795, 33464, 8); + } + + public static string ??() + { + return 5[1796] ?? 6(1796, 33472, 21); + } + + public static string ??() + { + return 5[1797] ?? 6(1797, 33493, 13); + } + + public static string ??() + { + return 5[1798] ?? 6(1798, 33506, 12); + } + + public static string ??() + { + return 5[1799] ?? 6(1799, 33518, 9); + } + + public static string ??() + { + return 5[1800] ?? 6(1800, 33527, 10); + } + + public static string ??() + { + return 5[1801] ?? 6(1801, 33537, 10); + } + + public static string ??() + { + return 5[1802] ?? 6(1802, 33547, 6); + } + + public static string ??() + { + return 5[1803] ?? 6(1803, 33553, 12); + } + + public static string ??() + { + return 5[1804] ?? 6(1804, 33565, 15); + } + + public static string ??() + { + return 5[1805] ?? 6(1805, 33580, 17); + } + + public static string ??() + { + return 5[1806] ?? 6(1806, 33597, 11); + } + + public static string ??() + { + return 5[1807] ?? 6(1807, 33608, 13); + } + + public static string ??() + { + return 5[1808] ?? 6(1808, 33621, 11); + } + + public static string ??() + { + return 5[1809] ?? 6(1809, 33632, 8); + } + + public static string ??() + { + return 5[1810] ?? 6(1810, 33640, 11); + } + + public static string ??() + { + return 5[1811] ?? 6(1811, 33651, 12); + } + + public static string ??() + { + return 5[1812] ?? 6(1812, 33663, 22); + } + + public static string ??() + { + return 5[1813] ?? 6(1813, 33685, 13); + } + + public static string ??() + { + return 5[1814] ?? 6(1814, 33698, 16); + } + + public static string ??() + { + return 5[1815] ?? 6(1815, 33714, 21); + } + + public static string ??() + { + return 5[1816] ?? 6(1816, 33735, 22); + } + + public static string ??() + { + return 5[1817] ?? 6(1817, 33757, 29); + } + + public static string ??() + { + return 5[1818] ?? 6(1818, 33786, 8); + } + + public static string ??() + { + return 5[1819] ?? 6(1819, 33794, 13); + } + + public static string ??() + { + return 5[1820] ?? 6(1820, 33807, 15); + } + + public static string ??() + { + return 5[1821] ?? 6(1821, 33822, 20); + } + + public static string ??() + { + return 5[1822] ?? 6(1822, 33842, 28); + } + + public static string ??() + { + return 5[1823] ?? 6(1823, 33870, 25); + } + + public static string ??() + { + return 5[1824] ?? 6(1824, 33895, 4); + } + + public static string ??() + { + return 5[1825] ?? 6(1825, 33899, 18); + } + + public static string ??() + { + return 5[1826] ?? 6(1826, 33917, 18); + } + + public static string ??() + { + return 5[1827] ?? 6(1827, 33935, 18); + } + + public static string ??() + { + return 5[1828] ?? 6(1828, 33953, 26); + } + + public static string ??() + { + return 5[1829] ?? 6(1829, 33979, 26); + } + + public static string ??() + { + return 5[1830] ?? 6(1830, 34005, 26); + } + + public static string ??() + { + return 5[1831] ?? 6(1831, 34031, 19); + } + + public static string ??() + { + return 5[1832] ?? 6(1832, 34050, 19); + } + + public static string ??() + { + return 5[1833] ?? 6(1833, 34069, 19); + } + + public static string ??() + { + return 5[1834] ?? 6(1834, 34088, 19); + } + + public static string ??() + { + return 5[1835] ?? 6(1835, 34107, 19); + } + + public static string ??() + { + return 5[1836] ?? 6(1836, 34126, 17); + } + + public static string ??() + { + return 5[1837] ?? 6(1837, 34143, 17); + } + + public static string ??() + { + return 5[1838] ?? 6(1838, 34160, 17); + } + + public static string ??() + { + return 5[1839] ?? 6(1839, 34177, 17); + } + + public static string ??() + { + return 5[1840] ?? 6(1840, 34194, 17); + } + + public static string ??() + { + return 5[1841] ?? 6(1841, 34211, 17); + } + + public static string ??() + { + return 5[1842] ?? 6(1842, 34228, 17); + } + + public static string ??() + { + return 5[1843] ?? 6(1843, 34245, 28); + } + + public static string ??() + { + return 5[1844] ?? 6(1844, 34273, 15); + } + + public static string ??() + { + return 5[1845] ?? 6(1845, 34288, 15); + } + + public static string ??() + { + return 5[1846] ?? 6(1846, 34303, 15); + } + + public static string ??() + { + return 5[1847] ?? 6(1847, 34318, 16); + } + + public static string ??() + { + return 5[1848] ?? 6(1848, 34334, 16); + } + + public static string ??() + { + return 5[1849] ?? 6(1849, 34350, 16); + } + + public static string ??() + { + return 5[1850] ?? 6(1850, 34366, 16); + } + + public static string ??() + { + return 5[1851] ?? 6(1851, 34382, 16); + } + + public static string ??() + { + return 5[1852] ?? 6(1852, 34398, 25); + } + + public static string ??() + { + return 5[1853] ?? 6(1853, 34423, 25); + } + + public static string ??() + { + return 5[1854] ?? 6(1854, 34448, 14); + } + + public static string ??() + { + return 5[1855] ?? 6(1855, 34462, 20); + } + + public static string ??() + { + return 5[1856] ?? 6(1856, 34482, 20); + } + + public static string ??() + { + return 5[1857] ?? 6(1857, 34502, 20); + } + + public static string ??() + { + return 5[1858] ?? 6(1858, 34522, 22); + } + + public static string ??() + { + return 5[1859] ?? 6(1859, 34544, 22); + } + + public static string ??() + { + return 5[1860] ?? 6(1860, 34566, 32); + } + + public static string ??() + { + return 5[1861] ?? 6(1861, 34598, 41); + } + + public static string ??() + { + return 5[1862] ?? 6(1862, 34639, 24); + } + + public static string ??() + { + return 5[1863] ?? 6(1863, 34663, 27); + } + + public static string ??() + { + return 5[1864] ?? 6(1864, 34690, 31); + } + + public static string ??() + { + return 5[1865] ?? 6(1865, 34721, 33); + } + + public static string ??() + { + return 5[1866] ?? 6(1866, 34754, 23); + } + + public static string ??() + { + return 5[1867] ?? 6(1867, 34777, 8); + } + + public static string ??() + { + return 5[1868] ?? 6(1868, 34785, 14); + } + + public static string ??() + { + return 5[1869] ?? 6(1869, 34799, 13); + } + + public static string ??() + { + return 5[1870] ?? 6(1870, 34812, 17); + } + + public static string ??() + { + return 5[1871] ?? 6(1871, 34829, 13); + } + + public static string ??() + { + return 5[1872] ?? 6(1872, 34842, 14); + } + + public static string ??() + { + return 5[1873] ?? 6(1873, 34856, 18); + } + + public static string ??() + { + return 5[1874] ?? 6(1874, 34874, 20); + } + + public static string ??() + { + return 5[1875] ?? 6(1875, 34894, 14); + } + + public static string ??() + { + return 5[1876] ?? 6(1876, 34908, 13); + } + + public static string ??() + { + return 5[1877] ?? 6(1877, 34921, 13); + } + + public static string ??() + { + return 5[1878] ?? 6(1878, 34934, 10); + } + + public static string ??() + { + return 5[1879] ?? 6(1879, 34944, 22); + } + + public static string ??() + { + return 5[1880] ?? 6(1880, 34966, 30); + } + + public static string ??() + { + return 5[1881] ?? 6(1881, 34996, 13); + } + + public static string ??() + { + return 5[1882] ?? 6(1882, 35009, 13); + } + + public static string ??() + { + return 5[1883] ?? 6(1883, 35022, 16); + } + + public static string ??() + { + return 5[1884] ?? 6(1884, 35038, 11); + } + + public static string ??() + { + return 5[1885] ?? 6(1885, 35049, 9); + } + + public static string ??() + { + return 5[1886] ?? 6(1886, 35058, 13); + } + + public static string ??() + { + return 5[1887] ?? 6(1887, 35071, 14); + } + + public static string ??() + { + return 5[1888] ?? 6(1888, 35085, 15); + } + + public static string ??() + { + return 5[1889] ?? 6(1889, 35100, 12); + } + + public static string ??() + { + return 5[1890] ?? 6(1890, 35112, 42); + } + + public static string ??() + { + return 5[1891] ?? 6(1891, 35154, 17); + } + + public static string ??() + { + return 5[1892] ?? 6(1892, 35171, 1); + } + + public static string ??() + { + return 5[1893] ?? 6(1893, 35172, 2); + } + + public static string ??() + { + return 5[1894] ?? 6(1894, 35174, 4); + } + + public static string ??() + { + return 5[1895] ?? 6(1895, 35178, 4); + } + + public static string ??() + { + return 5[1896] ?? 6(1896, 35182, 24); + } + + public static string ??() + { + return 5[1897] ?? 6(1897, 35206, 31); + } + + public static string ??() + { + return 5[1898] ?? 6(1898, 35237, 28); + } + + public static string ??() + { + return 5[1899] ?? 6(1899, 35265, 9); + } + + public static string ??() + { + return 5[1900] ?? 6(1900, 35274, 17); + } + + public static string ??() + { + return 5[1901] ?? 6(1901, 35291, 10); + } + + public static string ??() + { + return 5[1902] ?? 6(1902, 35301, 11); + } + + public static string ??() + { + return 5[1903] ?? 6(1903, 35312, 7); + } + + public static string ??() + { + return 5[1904] ?? 6(1904, 35319, 17); + } + + public static string ??() + { + return 5[1905] ?? 6(1905, 35336, 11); + } + + public static string ??() + { + return 5[1906] ?? 6(1906, 35347, 10); + } + + public static string ??() + { + return 5[1907] ?? 6(1907, 35357, 20); + } + + public static string ??() + { + return 5[1908] ?? 6(1908, 35377, 25); + } + + public static string ??() + { + return 5[1909] ?? 6(1909, 35402, 27); + } + + public static string ??() + { + return 5[1910] ?? 6(1910, 35429, 28); + } + + public static string ??() + { + return 5[1911] ?? 6(1911, 35457, 28); + } + + public static string ??() + { + return 5[1912] ?? 6(1912, 35485, 28); + } + + public static string ??() + { + return 5[1913] ?? 6(1913, 35513, 30); + } + + public static string ??() + { + return 5[1914] ?? 6(1914, 35543, 12); + } + + public static string ??() + { + return 5[1915] ?? 6(1915, 35555, 18); + } + + public static string ??() + { + return 5[1916] ?? 6(1916, 35573, 24); + } + + public static string ??() + { + return 5[1917] ?? 6(1917, 35597, 12); + } + + public static string ??() + { + return 5[1918] ?? 6(1918, 35609, 22); + } + + public static string ??() + { + return 5[1919] ?? 6(1919, 35631, 43); + } + + public static string ??() + { + return 5[1920] ?? 6(1920, 35674, 4); + } + + public static string ??() + { + return 5[1921] ?? 6(1921, 35678, 4); + } + + public static string ??() + { + return 5[1922] ?? 6(1922, 35682, 4); + } + + public static string ??() + { + return 5[1923] ?? 6(1923, 35686, 21); + } + + public static string ??() + { + return 5[1924] ?? 6(1924, 35707, 7); + } + + public static string ??() + { + return 5[1925] ?? 6(1925, 35714, 11); + } + + public static string ??() + { + return 5[1926] ?? 6(1926, 35725, 11); + } + + public static string ??() + { + return 5[1927] ?? 6(1927, 35736, 5); + } + + public static string ??() + { + return 5[1928] ?? 6(1928, 35741, 8); + } + + public static string ??() + { + return 5[1929] ?? 6(1929, 35749, 12); + } + + public static string ??() + { + return 5[1930] ?? 6(1930, 35761, 6); + } + + public static string ??() + { + return 5[1931] ?? 6(1931, 35767, 3); + } + + public static string ??() + { + return 5[1932] ?? 6(1932, 35770, 3); + } + + public static string ??() + { + return 5[1933] ?? 6(1933, 35773, 151); + } + + public static string ??() + { + return 5[1934] ?? 6(1934, 35924, 2); + } + + public static string ??() + { + return 5[1935] ?? 6(1935, 35926, 14); + } + + public static string ??() + { + return 5[1936] ?? 6(1936, 35940, 47); + } + + public static string ??() + { + return 5[1937] ?? 6(1937, 35987, 49); + } + + public static string ??() + { + return 5[1938] ?? 6(1938, 36036, 47); + } + + public static string ??() + { + return 5[1939] ?? 6(1939, 36083, 49); + } + + public static string ??() + { + return 5[1940] ?? 6(1940, 36132, 3); + } + + public static string ??() + { + return 5[1941] ?? 6(1941, 36135, 52); + } + + public static string ??() + { + return 5[1942] ?? 6(1942, 36187, 152); + } + + public static string ??() + { + return 5[1943] ?? 6(1943, 36339, 54); + } + + public static string ??() + { + return 5[1944] ?? 6(1944, 36393, 52); + } + + public static string ??() + { + return 5[1945] ?? 6(1945, 36445, 54); + } + + public static string ??() + { + return 5[1946] ?? 6(1946, 36499, 3); + } + + public static string ??() + { + return 5[1947] ?? 6(1947, 36502, 13); + } + + public static string ??() + { + return 5[1948] ?? 6(1948, 36515, 150); + } + + public static string ??() + { + return 5[1949] ?? 6(1949, 36665, 49); + } + + public static string ??() + { + return 5[1950] ?? 6(1950, 36714, 51); + } + + public static string ??() + { + return 5[1951] ?? 6(1951, 36765, 49); + } + + public static string ??() + { + return 5[1952] ?? 6(1952, 36814, 51); + } + + public static string ??() + { + return 5[1953] ?? 6(1953, 36865, 13); + } + + public static string ??() + { + return 5[1954] ?? 6(1954, 36878, 4); + } + + public static string ??() + { + return 5[1955] ?? 6(1955, 36882, 15); + } + + public static string ??() + { + return 5[1956] ?? 6(1956, 36897, 158); + } + + public static string ??() + { + return 5[1957] ?? 6(1957, 37055, 2); + } + + public static string ??() + { + return 5[1958] ?? 6(1958, 37057, 7); + } + + public static string ??() + { + return 5[1959] ?? 6(1959, 37064, 4); + } + + public static string ??() + { + return 5[1960] ?? 6(1960, 37068, 4); + } + + public static string ??() + { + return 5[1961] ?? 6(1961, 37072, 10); + } + + public static string ??() + { + return 5[1962] ?? 6(1962, 37082, 10); + } + + public static string ??() + { + return 5[1963] ?? 6(1963, 37092, 8); + } + + public static string ??() + { + return 5[1964] ?? 6(1964, 37100, 16); + } + + public static string ??() + { + return 5[1965] ?? 6(1965, 37116, 165); + } + + public static string ??() + { + return 5[1966] ?? 6(1966, 37281, 7); + } + + public static string ??() + { + return 5[1967] ?? 6(1967, 37288, 8); + } + + public static string ??() + { + return 5[1968] ?? 6(1968, 37296, 6); + } + + public static string ??() + { + return 5[1969] ?? 6(1969, 37302, 1); + } + + public static string ??() + { + return 5[1970] ?? 6(1970, 37303, 2); + } + + public static string ??() + { + return 5[1971] ?? 6(1971, 37305, 1); + } + + public static string ??() + { + return 5[1972] ?? 6(1972, 37306, 5); + } + + public static string ??() + { + return 5[1973] ?? 6(1973, 37311, 8); + } + + public static string ??() + { + return 5[1974] ?? 6(1974, 37319, 12); + } + + public static string ??() + { + return 5[1975] ?? 6(1975, 37331, 13); + } + + public static string ??() + { + return 5[1976] ?? 6(1976, 37344, 10); + } + + public static string ??() + { + return 5[1977] ?? 6(1977, 37354, 17); + } + + public static string ??() + { + return 5[1978] ?? 6(1978, 37371, 12); + } + + public static string ??() + { + return 5[1979] ?? 6(1979, 37383, 12); + } + + public static string ??() + { + return 5[1980] ?? 6(1980, 37395, 10); + } + + public static string ??() + { + return 5[1981] ?? 6(1981, 37405, 17); + } + + public static string ??() + { + return 5[1982] ?? 6(1982, 37422, 2); + } + + public static string ??() + { + return 5[1983] ?? 6(1983, 37424, 3); + } + + public static string ??() + { + return 5[1984] ?? 6(1984, 37427, 2); + } + + public static string ??() + { + return 5[1985] ?? 6(1985, 37429, 7); + } + + public static string ??() + { + return 5[1986] ?? 6(1986, 37436, 8); + } + + public static string ??() + { + return 5[1987] ?? 6(1987, 37444, 21); + } + + public static string ??() + { + return 5[1988] ?? 6(1988, 37465, 22); + } + + public static string ??() + { + return 5[1989] ?? 6(1989, 37487, 22); + } + + public static string ??() + { + return 5[1990] ?? 6(1990, 37509, 25); + } + + public static string ??() + { + return 5[1991] ?? 6(1991, 37534, 16); + } + + public static string ??() + { + return 5[1992] ?? 6(1992, 37550, 7); + } + + public static string ??() + { + return 5[1993] ?? 6(1993, 37557, 17); + } + + public static string ??() + { + return 5[1994] ?? 6(1994, 37574, 6); + } + + public static string ??() + { + return 5[1995] ?? 6(1995, 37580, 4); + } + + public static string ??() + { + return 5[1996] ?? 6(1996, 37584, 3); + } + + public static string ??() + { + return 5[1997] ?? 6(1997, 37587, 15); + } + + public static string ??() + { + return 5[1998] ?? 6(1998, 37602, 37); + } + + public static string ??() + { + return 5[1999] ?? 6(1999, 37639, 7); + } + + public static string ??() + { + return 5[2000] ?? 6(2000, 37646, 7); + } + + public static string ??() + { + return 5[2001] ?? 6(2001, 37653, 9); + } + + public static string ??() + { + return 5[2002] ?? 6(2002, 37662, 9); + } + + public static string ??() + { + return 5[2003] ?? 6(2003, 37671, 18); + } + + public static string ??() + { + return 5[2004] ?? 6(2004, 37689, 18); + } + + public static string ??() + { + return 5[2005] ?? 6(2005, 37707, 16); + } + + public static string ??() + { + return 5[2006] ?? 6(2006, 37723, 14); + } + + public static string ??() + { + return 5[2007] ?? 6(2007, 37737, 17); + } + + public static string ??() + { + return 5[2008] ?? 6(2008, 37754, 14); + } + + public static string ??() + { + return 5[2009] ?? 6(2009, 37768, 17); + } + + public static string ??() + { + return 5[2010] ?? 6(2010, 37785, 38); + } + + public static string ??() + { + return 5[2011] ?? 6(2011, 37823, 18); + } + + public static string ??() + { + return 5[2012] ?? 6(2012, 37841, 8); + } + + public static string ??() + { + return 5[2013] ?? 6(2013, 37849, 11); + } + + public static string ??() + { + return 5[2014] ?? 6(2014, 37860, 6); + } + + public static string ??() + { + return 5[2015] ?? 6(2015, 37866, 10); + } + + public static string ??() + { + return 5[2016] ?? 6(2016, 37876, 9); + } + + public static string ??() + { + return 5[2017] ?? 6(2017, 37885, 5); + } + + public static string ??() + { + return 5[2018] ?? 6(2018, 37890, 10); + } + + public static string ??() + { + return 5[2019] ?? 6(2019, 37900, 12); + } + + public static string ??() + { + return 5[2020] ?? 6(2020, 37912, 20); + } + + public static string ??() + { + return 5[2021] ?? 6(2021, 37932, 11); + } + + public static string ??() + { + return 5[2022] ?? 6(2022, 37943, 13); + } + + public static string ??() + { + return 5[2023] ?? 6(2023, 37956, 11); + } + + public static string ??() + { + return 5[2024] ?? 6(2024, 37967, 8); + } + + public static string ??() + { + return 5[2025] ?? 6(2025, 37975, 6); + } + + public static string ??() + { + return 5[2026] ?? 6(2026, 37981, 13); + } + + public static string ??() + { + return 5[2027] ?? 6(2027, 37994, 11); + } + + public static string ??() + { + return 5[2028] ?? 6(2028, 38005, 19); + } + + public static string ??() + { + return 5[2029] ?? 6(2029, 38024, 49); + } + + public static string ??() + { + return 5[2030] ?? 6(2030, 38073, 8); + } + + public static string ??() + { + return 5[2031] ?? 6(2031, 38081, 23); + } + + public static string ??() + { + return 5[2032] ?? 6(2032, 38104, 17); + } + + public static string ??() + { + return 5[2033] ?? 6(2033, 38121, 58); + } + + public static string ??() + { + return 5[2034] ?? 6(2034, 38179, 14); + } + + public static string ??() + { + return 5[2035] ?? 6(2035, 38193, 28); + } + + public static string ??() + { + return 5[2036] ?? 6(2036, 38221, 38); + } + + public static string ??() + { + return 5[2037] ?? 6(2037, 38259, 32); + } + + public static string ??() + { + return 5[2038] ?? 6(2038, 38291, 77); + } + + public static string ??() + { + return 5[2039] ?? 6(2039, 38368, 13); + } + + public static string ??() + { + return 5[2040] ?? 6(2040, 38381, 6); + } + + public static string ??() + { + return 5[2041] ?? 6(2041, 38387, 37); + } + + public static string ??() + { + return 5[2042] ?? 6(2042, 38424, 14); + } + + public static string ??() + { + return 5[2043] ?? 6(2043, 38438, 14); + } + + public static string ??() + { + return 5[2044] ?? 6(2044, 38452, 12); + } + + public static string ??() + { + return 5[2045] ?? 6(2045, 38464, 12); + } + + public static string ??() + { + return 5[2046] ?? 6(2046, 38476, 13); + } + + public static string ??() + { + return 5[2047] ?? 6(2047, 38489, 24); + } + + public static string ??() + { + return 5[2048] ?? 6(2048, 38513, 8); + } + + public static string ??() + { + return 5[2049] ?? 6(2049, 38521, 1); + } + + public static string ??() + { + return 5[2050] ?? 6(2050, 38522, 3); + } + + public static string ??() + { + return 5[2051] ?? 6(2051, 38525, 33); + } + + public static string ??() + { + return 5[2052] ?? 6(2052, 38558, 20); + } + + public static string ??() + { + return 5[2053] ?? 6(2053, 38578, 23); + } + + public static string ??() + { + return 5[2054] ?? 6(2054, 38601, 13); + } + + public static string ??() + { + return 5[2055] ?? 6(2055, 38614, 13); + } + + public static string ??() + { + return 5[2056] ?? 6(2056, 38627, 14); + } + + public static string ??() + { + return 5[2057] ?? 6(2057, 38641, 16); + } + + public static string ??() + { + return 5[2058] ?? 6(2058, 38657, 4); + } + + public static string ??() + { + return 5[2059] ?? 6(2059, 38661, 160); + } + + public static string ??() + { + return 5[2060] ?? 6(2060, 38821, 22); + } + + public static string ??() + { + return 5[2061] ?? 6(2061, 38843, 15); + } + + public static string ??() + { + return 5[2062] ?? 6(2062, 38858, 17); + } + + public static string ??() + { + return 5[2063] ?? 6(2063, 38875, 4); + } + + public static string ??() + { + return 5[2064] ?? 6(2064, 38879, 10); + } + + public static string ??() + { + return 5[2065] ?? 6(2065, 38889, 3); + } + + public static string ??() + { + return 5[2066] ?? 6(2066, 38892, 155); + } + + public static string ??() + { + return 5[2067] ?? 6(2067, 39047, 12); + } + + static 3E560F35-EA4B-4F47-8302-BE30F80C1E18() + { + for (int i = 0; i < 4.Length; i++) + { + 4[i] = (byte)(4[i] ^ i ^ 0xAA); + } + } + } +} diff --git a/lib/_list.md b/lib/_list.md deleted file mode 100644 index ca7b1d84..00000000 --- a/lib/_list.md +++ /dev/null @@ -1,173 +0,0 @@ -# QuanTAlib Indicators Status - -## Implementation Status - -| Category | Done | Todo | Total | -|------------|------|------|-------| -| Averages | 33 | 0 | 33 | -| Momentum | 17 | 0 | 17 | -| Oscillators| 24 | 5 | 29 | -| Patterns | 0 | 8 | 8 | -| Statistics | 22 | 1 | 23 | -| Volatility | 31 | 4 | 35 | -| Total | 127 | 18 | 145 | - -## Indicators by Category - -### Averages (33/33) -✔️ AFIRMA - Adaptive FIR Moving Average -✔️ ALMA - Arnaud Legoux Moving Average -✔️ CONVOLUTION - 1D Convolution with sliding kernel -✔️ DEMA - Double Exponential Moving Average -✔️ DSMA - Dynamic Simple Moving Average -✔️ DWMA - Dynamic Weighted Moving Average -✔️ EMA - Exponential Moving Average -✔️ EPMA - Endpoint Moving Average -✔️ FRAMA - Fractal Adaptive Moving Average -✔️ FWMA - Forward Weighted Moving Average -✔️ GMA - Gaussian Moving Average -✔️ HMA - Hull Moving Average -✔️ HTIT - Hilbert Transform Instantaneous Trendline -✔️ HWMA - Hann Weighted Moving Average -✔️ JMA - Jurik Moving Average -✔️ KAMA - Kaufman Adaptive Moving Average -✔️ LTMA - Linear Time Moving Average -✔️ MAAF - Moving Average Adaptive Filter -✔️ MAMA - MESA Adaptive Moving Average (MAMA, FAMA) -✔️ MGDI - McGinley Dynamic Indicator -✔️ MMA - Modified Moving Average -✔️ PWMA - Parabolic Weighted Moving Average -✔️ QEMA - Quick Exponential Moving Average -✔️ REMA - Regularized Exponential Moving Average -✔️ RMA - Running Moving Average -✔️ SINEMA - Sine-weighted Moving Average -✔️ SMA - Simple Moving Average -✔️ SMMA - Smoothed Moving Average -✔️ T3 - Triple Exponential Moving Average (T3) -✔️ TEMA - Triple Exponential Moving Average -✔️ TRIMA - Triangular Moving Average -✔️ VIDYA - Variable Index Dynamic Average -✔️ WMA - Weighted Moving Average -✔️ ZLEMA - Zero-Lag Exponential Moving Average - -### Momentum (17/17) -✔️ ADX - Average Directional Movement Index -✔️ ADXR - Average Directional Movement Index Rating -✔️ APO - Absolute Price Oscillator -✔️ DMI - Directional Movement Index (DI+, DI-) -✔️ DMX - Jurik Directional Movement Index -✔️ DPO - Detrended Price Oscillator -✔️ MACD - Moving Average Convergence/Divergence (MACD, Signal, Histogram) -✔️ MOM - Momentum -✔️ PMO - Price Momentum Oscillator -✔️ PO - Price Oscillator -✔️ PPO - Percentage Price Oscillator -✔️ PRS - Price Relative Strength -✔️ ROC - Rate of Change -✔️ TSI - True Strength Index -✔️ TRIX - 1-day ROC of TEMA -✔️ VEL - Jurik Signal Velocity -✔️ VORTEX - Vortex Indicator (VI+, VI-) - -### Oscillators (24/29) -✔️ AC - Acceleration Oscillator -✔️ AO - Awesome Oscillator -✔️ AROON - Aroon oscillator (Up, Down) -✔️ BOP - Balance of Power -✔️ CCI - Commodity Channel Index -✔️ CFO - Chande Forcast Oscillator -✔️ CHOP - Choppiness Index -✔️ CMO - Chande Momentum Oscillator -✔️ COG - Ehler's Center of Gravity -✔️ COPPOCK - Coppock Curve -✔️ CRSI - Connor RSI -✔️ CTI - Ehler's Correlation Trend Indicator -✔️ DOSC - Derivative Oscillator -✔️ FISHER - Fisher Transform -✔️ EFI - Elder Ray's Force Index -✔️ RSI - Relative Strength Index -✔️ RSX - Jurik Trend Strength Index -✔️ SMI - Stochastic Momentum Index -✔️ SRSI - Stochastic RSI (SRSI, Signal) -✔️ STC - Schaff Trend Cycle -✔️ STOCH - Stochastic Oscillator (%K, %D) -✔️ TSI - True Strength Index -✔️ UO - Ultimate Oscillator -✔️ WILLR - Larry Williams' %R -FOSC - Forecast Oscillator -GATOR - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth) -KDJ - KDJ Indicator (K, D, J lines) -KRI - Kairi Relative Index -RVGI - Relative Vigor Index (RVGI, Signal) - -### Patterns (0/8) -DOJI - Doji Candlestick Pattern -ER - Elder Ray Pattern (Bull Power, Bear Power) -MARU - Marubozu Candlestick Pattern -PIV - Pivot Points (Support 1-3, Pivot, Resistance 1-3) -PP - Price Pivots (Support 1-3, Pivot, Resistance 1-3) -RPP - Rolling Pivot Points (Support 1-3, Pivot, Resistance 1-3) -WF - Williams Fractal -ZZ - Zig Zag Pattern - -### Statistics (22/23) -✔️ BETA - Beta coefficient measuring volatility relative to market -✔️ CORR - Correlation coefficient between two series -✔️ COVAR - Covariance between two series -✔️ CURVATURE - Curvature of a time series -✔️ ENTROPY - Information entropy of a series -✔️ GRANGER - Granger causality test -✔️ HURST - Hurst exponent for trend strength -✔️ KENDALL - Kendall rank correlation -✔️ KURTOSIS - Kurtosis measuring tail extremity -✔️ MAX - Maximum value over period -✔️ MEDIAN - Median value over period -✔️ MIN - Minimum value over period -✔️ MODE - Mode (most frequent value) -✔️ PERCENTILE - Percentile rank calculation -✔️ SKEW - Skewness measuring distribution asymmetry -✔️ SLOPE - Linear regression slope -✔️ SPEARMAN - Spearman rank correlation -✔️ STDDEV - Standard deviation -✔️ THEIL - Theil's U statistics for forecast accuracy -✔️ TSF - Time series forecast -✔️ VARIANCE - Statistical variance -✔️ ZSCORE - Z-score standardization -COINTEGRATION - Test for cointegrated series - -### Volatility (31/35) -✔️ ADR - Average Daily Range -✔️ AP - Andrew's Pitchfork -✔️ ATR - Average True Range -✔️ ATRP - Average True Range Percent -✔️ ATRS - ATR Trailing Stop -✔️ BBAND - Bollinger Bands® (Upper, Middle, Lower) -✔️ CCV - Close-to-Close Volatility -✔️ CE - Chandelier Exit -✔️ CV - Conditional Volatility (ARCH/GARCH) -✔️ CVI - Chaikin's Volatility -✔️ DCHN - Donchian Channels (Upper, Middle, Lower) -✔️ EWMA - Exponential Weighted Moving Average Volatility -✔️ FCB - Fractal Chaos Bands -✔️ GKV - Garman-Klass Volatility -✔️ HLV - High-Low Volatility -✔️ HV - Historical Volatility -✔️ JVOLTY - Jurik Volatility (Jvolty, Upper band, Lower band) -✔️ NATR - Normalized Average True Range -✔️ PCH - Price Channel Indicator -✔️ PV - Parkinson Volatility -✔️ RSV - Rogers-Satchell Volatility -✔️ RV - Realized Volatility -✔️ RVI - Relative Volatility Index -✔️ SV - Stochastic Volatility -✔️ TR - True Range -✔️ UI - Ulcer Index -✔️ VC - Volatility Cone (Mean, Upper Bound, Lower Bound) -✔️ VOV - Volatility of Volatility -✔️ VR - Volatility Ratio -✔️ VS - Volatility Stop (Long Stop, Short Stop) -✔️ YZV - Yang-Zhang Volatility -ICH - Ichimoku Cloud (Conversion, Base, Leading Span A, Leading Span B, Lagging Span) -KC - Keltner Channels (Upper, Middle, Lower) -PSAR - Parabolic Stop and Reverse (Value, Trend) -STARC - Starc Bands (Upper, Middle, Lower) diff --git a/lib/averages/Afirma.cs b/lib/averages/Afirma.cs deleted file mode 100644 index d31f4102..00000000 --- a/lib/averages/Afirma.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// AFIRMA: Adaptive FIR Moving Average -/// A finite impulse response (FIR) filter that combines windowing functions with sinc-based filtering. -/// Provides superior noise reduction while maintaining signal fidelity through adaptive filtering. -/// -/// -/// Implementation: -/// Original implementation based on FIR filter design principles -/// -public class Afirma : AbstractBase -{ - public enum WindowType - { - Rectangular, - Hanning1, - Hanning2, - Blackman, - BlackmanHarris - } - - private readonly int Periods; - private readonly int Taps; - private readonly WindowType Window; - private readonly CircularBuffer _buffer; - private readonly double[] _weights; - private readonly double _wsum; - private readonly double[] _armaBuffer; - private readonly int _n; - private readonly double _sx2, _sx3, _sx4, _sx5, _sx6, _den; - private readonly double _twoPi = 2.0 * Math.PI; - private readonly double _fourPi = 4.0 * Math.PI; - private readonly double _sixPi = 6.0 * Math.PI; - - /// The number of periods for the sinc filter calculation. - /// The number of filter taps (filter length). Must be odd number. - /// The type of window function to apply (Rectangular, Hanning1, Hanning2, Blackman, or BlackmanHarris). - /// Thrown when periods or taps is less than 1. - public Afirma(int periods, int taps, WindowType window) - { - if (periods < 1) - { - throw new ArgumentOutOfRangeException(nameof(periods), "Periods must be greater than or equal to 1."); - } - if (taps < 1) - { - throw new ArgumentOutOfRangeException(nameof(taps), "Taps must be greater than or equal to 1."); - } - Periods = periods; - Taps = taps; - Window = window; - WarmupPeriod = taps; - _buffer = new CircularBuffer(taps); - _weights = new double[taps]; - _wsum = CalculateWeights(); - _armaBuffer = new double[taps]; - _n = (Taps - 1) / 2; - - // Precalculate least squares coefficients - _sx2 = ((2 * _n) + 1) / 3.0; - _sx3 = _n * (_n + 1) / 2.0; - _sx4 = _sx2 * ((3 * _n * _n) + (3 * _n) - 1) / 5.0; - _sx5 = _sx3 * ((2 * _n * _n) + (2 * _n) - 1) / 3.0; - _sx6 = _sx2 * ((3 * Math.Pow(_n, 3) * (_n + 2)) - (3 * _n) + 1) / 7.0; - _den = (_sx6 * _sx4 / _sx5) - _sx5; - - Name = "Afirma"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods for the sinc filter calculation. - /// The number of filter taps (filter length). Must be odd number. - /// The type of window function to apply (Rectangular, Hanning1, Hanning2, Blackman, or BlackmanHarris). - public Afirma(object source, int periods, int taps, WindowType window) : this(periods, taps, window) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateSincWeight(double x) - { - return Math.Abs(x) < 1e-10 ? 1.0 : Math.Sin(x) / x; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double GetWindowWeight(int k, int tapsMinusOne) - { - switch (Window) - { - case WindowType.Rectangular: - return 1.0; - case WindowType.Hanning1: - return 0.50 - (0.50 * Math.Cos(_twoPi * k / tapsMinusOne)); - case WindowType.Hanning2: - return 0.54 - (0.46 * Math.Cos(_twoPi * k / tapsMinusOne)); - case WindowType.Blackman: - return 0.42 - (0.50 * Math.Cos(_twoPi * k / tapsMinusOne)) + (0.08 * Math.Cos(_fourPi * k / tapsMinusOne)); - case WindowType.BlackmanHarris: - return 0.35875 - (0.48829 * Math.Cos(_twoPi * k / tapsMinusOne)) + - (0.14128 * Math.Cos(_fourPi * k / tapsMinusOne)) - - (0.01168 * Math.Cos(_sixPi * k / tapsMinusOne)); - default: - return 1.0; - } - } - - protected override double Calculation() - { - ManageState(IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - if (_index >= Taps) - { - CalculateAdaptiveCoefficients(); - } - - double result = 0.0; - for (int k = 0; k < Taps; k++) - { - result += _buffer[k] * _weights[k]; - } - - IsHot = _index >= WarmupPeriod; - return result / _wsum; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CalculateAdaptiveCoefficients() - { - double a0 = _buffer[_n]; - double a1 = _buffer[_n] - _buffer[_n + 1]; - double sx2y = 0.0; - double sx3y = 0.0; - - for (int i = 0; i <= _n; i++) - { - double i2 = i * i; - sx2y += i2 * _buffer[_n - i]; - sx3y += i2 * i * _buffer[_n - i]; - } - - sx2y = 2.0 * sx2y / _n / (_n + 1); - sx3y = 2.0 * sx3y / _n / (_n + 1); - double p = sx2y - (a0 * _sx2) - (a1 * _sx3); - double q = sx3y - (a0 * _sx3) - (a1 * _sx4); - double a2 = ((p * _sx6 / _sx5) - q) / _den; - double a3 = ((q * _sx4 / _sx5) - p) / _den; - - for (int k = 0; k <= _n; k++) - { - double k2 = k * k; - _armaBuffer[_n - k] = a0 + (k * a1) + (k2 * a2) + (k2 * k * a3); - } - } - - private double CalculateWeights() - { - double wsum = 0.0; - double centerTap = (Taps - 1) / 2.0; - int tapsMinusOne = Taps - 1; - - for (int k = 0; k < Taps; k++) - { - double windowWeight = GetWindowWeight(k, tapsMinusOne); - double x = Math.PI * (k - centerTap) / Periods; - double sincWeight = CalculateSincWeight(x); - - _weights[k] = windowWeight * sincWeight; - wsum += _weights[k]; - } - return wsum; - } -} diff --git a/lib/averages/Alma.cs b/lib/averages/Alma.cs deleted file mode 100644 index ea2ffede..00000000 --- a/lib/averages/Alma.cs +++ /dev/null @@ -1,115 +0,0 @@ - -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ALMA: Arnaud Legoux Moving Average -/// Uses the curve of the Normal (Gauss) distribution. This moving average reduces lag -/// of the data in conjunction with smoothing to reduce noise. -/// -/// -/// Validation: -/// Skender.Stock.Indicators -/// -public class Alma : AbstractBase -{ - private readonly int _period; - private readonly double _offset; - private readonly double _sigma; - private CircularBuffer? _buffer; - private CircularBuffer? _weight; - private double _norm; - - /// The number of data points used in the ALMA calculation. - /// Controls the smoothness and high-frequency filtering. Default is 0.85. - /// Controls the shape of the Gaussian distribution. Default is 6. - /// Thrown when period is less than 1. - public Alma(int period, double offset = 0.85, double sigma = 6) - { - if (period < 1) - { - throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - _offset = offset; - _sigma = sigma; - WarmupPeriod = period; - Name = "Alma"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the ALMA calculation. - /// Controls the smoothness and high-frequency filtering. Default is 0.85. - /// Controls the shape of the Gaussian distribution. Default is 6. - public Alma(object source, int period, double offset = 0.85, double sigma = 6) : this(period, offset, sigma) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - public override void Init() - { - base.Init(); - _buffer = new CircularBuffer(_period); - _weight = new CircularBuffer(_period); - _norm = 0; - } - - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - /// - /// Performs the core ALMA calculation. Called from parent abstractBase Calc() - /// - /// The calculated ALMA value. - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer!.Add(Input.Value, Input.IsNew); - if (_weight!.Count < _buffer.Count) - { - for (var i = 0; i < _buffer.Count - _weight.Count; i++) - { - _weight.Add(0.0); - } - } - - if (_buffer.Count <= _period) - { - UpdateWeights(); - } - - double weightedSum = 0; - for (var i = 0; i < _buffer.Count; i++) - { - weightedSum += _weight[i] * _buffer[i]; - } - - double result = weightedSum / _norm; - - IsHot = _index >= WarmupPeriod; - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void UpdateWeights() - { - int len = _buffer!.Count; - _norm = 0; - double m = _offset * (len - 1); - double s = len / _sigma; - for (int i = 0; i < len; i++) - { - double wt = Math.Exp(-((i - m) * (i - m)) / (2 * s * s)); - _weight![i] = wt; - _norm += wt; - } - } -} \ No newline at end of file diff --git a/lib/averages/Convolution.cs b/lib/averages/Convolution.cs deleted file mode 100644 index 0a678577..00000000 --- a/lib/averages/Convolution.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Convolution: A fundamental signal processing operation that combines two signals to form a third signal -/// Applies a custom kernel (weight array) to the input data through convolution, allowing for flexible -/// filtering operations. The kernel is automatically normalized to ensure consistent output scaling. -/// -/// -/// Implementation: -/// Based on standard discrete convolution principles from signal processing -/// -public class Convolution : AbstractBase -{ - private readonly double[] _kernel; - private readonly int _kernelSize; - private readonly CircularBuffer _buffer; - private readonly double[] _normalizedKernel; - private int _activeLength; - - /// Array of weights defining the convolution operation. The length of this array determines the filter's window size. - /// Thrown when kernel is null or empty. - public Convolution(double[] kernel) - { - if (kernel == null || kernel.Length == 0) - { - throw new ArgumentException("Kernel must not be null or empty.", nameof(kernel)); - } - _kernel = kernel; - _kernelSize = kernel.Length; - _buffer = new CircularBuffer(_kernelSize); - _normalizedKernel = new double[_kernelSize]; - Init(); - } - - /// The data source object that publishes updates. - /// Array of weights defining the convolution operation. - public Convolution(object source, double[] kernel) : this(kernel) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _buffer.Clear(); - System.Array.Copy(_kernel, _normalizedKernel, _kernelSize); - _activeLength = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _activeLength = System.Math.Min(_index, _kernelSize); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double GetLastValid() - { - return _lastValidValue; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - // Normalize kernel on each calculation until buffer is full - if (_index <= _kernelSize) - { - NormalizeKernel(); - } - - double result = ConvolveBuffer(); - IsHot = _index >= _kernelSize; - - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void NormalizeKernel() - { - double sum = 0; - - // Calculate the sum of the active kernel elements - for (int i = 0; i < _activeLength; i++) - { - sum += _kernel[i]; - } - - // Normalize the kernel or set equal weights if the sum is zero - double normalizationFactor = (sum >= double.Epsilon) ? sum : _activeLength; - double invNormFactor = 1.0 / normalizationFactor; - - for (int i = 0; i < _activeLength; i++) - { - _normalizedKernel[i] = _kernel[i] * invNormFactor; - } - - // Set the rest of the normalized kernel to zero - if (_activeLength < _kernelSize) - { - System.Array.Clear(_normalizedKernel, _activeLength, _kernelSize - _activeLength); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double ConvolveBuffer() - { - double sum = 0; - var bufferSpan = _buffer.GetSpan(); - int offset = _activeLength - 1; - - // Unroll the loop for better performance when possible - int i = 0; - while (i <= offset - 3) - { - sum += (bufferSpan[offset - i] * _normalizedKernel[i]) + - (bufferSpan[offset - (i + 1)] * _normalizedKernel[i + 1]) + - (bufferSpan[offset - (i + 2)] * _normalizedKernel[i + 2]) + - (bufferSpan[offset - (i + 3)] * _normalizedKernel[i + 3]); - i += 4; - } - - // Handle remaining elements - while (i < _activeLength) - { - sum += bufferSpan[offset - i] * _normalizedKernel[i]; - i++; - } - - return sum; - } -} diff --git a/lib/averages/Dema.cs b/lib/averages/Dema.cs deleted file mode 100644 index 3f543649..00000000 --- a/lib/averages/Dema.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DEMA: Double Exponential Moving Average -/// DEMA reduces the lag of a traditional EMA by applying a second EMA over EMA. -/// It responds more quickly to price changes than a standard EMA while maintaining -/// smoothness, at the cost of overshooting the signal line. -/// -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Double_exponential_moving_average -/// https://www.investopedia.com/terms/d/double-exponential-moving-average.asp -/// https://www.tradingview.com/support/solutions/43000502589-double-exponential-moving-average-dema/ -/// -/// Validation: -/// Skender.Stock.Indicators -/// -public class Dema : AbstractBase -{ - private readonly double _k; - private readonly double _epsilon = 1e-10; - private double _lastEma1, _p_lastEma1; - private double _lastEma2, _p_lastEma2; - private double _e, _p_e; - - public Dema(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - _k = 2.0 / (period + 1); - Name = "Dema"; - double percentile = 0.85; //targeting 85th percentile of correctness of converging EMA - WarmupPeriod = (int)System.Math.Ceiling(-period * System.Math.Log(1 - percentile)); - Init(); - } - - public Dema(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _e = 1.0; - _lastEma1 = 0; - _lastEma2 = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastEma1 = _lastEma1; - _p_lastEma2 = _lastEma2; - _p_e = _e; - _index++; - } - else - { - _lastEma1 = _p_lastEma1; - _lastEma2 = _p_lastEma2; - _e = _p_e; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateEma(double input, double lastEma) - { - return (_k * (input - lastEma)) + lastEma; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Compensator for early EMA values - _e = (_e > _epsilon) ? (1 - _k) * _e : 0; - double invE = (_e > _epsilon) ? 1 / (1 - _e) : 1; - - // Calculate EMAs - double ema1 = CalculateEma(Input.Value, _lastEma1); - double compensatedEma1 = ema1 * invE; - double ema2 = CalculateEma(compensatedEma1, _lastEma2); - - // Store values for next iteration - _lastEma1 = ema1; - _lastEma2 = ema2; - - // Calculate final DEMA - double result = (2 * compensatedEma1) - (ema2 * invE); - - IsHot = _index >= WarmupPeriod; - return result; - } -} diff --git a/lib/averages/Dsma.cs b/lib/averages/Dsma.cs deleted file mode 100644 index 238a78f7..00000000 --- a/lib/averages/Dsma.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DSMA: Deviation Scaled Moving Average -/// Adaptive moving average that adjusts its smoothing factor based on the volatility of the input data. -/// It aims to be more responsive during trending periods and more stable during ranging periods. -/// -/// -/// The DSMA uses a SuperSmoother filter to reduce noise and a dynamic alpha calculation based on the -/// scaled deviation of the input data. This allows it to adapt to changing market conditions. -/// -/// The algorithm involves these main steps: -/// 1. Apply a SuperSmoother filter to the zero-mean input data. -/// 2. Calculate the Root Mean Square (RMS) of the filtered data. -/// 3. Scale the filtered data by the RMS to get a measure in terms of standard deviations. -/// 4. Use the scaled deviation to calculate an adaptive alpha for the moving average. -/// -/// Source: -/// https://www.mesasoftware.com/papers/DEVIATION%20SCALED%20MOVING%20AVERAGE.pdf -/// -public class Dsma : AbstractBase -{ - private readonly CircularBuffer _buffer; - private readonly double _c2, _c3; - private readonly double _scaleFactor; - private readonly double _periodRecip; // 1/_period - private readonly double _scaleByPeriod; // 5/_period - private readonly double _c1Half; // _c1/2 - - private double _lastDsma, _p_lastDsma; - private double _filt, _filt1, _filt2, _zeros, _zeros1; - private double _p_filt, _p_filt1, _p_filt2, _p_zeros, _p_zeros1; - private bool _isInit, _p_isInit; - - /// - /// Initializes a new instance of the class. - /// - /// The number of data points used in the DSMA calculation. - /// Thrown when period is less than 1. - public Dsma(int period, double scaleFactor = 0.9) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - if (scaleFactor <= 0 || scaleFactor > 1) - { - throw new ArgumentOutOfRangeException(nameof(scaleFactor), "Scale factor must be between 0 and 1 (exclusive)."); - } - _periodRecip = 1.0 / period; - _scaleFactor = scaleFactor; - _buffer = new CircularBuffer(period); - - // SuperSmoother filter coefficients - double halfPeriod = 0.5 * period; - double a1 = System.Math.Exp(-1.414 * System.Math.PI / halfPeriod); - double b1 = 2.0 * a1 * System.Math.Cos(1.414 * System.Math.PI / halfPeriod); - - _c2 = b1; - _c3 = -a1 * a1; - double _c1 = 1.0 - _c2 - _c3; - _c1Half = _c1 * 0.5; - _scaleByPeriod = 5.0 / period; - - Name = "Dsma"; - WarmupPeriod = (int)(period * 1.5); // A conservative estimate - Init(); - } - - public Dsma(object source, int period, double scaleFactor = 0.9) : this(period, scaleFactor) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _lastDsma = 0; - _filt = _filt1 = _filt2 = 0; - _zeros = _zeros1 = 0; - _isInit = false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastDsma = _lastDsma; - _p_isInit = _isInit; - _p_zeros = _zeros; - _p_zeros1 = _zeros1; - _p_filt = _filt; - _p_filt1 = _filt1; - _p_filt2 = _filt2; - _index++; - } - else - { - _lastDsma = _p_lastDsma; - _isInit = _p_isInit; - _zeros = _p_zeros; - _zeros1 = _p_zeros1; - _filt = _p_filt; - _filt1 = _p_filt1; - _filt2 = _p_filt2; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateSuperSmootherFilter() - { - return (_c1Half * (_zeros + _zeros1)) + (_c2 * _filt1) + (_c3 * _filt2); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateAdaptiveAlpha(double scaledFilt) - { - double alpha = _scaleFactor * System.Math.Abs(scaledFilt) * _scaleByPeriod; - return System.Math.Clamp(alpha, 0.1, 1.0); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (!_isInit) - { - _lastDsma = Input.Value; - _isInit = true; - return _lastDsma; - } - - // Produce nominal zero mean - _zeros = Input.Value - _lastDsma; - - // SuperSmoother Filter - _filt = CalculateSuperSmootherFilter(); - - // Update buffer for RMS calculation - double filtSquared = _filt * _filt; - _buffer.Add(filtSquared, Input.IsNew); - - // Compute RMS (Root Mean Square) - double rms = System.Math.Sqrt(_buffer.Sum() * _periodRecip); - - // Rescale Filt in terms of Standard Deviations and calculate adaptive alpha - double scaledFilt = rms > 0 ? _filt / rms : 0; - double alpha = CalculateAdaptiveAlpha(scaledFilt); - - // DSMA calculation - double dsma = (alpha * Input.Value) + ((1 - alpha) * _lastDsma); - - // Update state variables - _zeros1 = _zeros; - _filt2 = _filt1; - _filt1 = _filt; - _lastDsma = dsma; - - IsHot = _index >= WarmupPeriod; - return dsma; - } -} diff --git a/lib/averages/Dwma.cs b/lib/averages/Dwma.cs deleted file mode 100644 index 864d4688..00000000 --- a/lib/averages/Dwma.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DWMA: Double Weighted Moving Average -/// DWMA is a technical indicator that applies a Weighted Moving Average (WMA) twice to the input data. -/// The weights are decreasing over the period with p^2 decay, and the most recent data has the heaviest weight. -/// -/// -/// The DWMA is calculated by applying two WMAs in sequence: -/// 1. An inner WMA is applied to the input data. -/// 2. An outer WMA is then applied to the result of the inner WMA. -/// -/// Key characteristics: -/// - The weight distribution follows a p^2 decay, where p is the position of the data point. -/// - More recent data points receive higher weights, emphasizing recent price movements. -/// - The double application of WMA results in a smoother indicator compared to a single WMA. -/// -/// The formula for DWMA can be expressed as: -/// DWMA = WMA(WMA(price, period), period) -/// -/// Where WMA is the Weighted Moving Average function and 'period' is the number of data points used in each WMA calculation. -/// -public class Dwma : AbstractBase -{ - private readonly Wma _innerWma; - private readonly Wma _outerWma; - - public Dwma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _innerWma = new Wma(period); - _outerWma = new Wma(period); - Name = "Dwma"; - WarmupPeriod = (2 * period) - 1; - Init(); - } - - public Dwma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _innerWma.Init(); - _outerWma.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double GetLastValid() - { - return _lastValidValue; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate inner WMA - var innerResult = _innerWma.Calc(Input); - - // Calculate outer WMA using the result of inner WMA - var outerResult = _outerWma.Calc(innerResult); - - IsHot = _index >= WarmupPeriod; - return outerResult.Value; - } -} diff --git a/lib/averages/Ema.cs b/lib/averages/Ema.cs deleted file mode 100644 index 0470dac9..00000000 --- a/lib/averages/Ema.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// EMA: Exponential Moving Average -/// -/// -/// EMA needs very short history buffer and calculates the EMA value using just the -/// previous EMA value. The weight of the new datapoint (alpha) is alpha = 2 / (period + 1) -/// -/// Key characteristics: -/// - Uses no buffer, relying only on the previous EMA value. -/// - The weight of new data points is calculated as alpha = 2 / (period + 1). -/// - Provides a balance between responsiveness and smoothing. No overshooting. Significant lag -/// -/// Calculation method: -/// This implementation can use SMA for the first Period bars as a seeding value for EMA when useSma is true. -/// -/// Sources: -/// - https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages -/// - https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp -/// - https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA -/// -public class Ema : AbstractBase -{ - private readonly int _period; - private readonly double _k; - private readonly bool _useSma; - private readonly double _epsilon = 1e-10; - private CircularBuffer _sma; - private double _lastEma, _p_lastEma; - private double _e, _p_e; - private bool _isInit, _p_isInit; - - /// - /// Initializes a new instance of the Ema class with a specified period. - /// - /// The period for EMA calculation. - /// Whether to use SMA for initial values. Default is true. - /// Thrown when period is less than 1. - public Ema(int period, bool useSma = true) - { - if (period < 1) - { - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - _period = period; - _k = 2.0 / (_period + 1); - _useSma = useSma; - _sma = new(_period); - Name = "Ema"; - WarmupPeriod = (int)System.Math.Ceiling(System.Math.Log(0.05) / System.Math.Log(1 - _k)); //95th percentile - Init(); - } - - /// - /// Initializes a new instance of the Ema class with a specified alpha value. - /// - /// The smoothing factor for EMA calculation. - public Ema(double alpha) - { - _k = alpha; - _useSma = false; - _sma = new(1); - Name = "Ema"; - _period = 1; - WarmupPeriod = (int)System.Math.Ceiling(System.Math.Log(0.05) / System.Math.Log(1 - _k)); //95th percentile - Init(); - } - - /// - /// Initializes a new instance of the Ema class with a specified source and period. - /// - /// The source object for event subscription. - /// The period for EMA calculation. - /// Whether to use SMA for initial values. Default is true. - public Ema(object source, int period, bool useSma = true) : this(period, useSma) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _e = 1.0; - _lastEma = 0; - _isInit = false; - _p_isInit = false; - _sma = new(_period); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastEma = _lastEma; - _p_isInit = _isInit; - _p_e = _e; - _index++; - } - else - { - _lastEma = _p_lastEma; - _isInit = _p_isInit; - _e = _p_e; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateEma(double input, double lastEma) - { - return (_k * (input - lastEma)) + lastEma; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CompensateEma(double ema) - { - return (_useSma || _e <= _epsilon) ? ema : ema / (1 - _e); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double ema; - if (!_isInit && _useSma) - { - _sma.Add(Input.Value, Input.IsNew); - ema = _sma.Average(); - if (_index >= _period) - { - _isInit = true; - } - } - else - { - // Compensator for early EMA values - _e = (_e > _epsilon) ? (1 - _k) * _e : 0; - ema = CalculateEma(Input.Value, _lastEma); - ema = CompensateEma(ema); - } - - _lastEma = ema; - IsHot = _index >= WarmupPeriod; - return ema; - } -} diff --git a/lib/averages/Epma.cs b/lib/averages/Epma.cs deleted file mode 100644 index 6cad88c7..00000000 --- a/lib/averages/Epma.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// EPMA: Endpoint Moving Average -/// A moving average that uses a specialized convolution kernel to emphasize recent price movements -/// while maintaining a connection to historical data. The weights decrease linearly with a focus -/// on endpoints. -/// -/// -/// The EPMA uses a unique weighting scheme where: -/// - The most recent price gets the highest weight: (2 * period - 1) -/// - Each previous price gets a weight reduced by 3: (2 * period - 1) - 3i -/// - Weights are normalized to sum to 1 -/// -/// Key characteristics: -/// - Emphasizes recent price movements more than traditional moving averages -/// - Maintains some influence from historical data -/// - Uses convolution for efficient calculation -/// - Provides better endpoint preservation than simple moving averages -/// -/// Implementation: -/// Original implementation based on convolution principles -/// -public class Epma : AbstractBase -{ - private readonly int _period; - private readonly Convolution _convolution; - - /// The number of data points used in the EPMA calculation. - /// Thrown when period is less than 1. - public Epma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - double[] _baseKernel = GenerateKernel(_period); - _convolution = new Convolution(_baseKernel); - Name = "Epma"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the EPMA calculation. - public Epma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateKernelSum(int period) - { - // Using arithmetic sequence sum formula: n(a1 + an)/2 - // where a1 = (2p-1) and an = (2p-1) - 3(n-1) - double firstTerm = (2 * period) - 1; - double lastTerm = firstTerm - (3 * (period - 1)); - return period * (firstTerm + lastTerm) * 0.5; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - double result = convolutionResult.Value; - - // Adjust for partial periods during warmup - if (_index < _period) - { - result *= CalculateKernelSum(_period) / CalculateKernelSum(_index); - } - - IsHot = _index >= WarmupPeriod; - return result; - } - - /// - /// Generates the convolution kernel for the EPMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of normalized weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double[] GenerateKernel(int period) - { - double[] kernel = new double[period]; - double weightSum = CalculateKernelSum(period); - double invWeightSum = 1.0 / weightSum; - double baseWeight = (2 * period) - 1; - - for (int i = 0; i < period; i++) - { - kernel[i] = (baseWeight - (3 * i)) * invWeightSum; - } - - return kernel; - } -} diff --git a/lib/averages/Frama.cs b/lib/averages/Frama.cs deleted file mode 100644 index 10db1698..00000000 --- a/lib/averages/Frama.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// FRAMA: Fractal Adaptive Moving Average -/// An adaptive moving average that adjusts its smoothing factor based on the fractal dimension -/// of the price series. FRAMA automatically adapts to market conditions, becoming more responsive -/// during trends and more stable during sideways markets. -/// -/// -/// The FRAMA algorithm works by: -/// 1. Calculating the fractal dimension of the price series -/// 2. Using this dimension to determine the optimal alpha (smoothing factor) -/// 3. Applying an EMA with the adaptive alpha -/// -/// Key characteristics: -/// - Self-adaptive to market conditions -/// - Reduces lag during trending periods -/// - Increases smoothing during sideways markets -/// - Uses fractal geometry principles for market analysis -/// -/// Sources: -/// John Ehlers - "FRAMA: A Trend-Following Indicator" -/// https://www.mesasoftware.com/papers/FRAMA.pdf -/// -public class Frama : AbstractBase -{ - private readonly int _period; - private readonly int _halfPeriod; - private readonly double _periodRecip; - private readonly double _halfPeriodRecip; - private readonly double _log2 = System.Math.Log(2); - private readonly double _epsilon = double.Epsilon; - private readonly CircularBuffer _buffer; - private double _lastFrama; - private double _prevLastFrama; - - /// The number of periods used for fractal dimension calculation. Must be at least 2. - /// Thrown when period is less than 2. - public Frama(int period) - { - if (period < 2) - throw new System.ArgumentException("Period must be at least 2", nameof(period)); - - _period = period; - _halfPeriod = period / 2; - _periodRecip = 1.0 / period; - _halfPeriodRecip = 1.0 / _halfPeriod; - _buffer = new CircularBuffer(period); - WarmupPeriod = period; - } - - /// The data source object that publishes updates. - /// The number of periods used for fractal dimension calculation. - public Frama(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _lastFrama = 0; - _prevLastFrama = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _prevLastFrama = _lastFrama; - _index++; - } - else - { - _lastFrama = _prevLastFrama; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void UpdateMinMax(double price, ref double high, ref double low) - { - high = System.Math.Max(high, price); - low = System.Math.Min(low, price); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateAlpha(double dimension) - { - double alpha = System.Math.Exp(-4.6 * (dimension - 1)); - return System.Math.Clamp(alpha, 0.01, 1.0); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double GetLastValid() - { - return _lastFrama; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer.Add(Input.Value, Input.IsNew); - - if (_buffer.Count < _period) - { - _lastFrama = _buffer.Average(); - return _lastFrama; - } - - double hh = double.MinValue, ll = double.MaxValue; - double hh1 = double.MinValue, ll1 = double.MaxValue; - double hh2 = double.MinValue, ll2 = double.MaxValue; - - for (int i = 0; i < _period; i++) - { - double price = _buffer[i]; - UpdateMinMax(price, ref hh, ref ll); - - if (i < _halfPeriod) - { - UpdateMinMax(price, ref hh1, ref ll1); - } - else - { - UpdateMinMax(price, ref hh2, ref ll2); - } - } - - double n1 = (hh - ll) * _periodRecip; - double n2 = (hh1 - ll1 + hh2 - ll2) * _halfPeriodRecip; - - double dimension = (System.Math.Log(n2 + _epsilon) - System.Math.Log(n1 + _epsilon)) / _log2; - double alpha = CalculateAlpha(dimension); - - _lastFrama = (alpha * (Input.Value - _lastFrama)) + _lastFrama; - - IsHot = _index >= WarmupPeriod; - return _lastFrama; - } -} diff --git a/lib/averages/Fwma.cs b/lib/averages/Fwma.cs deleted file mode 100644 index eb8f2618..00000000 --- a/lib/averages/Fwma.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// FWMA: Fibonacci Weighted Moving Average -/// A moving average that uses Fibonacci numbers as weights in its calculation. The weights -/// are arranged in reverse order so that recent prices receive higher weights corresponding -/// to larger Fibonacci numbers. -/// -/// -/// The FWMA calculation process: -/// 1. Generates a Fibonacci sequence up to the specified period -/// 2. Reverses the sequence to give higher weights to recent prices -/// 3. Normalizes the weights to sum to 1 -/// 4. Applies the weights through convolution -/// -/// Key characteristics: -/// - Uses Fibonacci sequence for weight distribution -/// - Recent prices receive higher weights -/// - Natural progression of weights based on the golden ratio -/// - Implemented using efficient convolution operations -/// -/// Implementation: -/// Original implementation based on Fibonacci sequence principles -/// -public class Fwma : AbstractBase -{ - private readonly Convolution _convolution; - - /// The number of data points used in the FWMA calculation. - /// Thrown when period is less than 1. - public Fwma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - double[] _kernel = GenerateKernel(period); - _convolution = new Convolution(_kernel); - Name = "Fwma"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the FWMA calculation. - public Fwma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - /// - /// Generates the Fibonacci-based convolution kernel for the FWMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of normalized Fibonacci-based weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double[] GenerateKernel(int period) - { - double[] kernel = new double[period]; - double[] fibSeries = new double[period]; - - // Generate Fibonacci series with running sum - fibSeries[0] = fibSeries[1] = 1; - double weightSum = 2.0; // Initial sum for first two Fibonacci numbers - - for (int i = 2; i < period; i++) - { - fibSeries[i] = fibSeries[i - 1] + fibSeries[i - 2]; - weightSum += fibSeries[i]; - } - - // Calculate inverse of weight sum for normalization - double invWeightSum = 1.0 / weightSum; - - // Reverse and normalize the series in one pass - for (int i = 0; i < period; i++) - { - kernel[i] = fibSeries[period - 1 - i] * invWeightSum; - } - - return kernel; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - IsHot = _index >= WarmupPeriod; - - return convolutionResult.Value; - } -} diff --git a/lib/averages/Gma.cs b/lib/averages/Gma.cs deleted file mode 100644 index c0828318..00000000 --- a/lib/averages/Gma.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// GMA: Gaussian Moving Average -/// A moving average that uses weights based on the Gaussian (normal) distribution curve. -/// This creates a smooth, bell-shaped weighting scheme that gives maximum weight to the -/// center of the period and gradually decreasing weights towards the edges. -/// -/// -/// The GMA calculation process: -/// 1. Creates a Gaussian distribution of weights centered on the period -/// 2. Normalizes the weights to sum to 1 -/// 3. Applies the weights through convolution -/// -/// Key characteristics: -/// - Smooth, symmetric weight distribution -/// - Natural bell curve weighting -/// - Reduces noise while preserving signal characteristics -/// - Less sensitive to outliers than simple moving averages -/// - Implemented using efficient convolution operations -/// -/// Implementation: -/// Based on Gaussian distribution principles from statistics -/// -public class Gma : AbstractBase -{ - private readonly Convolution _convolution; - - /// The number of data points used in the GMA calculation. - /// Thrown when period is less than 1. - public Gma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - double[] _kernel = GenerateKernel(period); - _convolution = new Convolution(_kernel); - Name = "Gma"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the GMA calculation. - public Gma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - /// - /// Generates the Gaussian-based convolution kernel for the GMA calculation. - /// - /// The period for which to generate the kernel. - /// The standard deviation parameter controlling the spread of the Gaussian curve. Default is 1.0. - /// An array of normalized Gaussian-based weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double[] GenerateKernel(int period, double sigma = 1.0) - { - double[] kernel = new double[period]; - double weightSum = 0; - int center = period / 2; - double centerRecip = 1.0 / center; - double sigmaSquared2 = 2.0 * sigma * sigma; - - // Calculate weights and sum in one pass - for (int i = 0; i < period; i++) - { - double x = (i - center) * centerRecip; - kernel[i] = System.Math.Exp(-(x * x) / sigmaSquared2); - weightSum += kernel[i]; - } - - // Normalize using multiplication instead of division - double invWeightSum = 1.0 / weightSum; - for (int i = 0; i < period; i++) - { - kernel[i] *= invWeightSum; - } - - return kernel; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - IsHot = _index >= WarmupPeriod; - - return convolutionResult.Value; - } -} diff --git a/lib/averages/Hma.cs b/lib/averages/Hma.cs deleted file mode 100644 index d36c9f34..00000000 --- a/lib/averages/Hma.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// HMA: Hull Moving Average -/// A moving average designed by Alan Hull to reduce lag while maintaining smoothness. -/// It combines weighted moving averages of different periods to achieve better -/// responsiveness to price changes while minimizing noise. -/// -/// -/// The HMA calculation process: -/// 1. Calculate WMA with period n/2 -/// 2. Calculate WMA with period n -/// 3. Calculate difference: 2*WMA(n/2) - WMA(n) -/// 4. Apply final WMA with period sqrt(n) to the difference -/// -/// Key characteristics: -/// - Significantly reduced lag compared to traditional moving averages -/// - Maintains smoothness despite the reduced lag -/// - Responds more quickly to price changes -/// - Better at identifying trend changes -/// - Uses weighted moving averages for all calculations -/// -/// Sources: -/// Alan Hull - "Better Trading with Hull Moving Average" -/// https://alanhull.com/hull-moving-average -/// -public class Hma : AbstractBase -{ - private readonly Convolution _wmaHalf, _wmaFull, _wmaFinal; - - /// The number of data points used in the HMA calculation. Must be at least 2. - /// Thrown when period is less than 2. - public Hma(int period) - { - if (period < 2) - { - throw new System.ArgumentException("Period must be greater than or equal to 2.", nameof(period)); - } - int _sqrtPeriod = (int)System.Math.Sqrt(period); - - // Generate all kernels once - double[] _kernelHalf = GenerateWmaKernel(period / 2); - double[] _kernelFull = GenerateWmaKernel(period); - double[] _kernelFinal = GenerateWmaKernel(_sqrtPeriod); - - // Initialize convolutions with pre-generated kernels - _wmaHalf = new Convolution(_kernelHalf); - _wmaFull = new Convolution(_kernelFull); - _wmaFinal = new Convolution(_kernelFinal); - - Name = "Hma"; - WarmupPeriod = period + _sqrtPeriod - 1; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the HMA calculation. - public Hma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - /// - /// Generates the weighted moving average kernel for the HMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of linearly weighted values for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double[] GenerateWmaKernel(int period) - { - double[] kernel = new double[period]; - double weightSum = period * (period + 1) * 0.5; // Multiply by 0.5 instead of dividing by 2 - double invWeightSum = 1.0 / weightSum; - - for (int i = 0; i < period; i++) - { - kernel[i] = (period - i) * invWeightSum; - } - - return kernel; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _wmaHalf.Init(); - _wmaFull.Init(); - _wmaFinal.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate WMA(n/2) and WMA(n) - double wmaHalfResult = _wmaHalf.Calc(Input).Value; - double wmaFullResult = _wmaFull.Calc(Input).Value; - - // Calculate 2*WMA(n/2) - WMA(n) - double intermediateResult = (2.0 * wmaHalfResult) - wmaFullResult; - - // Calculate final WMA - var finalInput = new TValue(Input.Time, intermediateResult, Input.IsNew); - double result = _wmaFinal.Calc(finalInput).Value; - - IsHot = _index >= WarmupPeriod; - return result; - } -} diff --git a/lib/averages/Htit.cs b/lib/averages/Htit.cs deleted file mode 100644 index 6e04311d..00000000 --- a/lib/averages/Htit.cs +++ /dev/null @@ -1,184 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// HTIT: Hilbert Transform Instantaneous Trendline -/// A sophisticated moving average that uses the Hilbert Transform to identify the dominant cycle -/// period in price data and create a smooth trend line. It adapts to the market's natural cycles -/// and provides a dynamic moving average. -/// -/// -/// The HTIT calculation process: -/// 1. Uses a Hilbert Transform to decompose price into in-phase and quadrature components -/// 2. Employs a homodyne discriminator to determine the dominant cycle period -/// 3. Applies smoothing based on the detected cycle period -/// 4. Creates a trend line that automatically adapts to market cycles -/// -/// Key characteristics: -/// - Automatically adapts to market cycles -/// - Reduces lag by using cycle analysis -/// - Complex signal processing for better trend identification -/// - Combines multiple digital signal processing techniques -/// -/// Sources: -/// John Ehlers - "Cycle Analytics for Traders" -/// -/// Note: This implementation is currently under development and may not pass -/// all consistency tests. -/// -public class Htit : AbstractBase -{ - private readonly CircularBuffer _priceBuffer = new(7); - private readonly CircularBuffer _spBuffer = new(7); - private readonly CircularBuffer _dtBuffer = new(7); - private readonly CircularBuffer _i1Buffer = new(7); - private readonly CircularBuffer _q1Buffer = new(7); - private readonly CircularBuffer _i2Buffer = new(2); - private readonly CircularBuffer _q2Buffer = new(2); - private readonly CircularBuffer _reBuffer = new(2); - private readonly CircularBuffer _imBuffer = new(2); - private readonly CircularBuffer _pdBuffer = new(2); - private readonly CircularBuffer _sdBuffer = new(2); - private readonly CircularBuffer _itBuffer = new(4); - - private const double ALPHA = 0.2; - private const double BETA = 0.8; - private const double TWO_PI = 2.0 * System.Math.PI; - private const double MIN_PERIOD = 6.0; - private const double MAX_PERIOD = 50.0; - private const double PERIOD_UPPER_LIMIT = 1.5; - private const double PERIOD_LOWER_LIMIT = 0.67; - - private double _lastPd = 0; - private double _p_lastPd = 0; - - public Htit() - { - Name = "Htit"; - WarmupPeriod = 12; - } - - public Htit(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastPd = _lastPd; - _index++; - } - else - { - _lastPd = _p_lastPd; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateSmoothedPrice(double p0, double p1, double p2, double p3) - { - return ((4.0 * p0) + (3.0 * p1) + (2.0 * p2) + p3) * 0.1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateHilbertTransform(double b0, double b2, double b4, double b6, double adj) - { - return ((0.0962 * (b0 - b6)) + (0.5769 * (b2 - b4))) * adj; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double ClampPeriod(double pd, double lastPd) - { - pd = pd > PERIOD_UPPER_LIMIT * lastPd ? PERIOD_UPPER_LIMIT * lastPd : pd; - pd = pd < PERIOD_LOWER_LIMIT * lastPd ? PERIOD_LOWER_LIMIT * lastPd : pd; - return System.Math.Clamp(pd, MIN_PERIOD, MAX_PERIOD); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double pr = Input.Value; - _priceBuffer.Add(pr, Input.IsNew); - - if (_index <= 5) - { - _spBuffer.Add(0, Input.IsNew); - _dtBuffer.Add(0, Input.IsNew); - _i1Buffer.Add(0, Input.IsNew); - _q1Buffer.Add(0, Input.IsNew); - _i2Buffer.Add(0, Input.IsNew); - _q2Buffer.Add(0, Input.IsNew); - _reBuffer.Add(0, Input.IsNew); - _imBuffer.Add(0, Input.IsNew); - _pdBuffer.Add(0, Input.IsNew); - _sdBuffer.Add(0, Input.IsNew); - _itBuffer.Add(pr, Input.IsNew); - return pr; - } - - double adj = (0.075 * _lastPd) + 0.54; - - // Smooth and detrender - double sp = CalculateSmoothedPrice(_priceBuffer[0], _priceBuffer[1], _priceBuffer[2], _priceBuffer[3]); - _spBuffer.Add(sp, Input.IsNew); - - double dt = CalculateHilbertTransform(_spBuffer[0], _spBuffer[2], _spBuffer[4], _spBuffer[6], adj); - _dtBuffer.Add(dt, Input.IsNew); - - // In-phase and quadrature - double q1 = CalculateHilbertTransform(_dtBuffer[0], _dtBuffer[2], _dtBuffer[4], _dtBuffer[6], adj); - _q1Buffer.Add(q1, Input.IsNew); - - double i1 = _dtBuffer[3]; - _i1Buffer.Add(i1, Input.IsNew); - - // Advance the phases by 90 degrees - double jI = CalculateHilbertTransform(_i1Buffer[0], _i1Buffer[2], _i1Buffer[4], _i1Buffer[6], adj); - double jQ = CalculateHilbertTransform(_q1Buffer[0], _q1Buffer[2], _q1Buffer[4], _q1Buffer[6], adj); - - // Phasor addition for 3-bar averaging - double i2 = (ALPHA * (i1 - jQ)) + (BETA * _i2Buffer[0]); - double q2 = (ALPHA * (q1 + jI)) + (BETA * _q2Buffer[0]); - - _i2Buffer.Add(i2, Input.IsNew); - _q2Buffer.Add(q2, Input.IsNew); - - // Homodyne discriminator - double re = (ALPHA * ((i2 * _i2Buffer[1]) + (q2 * _q2Buffer[1]))) + (BETA * _reBuffer[0]); - double im = (ALPHA * ((i2 * _q2Buffer[1]) - (q2 * _i2Buffer[1]))) + (BETA * _imBuffer[0]); - - _reBuffer.Add(re, Input.IsNew); - _imBuffer.Add(im, Input.IsNew); - - // Calculate period - double pd = (im >= double.Epsilon && re >= double.Epsilon) ? TWO_PI / System.Math.Atan(im / re) : 0; - pd = ClampPeriod(pd, _lastPd); - pd = (ALPHA * pd) + (BETA * _lastPd); - _pdBuffer.Add(pd, Input.IsNew); - - double sd = (0.33 * pd) + (0.67 * _sdBuffer[0]); - _sdBuffer.Add(sd, Input.IsNew); - - // Smooth dominant cycle period - int dcPeriods = (int)(sd + 0.5); - double sumPr = _priceBuffer.GetSpan().Slice(0, System.Math.Min(dcPeriods, _priceBuffer.Count)).ToArray().Sum(); - double it = dcPeriods > 0 ? sumPr / dcPeriods : pr; - _itBuffer.Add(it, Input.IsNew); - - _p_lastPd = _lastPd; - _lastPd = pd; - - // Final indicator - if (_index >= 11) - { - return CalculateSmoothedPrice(_itBuffer[0], _itBuffer[1], _itBuffer[2], _itBuffer[3]); - } - - return pr; - } -} diff --git a/lib/averages/Hwma.cs b/lib/averages/Hwma.cs deleted file mode 100644 index 60a73752..00000000 --- a/lib/averages/Hwma.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// HWMA: Holt-Winters Moving Average -/// A triple exponential smoothing method that incorporates level (F), velocity (V), and -/// acceleration (A) components to create a responsive yet smooth moving average. This -/// implementation uses optimized smoothing factors for each component. -/// -/// -/// The HWMA calculation process: -/// 1. Updates the level (F) component using alpha smoothing -/// 2. Updates the velocity (V) component using beta smoothing -/// 3. Updates the acceleration (A) component using gamma smoothing -/// 4. Combines all components for final value: F + V + 0.5A -/// -/// Key characteristics: -/// - Adapts to both trends and acceleration in price movement -/// - Three separate smoothing factors for fine-tuned control -/// - More responsive to changes than simple moving averages -/// - Handles both linear and non-linear trends -/// -/// Implementation: -/// Based on Holt-Winters triple exponential smoothing principles -/// with optimized default parameters: -/// - Alpha (nA) = 2/(period + 1) -/// - Beta (nB) = 1/period -/// - Gamma (nC) = 1/period -/// -public class Hwma : AbstractBase -{ - private readonly int _period; - private readonly double _nA, _nB, _nC; - private readonly double _oneMinusNa, _oneMinusNb, _oneMinusNc; - private readonly double _halfA = 0.5; - private double _pF, _pV, _pA; - private double _ppF, _ppV, _ppA; - - /// The number of data points used in the HWMA calculation. - public Hwma(int period) : this(period, 2.0 / (1 + period), 1.0 / period, 1.0 / period) - { - } - - /// Alpha smoothing factor for the level component. - /// Beta smoothing factor for the velocity component. - /// Gamma smoothing factor for the acceleration component. - public Hwma(double nA, double nB, double nC) : this((int)((2 - nA) / nA), nA, nB, nC) - { - } - - /// The number of data points used in the HWMA calculation. - /// Alpha smoothing factor for the level component. - /// Beta smoothing factor for the velocity component. - /// Gamma smoothing factor for the acceleration component. - /// Thrown when period is less than 1. - public Hwma(int period, double nA, double nB, double nC) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - _nA = nA; - _nB = nB; - _nC = nC; - _oneMinusNa = 1.0 - nA; - _oneMinusNb = 1.0 - nB; - _oneMinusNc = 1.0 - nC; - WarmupPeriod = period; - Name = $"Hwma({_period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the HWMA calculation. - public Hwma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _pF = _pV = _pA = 0; - _ppF = _ppV = _ppA = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _ppF = _pF; - _ppV = _pV; - _ppA = _pA; - } - else - { - _pF = _ppF; - _pV = _ppV; - _pA = _ppA; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateLevel(double input) - { - return (_oneMinusNa * (_pF + _pV + (_halfA * _pA))) + (_nA * input); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateVelocity(double F) - { - return (_oneMinusNb * (_pV + _pA)) + (_nB * (F - _pF)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateAcceleration(double V) - { - return (_oneMinusNc * _pA) + (_nC * (V - _pV)); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index == 1) - { - _pF = Input.Value; - _pA = _pV = 0; - return Input.Value; - } - - if (_period == 1) - { - _pF = Input.Value; - _pV = _pA = 0; - return Input.Value; - } - - double F = CalculateLevel(Input.Value); - double V = CalculateVelocity(F); - double A = CalculateAcceleration(V); - - _pF = F; - _pV = V; - _pA = A; - - IsHot = _index >= WarmupPeriod; - return F + V + (_halfA * A); - } -} diff --git a/lib/averages/Jma.cs b/lib/averages/Jma.cs deleted file mode 100644 index 413f25b2..00000000 --- a/lib/averages/Jma.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// JMA: Jurik Moving Average -/// A sophisticated moving average that combines adaptive volatility measurement with -/// phase-shifted smoothing. JMA provides excellent noise reduction while maintaining -/// responsiveness to significant price movements. -/// -/// -/// The JMA calculation process: -/// 1. Calculates adaptive volatility bands -/// 2. Uses volatility to adjust smoothing parameters -/// 3. Applies phase-shifted smoothing for lag reduction -/// 4. Combines multiple smoothing stages for final output -/// -/// Key characteristics: -/// - Adaptive smoothing based on price volatility -/// - Phase-shifting to reduce lag -/// - Excellent noise reduction -/// - Maintains responsiveness to significant moves -/// - Provides volatility bands as additional outputs -/// -/// Implementation: -/// Based on known and reverse-engineered insights from Jurik Research -/// Original work by Mark Jurik -/// -public class Jma : AbstractBase -{ - private readonly double _phase; - private readonly CircularBuffer _vsumBuff; - private readonly CircularBuffer _avoltyBuff; - private readonly double _beta; - private readonly double _len1; - private readonly double _pow1; - private readonly double _oneMinusAlphaSquared; - private readonly double _alphaSquared; - - private double _upperBand, _lowerBand, _p_upperBand, _p_lowerBand; - private double _prevMa1, _prevDet0, _prevDet1, _prevJma; - private double _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma; - private double _vSum, _p_vSum; - - public double UpperBand { get; set; } - public double LowerBand { get; set; } - public double Volty { get; set; } - public double Factor { get; set; } - - public Jma(int period, int phase = 0, double factor = 0.45, int buffer = 10) - { - if (period < 1) - { - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - Factor = factor; - _phase = Math.Clamp((phase * 0.01) + 1.5, 0.5, 2.5); - - _vsumBuff = new CircularBuffer(buffer); - _avoltyBuff = new CircularBuffer(65); - _beta = factor * (period - 1) / ((factor * (period - 1)) + 2); - - _len1 = Math.Max((Math.Log(Math.Sqrt(period - 1)) / Math.Log(2.0)) + 2.0, 0); - _pow1 = Math.Max(_len1 - 2.0, 0.5); - - // Precalculate constants for alpha-based calculations - double alpha = Math.Pow(_beta, _pow1); - double _oneMinusAlpha = 1.0 - alpha; - _oneMinusAlphaSquared = _oneMinusAlpha * _oneMinusAlpha; - _alphaSquared = alpha * alpha; - - WarmupPeriod = period * 2; - Name = $"JMA({period})"; - } - - public Jma(object source, int period, int phase = 0, double factor = 0.45, int buffer = 10) : this(period, phase, factor, buffer) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _upperBand = _lowerBand = 0.0; - _p_upperBand = _p_lowerBand = 0.0; - _avoltyBuff.Clear(); - _vsumBuff.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_upperBand = _upperBand; - _p_lowerBand = _lowerBand; - _p_vSum = _vSum; - _p_prevMa1 = _prevMa1; - _p_prevDet0 = _prevDet0; - _p_prevDet1 = _prevDet1; - _p_prevJma = _prevJma; - } - else - { - _upperBand = _p_upperBand; - _lowerBand = _p_lowerBand; - _vSum = _p_vSum; - _prevMa1 = _p_prevMa1; - _prevDet0 = _p_prevDet0; - _prevDet1 = _p_prevDet1; - _prevJma = _p_prevJma; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateVolatility(double price, double del1, double del2) - { - double volty = Math.Max(Math.Abs(del1), Math.Abs(del2)); - _vsumBuff.Add(volty, Input.IsNew); - _vSum += (_vsumBuff[^1] - _vsumBuff[0]) / _vsumBuff.Count; - _avoltyBuff.Add(_vSum, Input.IsNew); - return volty; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateRelativeVolatility(double volty, double avgVolty) - { - double rvolty = (avgVolty > 0) ? volty / avgVolty : 1; - return Math.Min(Math.Max(rvolty, 1.0), Math.Pow(_len1, 1.0 / _pow1)); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double price = Input.Value; - if (_index <= 1) - { - _upperBand = _lowerBand = price; - _prevMa1 = _prevJma = price; - return price; - } - - double del1 = price - _upperBand; - double del2 = price - _lowerBand; - double volty = CalculateVolatility(price, del1, del2); - double avgVolty = _avoltyBuff.Average(); - - double rvolty = CalculateRelativeVolatility(volty, avgVolty); - double pow2 = Math.Pow(rvolty, _pow1); - double Kv = Math.Pow(_beta, Math.Sqrt(pow2)); - - _upperBand = (del1 >= 0) ? price : price - (Kv * del1); - _lowerBand = (del2 <= 0) ? price : price - (Kv * del2); - - double alpha = Math.Pow(_beta, pow2); - double ma1 = price + (alpha * (_prevMa1 - price)); - _prevMa1 = ma1; - - double det0 = price + (_beta * (_prevDet0 - price + ma1)) - ma1; - _prevDet0 = det0; - double ma2 = ma1 + (_phase * det0); - - double det1 = ((ma2 - _prevJma) * _oneMinusAlphaSquared) + (_alphaSquared * _prevDet1); - _prevDet1 = det1; - double jma = _prevJma + det1; - _prevJma = jma; - - UpperBand = _upperBand; - LowerBand = _lowerBand; - Volty = volty; - - IsHot = _index >= WarmupPeriod; - return jma; - } -} diff --git a/lib/averages/Kama.cs b/lib/averages/Kama.cs deleted file mode 100644 index 58f4011d..00000000 --- a/lib/averages/Kama.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// KAMA: Kaufman's Adaptive Moving Average -/// An adaptive moving average that adjusts its smoothing based on market efficiency. -/// KAMA responds quickly during trending periods and becomes more stable during -/// sideways or choppy markets. -/// -/// -/// The KAMA calculation process: -/// 1. Calculates the Efficiency Ratio (ER) to measure market noise -/// 2. Uses ER to determine the optimal smoothing between fast and slow constants -/// 3. Applies the adaptive smoothing to create the moving average -/// -/// Key characteristics: -/// - Self-adaptive to market conditions -/// - Fast response during trends -/// - Stable during sideways markets -/// - Uses market efficiency for smoothing adjustment -/// - Reduces whipsaws in choppy markets -/// -/// Sources: -/// Perry Kaufman - "Smarter Trading" -/// https://www.investopedia.com/terms/k/kaufmansadaptivemovingaverage.asp -/// -public class Kama : AbstractBase -{ - private readonly int _period; - private readonly double _scSlow; - private readonly double _scDiff; // Precalculated (_scFast - _scSlow) - private readonly CircularBuffer _buffer; - private double _lastKama, _p_lastKama; - - /// The number of periods used to calculate the Efficiency Ratio. - /// The number of periods for the fastest EMA response (default 2). - /// The number of periods for the slowest EMA response (default 30). - /// Thrown when period is less than 1. - public Kama(int period, int fast = 2, int slow = 30) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - double _scFast = 2.0 / (((period < fast) ? period : fast) + 1); - _scSlow = 2.0 / (slow + 1); - _scDiff = _scFast - _scSlow; - _buffer = new CircularBuffer(_period + 1); - WarmupPeriod = period; - Name = $"Kama({_period}, {fast}, {slow})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used to calculate the Efficiency Ratio. - /// The number of periods for the fastest EMA response (default 2). - /// The number of periods for the slowest EMA response (default 30). - public Kama(object source, int period, int fast = 2, int slow = 30) : this(period, fast, slow) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _lastKama = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _p_lastKama = _lastKama; - } - else - { - _lastKama = _p_lastKama; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateVolatility() - { - double volatility = 0; - for (int i = 1; i < _buffer.Count; i++) - { - volatility += System.Math.Abs(_buffer[i] - _buffer[i - 1]); - } - return volatility; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateEfficiencyRatio(double change, double volatility) - { - return volatility >= double.Epsilon ? change / volatility : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateSmoothingConstant(double er) - { - double sc = (er * _scDiff) + _scSlow; - return sc * sc; // Square the smoothing constant - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer.Add(Input.Value, Input.IsNew); - - if (_index <= _period) - { - _lastKama = Input.Value; - return Input.Value; - } - - double change = System.Math.Abs(_buffer[^1] - _buffer[0]); - double volatility = CalculateVolatility(); - double er = CalculateEfficiencyRatio(change, volatility); - double sc = CalculateSmoothingConstant(er); - - _lastKama += sc * (Input.Value - _lastKama); - IsHot = _index >= WarmupPeriod; - - return _lastKama; - } -} diff --git a/lib/averages/Ltma.cs b/lib/averages/Ltma.cs deleted file mode 100644 index b40960f4..00000000 --- a/lib/averages/Ltma.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// LTMA: Laguerre Time Moving Average -/// A sophisticated moving average that uses Laguerre polynomials to create a time-based -/// filter. This approach provides excellent noise reduction while maintaining -/// responsiveness to price changes. -/// -/// -/// The LTMA calculation process: -/// 1. Applies a cascade of four Laguerre filters -/// 2. Each filter stage provides additional smoothing -/// 3. Combines the filtered outputs with optimal weights -/// 4. Produces a smooth output with minimal lag -/// -/// Key characteristics: -/// - Time-based filtering using Laguerre polynomials -/// - Excellent noise reduction -/// - Maintains good responsiveness -/// - Single parameter (gamma) controls smoothing -/// - Computationally efficient -/// -/// Sources: -/// John Ehlers - "Time Warp - Without Space Travel" -/// https://www.mesasoftware.com/papers/TimeWarp.pdf -/// -public class Ltma : AbstractBase -{ - private readonly double _gamma; - private readonly double _oneMinusGamma; - private readonly double _invSix = 1.0 / 6.0; // Precalculated constant for final averaging - private double _prevL0, _prevL1, _prevL2, _prevL3; - private double _p_prevL0, _p_prevL1, _p_prevL2, _p_prevL3; - - /// - /// Gets the gamma parameter value used in the Laguerre filter. - /// - public double Gamma => _gamma; - - /// The damping factor (0 to 1) controlling the smoothing. Lower values provide more smoothing. - /// Thrown when gamma is not between 0 and 1. - public Ltma(double gamma = 0.1) - { - if (gamma < 0 || gamma > 1) - throw new System.ArgumentOutOfRangeException(nameof(gamma), "Gamma must be between 0 and 1."); - _gamma = gamma; - _oneMinusGamma = 1.0 - gamma; - Name = $"Laguerre({gamma:F2})"; - WarmupPeriod = 4; // Minimum number of samples needed - Init(); - } - - /// The data source object that publishes updates. - /// The damping factor (0 to 1) controlling the smoothing. - public Ltma(object source, double gamma = 0.1) : this(gamma) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevL0 = _prevL1 = _prevL2 = _prevL3 = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_prevL0 = _prevL0; - _p_prevL1 = _prevL1; - _p_prevL2 = _prevL2; - _p_prevL3 = _prevL3; - _index++; - } - else - { - _prevL0 = _p_prevL0; - _prevL1 = _p_prevL1; - _prevL2 = _p_prevL2; - _prevL3 = _p_prevL3; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateLaguerreStage(double input, double prev, double prevPrev) - { - return (-_gamma * input) + prev + (_gamma * prevPrev); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CombineOutputs(double l0, double l1, double l2, double l3) - { - return (l0 + (2.0 * (l1 + l2)) + l3) * _invSix; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // First stage - double l0 = (_oneMinusGamma * Input.Value) + (_gamma * _prevL0); - - // Subsequent stages using helper method - double l1 = CalculateLaguerreStage(l0, _prevL0, _prevL1); - double l2 = CalculateLaguerreStage(l1, _prevL1, _prevL2); - double l3 = CalculateLaguerreStage(l2, _prevL2, _prevL3); - - // Store values for next iteration - _prevL0 = l0; - _prevL1 = l1; - _prevL2 = l2; - _prevL3 = l3; - - IsHot = _index >= WarmupPeriod; - return CombineOutputs(l0, l1, l2, l3); - } -} diff --git a/lib/averages/Maaf.cs b/lib/averages/Maaf.cs deleted file mode 100644 index b5f6c5fa..00000000 --- a/lib/averages/Maaf.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MAAF: Median Adaptive Average Filter -/// A sophisticated moving average that combines median filtering with adaptive smoothing -/// to provide robust noise reduction while maintaining signal fidelity. The filter -/// automatically adjusts its length based on market conditions. -/// -/// -/// The MAAF calculation process: -/// 1. Applies initial smoothing using weighted moving average -/// 2. Uses median filtering to remove outliers -/// 3. Adaptively adjusts filter length based on price deviation -/// 4. Applies final EMA smoothing with adaptive period -/// -/// Key characteristics: -/// - Combines median and exponential filtering -/// - Adaptive period adjustment -/// - Robust noise reduction -/// - Preserves significant price movements -/// - Reduces impact of outliers -/// -/// Sources: -/// John F. Ehlers - "The Secret Behind The Filter" -/// https://efs.kb.esignal.com/hc/en-us/articles/6362791434395-2005-Mar-The-Secret-Behind-The-Filter-MedianAdaptiveFilter-efs -/// -/// Note: Initial values handling is currently under development. -/// -public class Maaf : AbstractBase -{ - private readonly CircularBuffer _priceBuffer; - private readonly CircularBuffer _smoothBuffer; - private readonly double _threshold; - private readonly int _period; - private readonly double _invSix = 1.0 / 6.0; - private readonly double[] _sortBuffer; // Pre-allocated buffer for sorting - - private double _prevFilter, _prevValue2; - private double _p_prevFilter, _p_prevValue2; - - /// The initial period for the filter (default 39). - /// The threshold for adaptive adjustment (default 0.002). - public Maaf(int period = 39, double threshold = 0.002) - { - _period = period; - _threshold = threshold; - _priceBuffer = new CircularBuffer(4); - _smoothBuffer = new CircularBuffer(period); - _sortBuffer = new double[period]; // Pre-allocate sorting buffer - Name = "MAAF"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The initial period for the filter (default 39). - /// The threshold for adaptive adjustment (default 0.002). - public Maaf(object source, int period = 39, double threshold = 0.002) : this(period, threshold) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _priceBuffer.Clear(); - _smoothBuffer.Clear(); - _prevFilter = 0; - _prevValue2 = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _p_prevFilter = _prevFilter; - _p_prevValue2 = _prevValue2; - } - else - { - _prevFilter = _p_prevFilter; - _prevValue2 = _p_prevValue2; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateSmooth() - { - return (_priceBuffer[^1] + (2.0 * (_priceBuffer[^2] + _priceBuffer[^3])) + _priceBuffer[^4]) * _invSix; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double GetMedian(int length) - { - // Copy values to pre-allocated buffer - var span = _smoothBuffer.GetSpan().Slice(_smoothBuffer.Count - length, length); - span.CopyTo(_sortBuffer.AsSpan(0, length)); - - // Sort the required portion - System.Array.Sort(_sortBuffer, 0, length); - return _sortBuffer[length / 2]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateAlpha(int length) - { - return 2.0 / (length + 1); - } - - protected override double Calculation() - { - ManageState(IsNew); - - _priceBuffer.Add(Input.Value, Input.IsNew); - - if (_priceBuffer.Count < 4) - { - return Input.Value; - } - - double smooth = CalculateSmooth(); - _smoothBuffer.Add(smooth, Input.IsNew); - - if (_smoothBuffer.Count < _period) - { - return smooth; - } - - int length = _period; - double value3 = 0.2; - double value2 = _prevValue2; - - while (value3 > _threshold && length > 0) - { - double alpha = CalculateAlpha(length); - double value1 = GetMedian(length); - value2 = (alpha * (smooth - _prevValue2)) + _prevValue2; - - if (value1 >= double.Epsilon) - { - value3 = Math.Abs(value1 - value2) / value1; - } - - length -= 2; - } - - length = Math.Max(length, 3); - double finalAlpha = CalculateAlpha(length); - double filter = (finalAlpha * (smooth - _prevFilter)) + _prevFilter; - - _prevFilter = filter; - _prevValue2 = value2; - - IsHot = _index >= WarmupPeriod; - return filter; - } -} diff --git a/lib/averages/Mama.cs b/lib/averages/Mama.cs deleted file mode 100644 index a4b2e9fa..00000000 --- a/lib/averages/Mama.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MAMA: MESA Adaptive Moving Average -/// A highly sophisticated adaptive moving average that uses the MESA (Maximum Entropy -/// Spectral Analysis) algorithm to detect market cycles and adjust its smoothing -/// accordingly. MAMA provides both a faster (MAMA) and slower (FAMA) moving average. -/// -/// -/// The MAMA calculation process: -/// 1. Uses Hilbert Transform to decompose price into phase and amplitude -/// 2. Calculates the dominant cycle period using phase analysis -/// 3. Determines phase position and rate of change -/// 4. Adapts smoothing based on phase changes -/// 5. Generates both MAMA and FAMA (Following Adaptive Moving Average) -/// -/// Key characteristics: -/// - Highly adaptive to market conditions -/// - Provides two synchronized moving averages -/// - Uses cycle analysis for adaptation -/// - Excellent at identifying trend changes -/// - Combines multiple signal processing techniques -/// -/// Sources: -/// John Ehlers - "MESA Adaptive Moving Averages" -/// https://www.mesasoftware.com/papers/MAMA.pdf -/// -public class Mama : AbstractBase -{ - private readonly double _fastLimit, _slowLimit; - private readonly CircularBuffer _pr, _sm, _dt, _i1, _q1, _i2, _q2, _re, _im, _pd, _ph; - private readonly double _twoPi = 2.0 * System.Math.PI; - private readonly double _radToDeg = 180.0 / System.Math.PI; - private readonly double _alpha02 = 0.2; - private readonly double _alpha08 = 0.8; - private readonly double _famaAlpha = 0.5; - - private double _mama, _fama; - private double _prevMama, _prevFama, _sumPr; - private double _p_prevMama, _p_prevFama, _p_sumPr; - - /// - /// Gets the Following Adaptive Moving Average (FAMA) value. - /// - public TValue Fama { get; private set; } - - public Mama(double fastLimit = 0.5, double slowLimit = 0.05) - { - Fama = new TValue(); - _fastLimit = fastLimit; - _slowLimit = slowLimit; - _pr = new(7); - _sm = new(7); - _dt = new(7); - _q1 = new(7); - _i1 = new(7); - _i2 = new(2); - _q2 = new(2); - _re = new(2); - _im = new(2); - _pd = new(2); - _ph = new(2); - Name = $"Mama({_fastLimit:F2}, {_slowLimit:F2})"; - Init(); - } - - public Mama(object source, double fastLimit = 0.5, double slowLimit = 0.05) : this(fastLimit, slowLimit) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - Fama = new TValue(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_prevMama = _prevMama; - _p_prevFama = _prevFama; - _p_sumPr = _sumPr; - _lastValidValue = Input.Value; - _index++; - } - else - { - _prevMama = _p_prevMama; - _prevFama = _p_prevFama; - _sumPr = _p_sumPr; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateSmooth() - { - return ((4.0 * _pr[^1]) + (3.0 * _pr[^2]) + (2.0 * _pr[^3]) + _pr[^4]) * 0.1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateHilbertTransform(CircularBuffer buffer, double adj) - { - return ((0.0962 * (buffer[^1] - buffer[^7])) + (0.5769 * (buffer[^3] - buffer[^5]))) * adj; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculatePeriod(double im, double re) - { - if (System.Math.Abs(im) <= double.Epsilon || System.Math.Abs(re) <= double.Epsilon) return _pd[^2]; - return _twoPi / System.Math.Atan(im / re); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double AdjustPeriod(double period) - { - period = System.Math.Clamp(period, 0.67 * _pd[^2], 1.5 * _pd[^2]); - period = System.Math.Clamp(period, 6.0, 50.0); - return (_alpha02 * period) + (_alpha08 * _pd[^2]); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - _pr.Add(Input.Value, Input.IsNew); - - if (_index > 6) - { - double adj = (0.075 * _pd[^1]) + 0.54; - - // Smooth and Detrender - _sm.Add(CalculateSmooth(), Input.IsNew); - _dt.Add(CalculateHilbertTransform(_sm, adj), Input.IsNew); - - // In-phase and quadrature - _q1.Add(CalculateHilbertTransform(_dt, adj), Input.IsNew); - _i1.Add(_dt[^4], Input.IsNew); - - // Advance phases - double jI = CalculateHilbertTransform(_i1, adj); - double jQ = CalculateHilbertTransform(_q1, adj); - - // Phasor addition - double i2 = _i1[^1] - jQ; - double q2 = _q1[^1] + jI; - _i2.Add(i2, Input.IsNew); - _q2.Add(q2, Input.IsNew); - _i2[^1] = (_alpha02 * _i2[^1]) + (_alpha08 * _i2[^2]); - _q2[^1] = (_alpha02 * _q2[^1]) + (_alpha08 * _q2[^2]); - - // Homodyne discriminator - double re = (_i2[^1] * _i2[^2]) + (_q2[^1] * _q2[^2]); - double im = (_i2[^1] * _q2[^2]) - (_q2[^1] * _i2[^2]); - _re.Add(re, Input.IsNew); - _im.Add(im, Input.IsNew); - _re[^1] = (_alpha02 * _re[^1]) + (_alpha08 * _re[^2]); - _im[^1] = (_alpha02 * _im[^1]) + (_alpha08 * _im[^2]); - - // Calculate and adjust period - double period = CalculatePeriod(_im[^1], _re[^1]); - _pd.Add(period, Input.IsNew); - _pd[^1] = AdjustPeriod(_pd[^1]); - - // Phase calculation - double phase = Math.Abs(_i1[^1]) >= double.Epsilon ? System.Math.Atan(_q1[^1] / _i1[^1]) * _radToDeg : _ph[^2]; - _ph.Add(phase, Input.IsNew); - - // Adaptive alpha - double delta = System.Math.Max(_ph[^2] - _ph[^1], 1.0); - double alpha = System.Math.Clamp(_fastLimit / delta, _slowLimit, _fastLimit); - - // Final indicators - _mama = (alpha * (_pr[^1] - _prevMama)) + _prevMama; - _fama = (_famaAlpha * alpha * (_mama - _prevFama)) + _prevFama; - - _prevMama = _mama; - _prevFama = _fama; - } - else - { - InitializeBuffers(); - _sumPr += Input.Value; - _mama = _fama = _prevMama = _prevFama = _sumPr / _index; - } - - Fama = new TValue(Time: Input.Time, Value: _fama, IsNew: Input.IsNew); - IsHot = _index >= 6; - - return _mama; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void InitializeBuffers() - { - _pd.Add(0, Input.IsNew); - _sm.Add(0, Input.IsNew); - _dt.Add(0, Input.IsNew); - _i1.Add(0, Input.IsNew); - _q1.Add(0, Input.IsNew); - _i2.Add(0, Input.IsNew); - _q2.Add(0, Input.IsNew); - _re.Add(0, Input.IsNew); - _im.Add(0, Input.IsNew); - _ph.Add(0, Input.IsNew); - } -} diff --git a/lib/averages/Mgdi.cs b/lib/averages/Mgdi.cs deleted file mode 100644 index d02c05dc..00000000 --- a/lib/averages/Mgdi.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MGDI: Modified Geometric Decay Index -/// A moving average that uses geometric decay with a ratio-based adjustment factor. -/// The decay rate is modified based on the ratio between current and previous values, -/// allowing for adaptive smoothing based on price movement magnitude. -/// -/// -/// The MGDI calculation process: -/// 1. Calculates ratio between current and previous values -/// 2. Uses ratio to modify the geometric decay rate -/// 3. Applies modified decay to smooth the data -/// 4. Adjusts smoothing based on K-factor parameter -/// -/// Key characteristics: -/// - Geometric decay-based smoothing -/// - Adaptive to price movement magnitude -/// - Adjustable smoothing via K-factor -/// - More responsive to large price changes -/// - Maintains smoothness during small fluctuations -/// -/// Implementation: -/// Based on geometric decay principles with ratio-based modification -/// -public class Mgdi : AbstractBase -{ - private readonly int _period; - private readonly double _kFactorPeriod; // Precalculated k * period - private double _prevMd, _p_prevMd; - - /// The number of periods used in the MGDI calculation. - /// The K-factor controlling the decay rate adjustment (default 0.6). - /// Thrown when period or kFactor is less than or equal to 0. - public Mgdi(int period, double kFactor = 0.6) - { - if (period <= 0) - { - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than 0."); - } - if (kFactor <= 0) - { - throw new System.ArgumentOutOfRangeException(nameof(kFactor), "K-Factor must be greater than 0."); - } - _period = period; - _kFactorPeriod = kFactor * period; - Name = "Mgdi"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used in the MGDI calculation. - /// The K-factor controlling the decay rate adjustment (default 0.6). - public Mgdi(object source, int period, double kFactor = 0.6) : this(period, kFactor) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevMd = _p_prevMd = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_prevMd = _prevMd; - _index++; - } - else - { - _prevMd = _p_prevMd; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateRatio(double value) - { - return _prevMd >= double.Epsilon ? value / _prevMd : 1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateMd(double value, double ratio) - { - return _prevMd + ((value - _prevMd) / (_kFactorPeriod * System.Math.Pow(ratio, 4))); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double value = Input.Value; - if (_index < 2) - { - _prevMd = value; - } - else - { - double ratio = CalculateRatio(value); - _prevMd = CalculateMd(value, ratio); - } - - IsHot = _index >= _period; - return _prevMd; - } -} diff --git a/lib/averages/Mma.cs b/lib/averages/Mma.cs deleted file mode 100644 index 3e4501e4..00000000 --- a/lib/averages/Mma.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MMA: Modified Moving Average -/// A moving average that combines a simple moving average with a weighted component -/// to provide a balanced smoothing effect. The weighting scheme emphasizes central -/// values while maintaining overall data representation. -/// -/// -/// The MMA calculation process: -/// 1. Calculates the simple moving average component (T/period) -/// 2. Calculates a weighted sum with symmetric weights around the center -/// 3. Combines both components using the formula: SMA + 6*WeightedSum/((period+1)*period) -/// -/// Key characteristics: -/// - Combines simple and weighted moving averages -/// - Symmetric weighting around the center -/// - Better balance between smoothing and responsiveness -/// - Reduces lag compared to simple moving average -/// - Maintains stability through dual-component approach -/// -/// Implementation: -/// Based on modified moving average principles combining -/// simple and weighted components for optimal smoothing -/// -public class Mma : AbstractBase -{ - private readonly int _period; - private readonly CircularBuffer _buffer; - private readonly double _periodRecip; // 1/period - private readonly double _combinedRecip; // 6/((period+1)*period) - private readonly double[] _weights; // Precalculated weights - private double _lastMma; - - /// The number of periods used in the MMA calculation. Must be at least 2. - /// Thrown when period is less than 2. - public Mma(int period) - { - if (period < 2) - { - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2."); - } - _period = period; - _buffer = new CircularBuffer(period); - _periodRecip = 1.0 / period; - _combinedRecip = 6.0 / ((period + 1) * period); - - // Precalculate weights - _weights = new double[period]; - for (int i = 0; i < period; i++) - { - _weights[i] = (period - ((2 * i) + 1)) * 0.5; - } - - Name = "Mma"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used in the MMA calculation. - public Mma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _lastMma = 0; - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateWeightedSum() - { - double sum = 0; - for (int i = 0; i < _period; i++) - { - sum += _weights[i] * _buffer[^(i + 1)]; - } - return sum; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - if (_index >= _period) - { - double T = _buffer.Sum(); - double S = CalculateWeightedSum(); - _lastMma = (T * _periodRecip) + (S * _combinedRecip); - } - else - { - // Use simple average until we have enough data points - _lastMma = _buffer.Average(); - } - - IsHot = _index >= _period; - return _lastMma; - } -} diff --git a/lib/averages/Pwma.cs b/lib/averages/Pwma.cs deleted file mode 100644 index 22a82102..00000000 --- a/lib/averages/Pwma.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PWMA: Pascal Weighted Moving Average -/// A moving average that uses Pascal's triangle coefficients as weights, providing -/// a natural distribution of weights that increases towards the center of the period. -/// This creates a smooth average with balanced emphasis on central values. -/// -/// -/// The PWMA calculation process: -/// 1. Generates weights using Pascal's triangle coefficients -/// 2. Normalizes the weights to sum to 1 -/// 3. Applies the weights through convolution -/// 4. Adjusts for partial periods during warmup -/// -/// Key characteristics: -/// - Natural weight distribution from Pascal's triangle -/// - Symmetric weighting around the center -/// - Smooth response to price changes -/// - Balanced between recent and historical data -/// - Implemented using efficient convolution operations -/// -/// Implementation: -/// Based on Pascal's triangle principles for weight generation -/// Uses convolution for efficient calculation -/// -public class Pwma : AbstractBase -{ - private readonly int _period; - private readonly Convolution _convolution; - private readonly double[] _kernel; - - /// The number of data points used in the PWMA calculation. - /// Thrown when period is less than 1. - public Pwma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - _kernel = GenerateKernel(_period); - _convolution = new Convolution(_kernel); - Name = "Pwma"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the PWMA calculation. - public Pwma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateKernelSum(double[] kernel, int length) - { - double sum = 0; - for (int i = 0; i < length; i++) - { - sum += kernel[i]; - } - return sum; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - double result = convolutionResult.Value; - - // Adjust for partial periods during warmup - if (_index < _period) - { - double[] partialKernel = GenerateKernel(_index); - result *= CalculateKernelSum(_kernel, _period) / CalculateKernelSum(partialKernel, _index); - } - - IsHot = _index >= WarmupPeriod; - return result; - } - - /// - /// Generates the Pascal's triangle-based convolution kernel for the PWMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of normalized Pascal's triangle-based weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double[] GenerateKernel(int period) - { - double[] kernel = new double[period]; - kernel[0] = 1; - - // Generate Pascal's triangle coefficients - for (int i = 1; i < period; i++) - { - for (int j = i; j > 0; j--) - { - kernel[j] += kernel[j - 1]; - } - } - - // Calculate sum and normalize in one pass - double weightSum = CalculateKernelSum(kernel, period); - double invWeightSum = 1.0 / weightSum; - - for (int i = 0; i < period; i++) - { - kernel[i] *= invWeightSum; - } - - return kernel; - } -} diff --git a/lib/averages/Qema.cs b/lib/averages/Qema.cs deleted file mode 100644 index a594e7d5..00000000 --- a/lib/averages/Qema.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// QEMA: Quadruple Exponential Moving Average -/// A sophisticated moving average that applies four exponential moving averages in sequence -/// and combines them using a specific formula to reduce lag while maintaining smoothness. -/// The final combination is: 4*EMA1 - 6*EMA2 + 4*EMA3 - EMA4 -/// -/// -/// The QEMA calculation process: -/// 1. Applies first EMA to price data -/// 2. Applies second EMA to result of first EMA -/// 3. Applies third EMA to result of second EMA -/// 4. Applies fourth EMA to result of third EMA -/// 5. Combines results using the formula: 4*EMA1 - 6*EMA2 + 4*EMA3 - EMA4 -/// -/// Key characteristics: -/// - Multiple EMA smoothing stages -/// - Reduced lag through combination formula -/// - Customizable smoothing factors for each EMA -/// - Better noise reduction than single EMA -/// - Maintains responsiveness to significant moves -/// -/// Implementation: -/// Based on quadruple exponential smoothing principles -/// with optimized combination formula -/// -public class Qema : AbstractBase -{ - private readonly Ema _ema1, _ema2, _ema3, _ema4; - private double _lastQema, _p_lastQema; - - /// Smoothing factor for first EMA (default 0.2). - /// Smoothing factor for second EMA (default 0.2). - /// Smoothing factor for third EMA (default 0.2). - /// Smoothing factor for fourth EMA (default 0.2). - /// Thrown when any k value is less than or equal to 0. - public Qema(double k1 = 0.2, double k2 = 0.2, double k3 = 0.2, double k4 = 0.2) - { - if (k1 <= 0 || k2 <= 0 || k3 <= 0 || k4 <= 0) - { - throw new System.ArgumentOutOfRangeException(nameof(k1), "All k values must be in the range (0, 1]."); - } - - _ema1 = new Ema(k1); - _ema2 = new Ema(k2); - _ema3 = new Ema(k3); - _ema4 = new Ema(k4); - - Name = $"QEMA ({k1:F2},{k2:F2},{k3:F2},{k4:F2})"; - double smK = System.Math.Min(System.Math.Min(k1, k2), System.Math.Min(k3, k4)); - WarmupPeriod = (int)((2 - smK) / smK); - Init(); - } - - /// The data source object that publishes updates. - /// Smoothing factor for first EMA. - /// Smoothing factor for second EMA. - /// Smoothing factor for third EMA. - /// Smoothing factor for fourth EMA. - public Qema(object source, double k1, double k2, double k3, double k4) - : this(k1, k2, k3, k4) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _lastQema = 0; - _p_lastQema = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastQema = _lastQema; - _index++; - } - else - { - _lastQema = _p_lastQema; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateEma(Ema ema, double value) - { - var tempValue = new TValue(Input.Time, value, Input.IsNew); - return ema.Calc(tempValue).Value; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate EMAs in sequence - double ema1 = CalculateEma(_ema1, Input.Value); - double ema2 = CalculateEma(_ema2, ema1); - double ema3 = CalculateEma(_ema3, ema2); - double ema4 = CalculateEma(_ema4, ema3); - - // Combine EMAs using optimized formula - _lastQema = (4.0 * (ema1 + ema3)) - ((6.0 * ema2) + ema4); - - IsHot = _index >= WarmupPeriod; - return _lastQema; - } -} diff --git a/lib/averages/Rema.cs b/lib/averages/Rema.cs deleted file mode 100644 index 96314157..00000000 --- a/lib/averages/Rema.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// REMA: Regularized Exponential Moving Average -/// A modified exponential moving average that includes a regularization term to reduce -/// noise and improve trend following. The regularization helps to smooth the output -/// while maintaining responsiveness to significant price movements. -/// -/// -/// The REMA calculation process: -/// 1. Uses standard EMA smoothing with adaptive alpha -/// 2. Adds regularization term based on previous values -/// 3. Balances new and regularized terms using lambda parameter -/// 4. Provides smoother output than standard EMA -/// -/// Key characteristics: -/// - Improved noise reduction through regularization -/// - Better trend following than standard EMA -/// - Adjustable regularization via lambda parameter -/// - Adaptive alpha based on period -/// - Reduced whipsaws in choppy markets -/// -/// Sources: -/// https://user42.tuxfamily.org/chart/manual/Regularized-Exponential-Moving-Average.html -/// -public class Rema : AbstractBase -{ - private readonly int _period; - private readonly double _lambda; - private readonly double _lambdaPlus1Recip; // 1/(1 + lambda) - private double _lastRema, _prevRema; - private double _savedLastRema, _savedPrevRema; - - /// - /// Gets the period used in the REMA calculation. - /// - public int Period => _period; - - /// - /// Gets the lambda (regularization) parameter value. - /// - public double Lambda => _lambda; - - /// The number of periods used in the REMA calculation. - /// The regularization parameter (default 0.5). Higher values increase smoothing. - /// Thrown when period is less than 1 or lambda is negative. - public Rema(int period, double lambda = 0.5) - { - if (period < 1) - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - if (lambda < 0) - throw new System.ArgumentOutOfRangeException(nameof(lambda), "Lambda must be non-negative."); - - _period = period; - _lambda = lambda; - _lambdaPlus1Recip = 1.0 / (1.0 + lambda); - Name = $"REMA({period},{lambda:F2})"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used in the REMA calculation. - /// The regularization parameter (default 0.5). - public Rema(object source, int period, double lambda = 0.5) : this(period, lambda) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _lastRema = 0; - _prevRema = 0; - _savedLastRema = 0; - _savedPrevRema = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _savedLastRema = _lastRema; - _savedPrevRema = _prevRema; - _index++; - } - else - { - _lastRema = _savedLastRema; - _prevRema = _savedPrevRema; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateAlpha() - { - return 2.0 / (System.Math.Min(_period, _index) + 1); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateRema(double alpha, double input) - { - double standardTerm = _lastRema + (alpha * (input - _lastRema)); - double regularizationTerm = _lastRema + (_lastRema - _prevRema); - return (standardTerm + (_lambda * regularizationTerm)) * _lambdaPlus1Recip; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index > 2) - { - double alpha = CalculateAlpha(); - double rema = CalculateRema(alpha, Input.Value); - _prevRema = _lastRema; - _lastRema = rema; - } - else if (_index == 2) - { - _prevRema = _lastRema; - _lastRema = Input.Value; - } - else - { - _lastRema = Input.Value; - } - - IsHot = _index >= WarmupPeriod; - return _lastRema; - } -} diff --git a/lib/averages/Rma.cs b/lib/averages/Rma.cs deleted file mode 100644 index 16c92029..00000000 --- a/lib/averages/Rma.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RMA: Relative Moving Average (also known as Wilder's Moving Average) -/// -/// -/// RMA is similar to EMA but uses a different smoothing factor. -/// -/// Key characteristics: -/// - Uses no buffer, relying only on the previous RMA value. -/// - The weight of new data points (alpha) is calculated as 1 / period. -/// - Provides a smoother curve compared to SMA and EMA, reacting more slowly to price changes. -/// -/// Calculation method: -/// This implementation can use SMA for the first Period bars as a seeding value for RMA when useSma is true. -/// -/// Sources: -/// - https://www.tradingview.com/pine-script-reference/v5/#fun_ta{dot}rma -/// - https://www.investopedia.com/terms/w/wilders-smoothing.asp -/// -public class Rma : AbstractBase -{ - private readonly int _period; - private readonly double _k; // Wilder's smoothing factor - private readonly double _oneMinusK; // 1 - k - private readonly double _epsilon = 1e-10; - private readonly bool _useSma; - private CircularBuffer _sma; - - private double _lastRma, _p_lastRma; - private double _e, _p_e; - private bool _isInit, _p_isInit; - - /// - /// Initializes a new instance of the Rma class with a specified period. - /// - /// The period for RMA calculation. - /// Whether to use SMA for initial values. Default is true. - /// Thrown when period is less than 1. - public Rma(int period, bool useSma = true) - { - if (period < 1) - { - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - _period = period; - _k = 1.0 / period; - _oneMinusK = 1.0 - _k; - _useSma = useSma; - _sma = new(period); - Name = "Rma"; - WarmupPeriod = period * 2; // RMA typically needs more warmup periods - Init(); - } - - /// - /// Initializes a new instance of the Rma class with a specified source and period. - /// - /// The source object for event subscription. - /// The period for RMA calculation. - /// Whether to use SMA for initial values. Default is true. - public Rma(object source, int period, bool useSma = true) : this(period, useSma) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _e = 1.0; - _lastRma = 0; - _isInit = false; - _p_isInit = false; - _sma = new(_period); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastRma = _lastRma; - _p_isInit = _isInit; - _p_e = _e; - _index++; - } - else - { - _lastRma = _p_lastRma; - _isInit = _p_isInit; - _e = _p_e; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateRma(double input) - { - return (_k * input) + (_oneMinusK * _lastRma); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CompensateRma(double rma) - { - _e = (_e > _epsilon) ? _oneMinusK * _e : 0; - return (_useSma || _e <= double.Epsilon) ? rma : rma / (1.0 - _e); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double result; - if (!_isInit && _useSma) - { - _sma.Add(Input.Value, Input.IsNew); - _lastRma = _sma.Average(); - result = _lastRma; - - if (_index >= _period) - { - _isInit = true; - } - } - else - { - _lastRma = CalculateRma(Input.Value); - result = CompensateRma(_lastRma); - } - - IsHot = _index >= WarmupPeriod; - return result; - } -} diff --git a/lib/averages/Sinema.cs b/lib/averages/Sinema.cs deleted file mode 100644 index 10f0f4ab..00000000 --- a/lib/averages/Sinema.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SINEMA: Sine-weighted Exponential Moving Average -/// A moving average that uses sine function-based weights to create a natural -/// distribution of importance across the period. The weights follow a sine curve, -/// providing smooth transitions and natural emphasis on different parts of the data. -/// -/// -/// The SINEMA calculation process: -/// 1. Generates weights using sine function over the period -/// 2. Normalizes weights to sum to 1 -/// 3. Applies weights through convolution -/// 4. Produces smooth output with natural weight distribution -/// -/// Key characteristics: -/// - Sine-based weight distribution -/// - Natural smoothing through trigonometric weights -/// - No sharp transitions in weight values -/// - Balanced emphasis across the period -/// - Implemented using efficient convolution operations -/// -/// Implementation: -/// Based on sine function principles for weight generation -/// Uses convolution for efficient calculation -/// -public class Sinema : AbstractBase -{ - private readonly Convolution _convolution; - - /// The number of data points used in the SINEMA calculation. - /// Thrown when period is less than 1. - public Sinema(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - double[] _kernel = GenerateKernel(period); - _convolution = new Convolution(_kernel); - Name = "Sinema"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the SINEMA calculation. - public Sinema(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - /// - /// Generates the sine-based convolution kernel for the SINEMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of normalized sine-based weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double[] GenerateKernel(int period) - { - double[] kernel = new double[period]; - double weightSum = 0; - double piDivPeriodPlus1 = System.Math.PI / (period + 1); - - // Calculate weights and sum in one pass - for (int i = 0; i < period; i++) - { - kernel[i] = System.Math.Sin((i + 1) * piDivPeriodPlus1); - weightSum += kernel[i]; - } - - // Normalize using multiplication instead of division - double invWeightSum = 1.0 / weightSum; - for (int i = 0; i < period; i++) - { - kernel[i] *= invWeightSum; - } - - return kernel; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - IsHot = _index >= WarmupPeriod; - - return convolutionResult.Value; - } -} diff --git a/lib/averages/Sma.cs b/lib/averages/Sma.cs deleted file mode 100644 index 684d4445..00000000 --- a/lib/averages/Sma.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SMA: Simple Moving Average -/// The most basic form of moving average, calculating the arithmetic mean over a -/// specified period. Each data point in the period has equal weight in the -/// calculation. -/// -/// -/// The SMA calculation process: -/// 1. Maintains a circular buffer of the last 'period' values -/// 2. Maintains a running sum for O(1) calculation -/// 3. Updates: sum = sum - oldest + newest -/// 4. Returns sum / count for the average -/// -/// Key characteristics: -/// - Equal weight for all values in the period -/// - O(1) time complexity using running sum -/// - Simple and straightforward calculation -/// - Significant lag due to equal weighting -/// - Smooth output with good noise reduction -/// - Most basic form of trend following -/// -/// Sources: -/// https://www.investopedia.com/terms/s/sma.asp -/// https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages -/// -[SkipLocalsInit] -public sealed class Sma : AbstractBase -{ - private readonly CircularBuffer _buffer; - private double _sum, _p_sum; - private double _lastValue, _p_lastValue; - - /// The number of data points used in the SMA calculation. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Sma(int period) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - _buffer = new CircularBuffer(period); - Name = $"Sma({period})"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the SMA calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Sma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_sum = _sum; - _p_lastValue = _lastValue; - } - else - { - _sum = _p_sum; - _lastValue = _p_lastValue; - } - } - - /// - /// Performs the core SMA calculation using O(1) running sum algorithm. - /// - /// The calculated SMA value. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double oldValue; - if (Input.IsNew) - { - oldValue = _buffer.Count == _buffer.Capacity ? _buffer.Oldest() : 0.0; - _lastValue = Input.Value; - } - else - { - oldValue = _lastValue; - } - - _sum = _sum - oldValue + Input.Value; - _buffer.Add(Input.Value, Input.IsNew); - - IsHot = _index >= WarmupPeriod; - return _sum / _buffer.Count; - } -} diff --git a/lib/averages/Smma.cs b/lib/averages/Smma.cs deleted file mode 100644 index 56c9c70b..00000000 --- a/lib/averages/Smma.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SMMA: Smoothed Moving Average -/// A modified moving average that gives more weight to recent prices while maintaining -/// a smooth output. It uses the previous SMMA value in its calculation, creating -/// a smoother line than traditional moving averages. -/// -/// -/// The SMMA calculation process: -/// 1. Uses SMA for initial value (first period points) -/// 2. For subsequent points, calculates: (prevSMMA * (period-1) + price) / period -/// 3. This creates a smoothed effect with reduced volatility -/// -/// Key characteristics: -/// - Smoother than traditional moving averages -/// - Reduced volatility in output -/// - Takes into account all previous prices -/// - Good for identifying overall trends -/// - Less lag than SMA but more than EMA -/// -/// Implementation: -/// Based on smoothed moving average principles with -/// initial SMA seeding for stability -/// -public class Smma : AbstractBase -{ - private readonly int _period; - private readonly double _periodRecip; // 1/period - private readonly double _periodMinusOne; // period-1 - private readonly CircularBuffer _buffer; - private double _lastSmma, _p_lastSmma; - - /// The number of data points used in the SMMA calculation. - /// Thrown when period is less than 1. - public Smma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - _periodRecip = 1.0 / period; - _periodMinusOne = period - 1; - _buffer = new CircularBuffer(period); - WarmupPeriod = period; - Name = $"Smma({_period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the SMMA calculation. - public Smma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _lastSmma = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _p_lastSmma = _lastSmma; - _index++; - } - else - { - _lastSmma = _p_lastSmma; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateSmma(double input) - { - return ((_lastSmma * _periodMinusOne) + input) * _periodRecip; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double smma; - if (_index <= _period) - { - smma = _buffer.Average(); - if (_index == _period) - { - _lastSmma = smma; // Initialize _lastSmma for the transition - } - } - else - { - smma = CalculateSmma(Input.Value); - } - - _lastSmma = smma; - IsHot = _index >= WarmupPeriod; - - return smma; - } -} diff --git a/lib/averages/T3.cs b/lib/averages/T3.cs deleted file mode 100644 index e7db51bf..00000000 --- a/lib/averages/T3.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// T3: Tillson T3 Moving Average -/// A sophisticated moving average developed by Tim Tillson that applies six EMAs -/// in sequence with optimized coefficients. The T3 provides excellent smoothing -/// while maintaining responsiveness and minimal lag. -/// -/// -/// The T3 calculation process: -/// 1. Applies six EMAs in sequence -/// 2. Uses volume factor to determine optimal coefficients -/// 3. Combines EMAs using specific formula: c1*EMA6 + c2*EMA5 + c3*EMA4 + c4*EMA3 -/// 4. Coefficients are based on the volume factor parameter -/// -/// Key characteristics: -/// - Excellent smoothing with minimal lag -/// - Adjustable via volume factor parameter -/// - No overshooting like triple EMA -/// - Better noise reduction than traditional EMAs -/// - Maintains responsiveness to significant moves -/// -/// Sources: -/// Tim Tillson - "Better Moving Averages" -/// TASC Magazine, 1998 -/// -public class T3 : AbstractBase -{ - private readonly int _period; - private readonly bool _useSma; - private readonly double _k; - private readonly double _c1, _c2, _c3, _c4; - private readonly CircularBuffer _buffer1, _buffer2, _buffer3, _buffer4, _buffer5, _buffer6; - - private double _lastEma1, _lastEma2, _lastEma3, _lastEma4, _lastEma5, _lastEma6; - private double _p_lastEma1, _p_lastEma2, _p_lastEma3, _p_lastEma4, _p_lastEma5, _p_lastEma6; - - /// The number of periods used in each EMA calculation. - /// Volume factor controlling smoothing (default 0.7). - /// Whether to use SMA for initial values (default true). - /// Thrown when period is less than 1. - public T3(int period, double vfactor = 0.7, bool useSma = true) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - _useSma = useSma; - WarmupPeriod = period; - - _k = 2.0 / (_period + 1); - - // Precalculate coefficients - double v2 = vfactor * vfactor; - double v3 = v2 * vfactor; - _c1 = -v3; - _c2 = 3.0 * (v2 + v3); - _c3 = -3.0 * ((2.0 * v2) + vfactor + v3); - _c4 = 1.0 + (3.0 * vfactor) + v3 + (3.0 * v2); - - _buffer1 = new(period); - _buffer2 = new(period); - _buffer3 = new(period); - _buffer4 = new(period); - _buffer5 = new(period); - _buffer6 = new(period); - - Name = $"T3({_period}, {vfactor})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used in each EMA calculation. - /// Volume factor controlling smoothing (default 0.7). - /// Whether to use SMA for initial values (default true). - public T3(object source, int period, double vfactor = 0.7, bool useSma = true) : this(period, vfactor, useSma) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - _lastEma1 = _lastEma2 = _lastEma3 = _lastEma4 = _lastEma5 = _lastEma6 = 0; - _buffer1.Clear(); - _buffer2.Clear(); - _buffer3.Clear(); - _buffer4.Clear(); - _buffer5.Clear(); - _buffer6.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _p_lastEma1 = _lastEma1; - _p_lastEma2 = _lastEma2; - _p_lastEma3 = _lastEma3; - _p_lastEma4 = _lastEma4; - _p_lastEma5 = _lastEma5; - _p_lastEma6 = _lastEma6; - } - else - { - _lastEma1 = _p_lastEma1; - _lastEma2 = _p_lastEma2; - _lastEma3 = _p_lastEma3; - _lastEma4 = _p_lastEma4; - _lastEma5 = _p_lastEma5; - _lastEma6 = _p_lastEma6; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateEma(double input, double lastEma) - { - return (_k * (input - lastEma)) + lastEma; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateT3(double ema3, double ema4, double ema5, double ema6) - { - return (_c1 * ema6) + (_c2 * ema5) + (_c3 * ema4) + (_c4 * ema3); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double ema1, ema2, ema3, ema4, ema5, ema6; - - if (_index == 1) - { - ema1 = ema2 = ema3 = ema4 = ema5 = ema6 = Input.Value; - } - else if (_index <= _period && _useSma) - { - _buffer1.Add(Input.Value, Input.IsNew); - ema1 = _buffer1.Average(); - _buffer2.Add(ema1, Input.IsNew); - ema2 = _buffer2.Average(); - _buffer3.Add(ema2, Input.IsNew); - ema3 = _buffer3.Average(); - _buffer4.Add(ema3, Input.IsNew); - ema4 = _buffer4.Average(); - _buffer5.Add(ema4, Input.IsNew); - ema5 = _buffer5.Average(); - _buffer6.Add(ema5, Input.IsNew); - ema6 = _buffer6.Average(); - } - else - { - ema1 = CalculateEma(Input.Value, _lastEma1); - ema2 = CalculateEma(ema1, _lastEma2); - ema3 = CalculateEma(ema2, _lastEma3); - ema4 = CalculateEma(ema3, _lastEma4); - ema5 = CalculateEma(ema4, _lastEma5); - ema6 = CalculateEma(ema5, _lastEma6); - } - - _lastEma1 = ema1; - _lastEma2 = ema2; - _lastEma3 = ema3; - _lastEma4 = ema4; - _lastEma5 = ema5; - _lastEma6 = ema6; - - IsHot = _index >= WarmupPeriod; - return CalculateT3(ema3, ema4, ema5, ema6); - } -} diff --git a/lib/averages/Tema.cs b/lib/averages/Tema.cs deleted file mode 100644 index a1238ee5..00000000 --- a/lib/averages/Tema.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TEMA: Triple Exponential Moving Average -/// A sophisticated moving average that applies three EMAs in sequence with a specific -/// combination formula to reduce lag while maintaining smoothness. The formula -/// 3*EMA1 - 3*EMA2 + EMA3 helps eliminate lag in trending markets. -/// -/// -/// The TEMA calculation process: -/// 1. Calculates first EMA of the price -/// 2. Calculates second EMA of the first EMA -/// 3. Calculates third EMA of the second EMA -/// 4. Combines using formula: 3*EMA1 - 3*EMA2 + EMA3 -/// -/// Key characteristics: -/// - Significantly reduced lag compared to single EMA -/// - Better response to trends than standard EMAs -/// - Maintains smoothness despite reduced lag -/// - More responsive than double EMA (DEMA) -/// - Uses compensator for early values -/// -/// Sources: -/// Patrick Mulloy - "Smoothing Data with Faster Moving Averages" -/// Technical Analysis of Stocks and Commodities, 1994 -/// -public class Tema : AbstractBase -{ - private readonly double _k; - private readonly double _oneMinusK; - private readonly double _epsilon = 1e-10; - private double _lastEma1, _p_lastEma1; - private double _lastEma2, _p_lastEma2; - private double _lastEma3, _p_lastEma3; - private double _e, _p_e; - - /// The number of periods used in each EMA calculation. - /// Thrown when period is less than 1. - public Tema(int period) - { - if (period < 1) - { - throw new System.ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - _k = 2.0 / (period + 1); - _oneMinusK = 1.0 - _k; - Name = "Tema"; - double percentile = 0.85; //targeting 85th percentile of correctness of converging EMA - WarmupPeriod = (int)System.Math.Ceiling(-period * System.Math.Log(1 - percentile)); - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used in each EMA calculation. - public Tema(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _e = 1.0; - _lastEma1 = _lastEma2 = _lastEma3 = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_lastEma1 = _lastEma1; - _p_lastEma2 = _lastEma2; - _p_lastEma3 = _lastEma3; - _p_e = _e; - _index++; - } - else - { - _lastEma1 = _p_lastEma1; - _lastEma2 = _p_lastEma2; - _lastEma3 = _p_lastEma3; - _e = _p_e; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateEma(double input, double lastEma, double invE) - { - return (_k * ((input * invE) - lastEma)) + lastEma; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double UpdateCompensator() - { - _e = (_e > _epsilon) ? _oneMinusK * _e : 0; - return (_e > _epsilon) ? 1.0 / (1.0 - _e) : 1.0; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - double invE = UpdateCompensator(); - - // Calculate EMAs with compensation - double ema1 = CalculateEma(Input.Value, _lastEma1, 1.0); // First EMA doesn't need compensation - double ema2 = CalculateEma(ema1, _lastEma2, invE); - double ema3 = CalculateEma(ema2, _lastEma3, invE); - - // Store values for next iteration - _lastEma1 = ema1; - _lastEma2 = ema2; - _lastEma3 = ema3; - - // Calculate final TEMA with compensation - double result = ((3.0 * ema1) - (3.0 * ema2) + ema3) * invE; - - IsHot = _index >= WarmupPeriod; - return result; - } -} diff --git a/lib/averages/Trima.cs b/lib/averages/Trima.cs deleted file mode 100644 index 650e2543..00000000 --- a/lib/averages/Trima.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TRIMA: Triangular Moving Average -/// A moving average that uses triangular-shaped weights that increase linearly to -/// the middle of the period and then decrease linearly. This creates a smoother -/// output than simple moving averages. -/// -/// -/// The TRIMA calculation process: -/// 1. Generates triangular weights that peak at the center -/// 2. Weights increase linearly to middle point -/// 3. Weights decrease linearly from middle point -/// 4. Applies normalized weights through convolution -/// -/// Key characteristics: -/// - Smoother than simple moving average -/// - Natural emphasis on central values -/// - Reduced noise sensitivity -/// - Double smoothing effect -/// - Implemented using efficient convolution operations -/// -/// Sources: -/// https://www.investopedia.com/terms/t/triangularaverage.asp -/// Technical Analysis of Stocks & Commodities magazine -/// -public class Trima : AbstractBase -{ - private readonly Convolution _convolution; - - /// The number of data points used in the TRIMA calculation. - /// Thrown when period is less than 1. - public Trima(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - double[] _kernel = GenerateKernel(period); - _convolution = new Convolution(_kernel); - Name = "Trima"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the TRIMA calculation. - public Trima(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - /// - /// Generates the triangular-shaped convolution kernel for the TRIMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of normalized triangular weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double[] GenerateKernel(int period) - { - double[] kernel = new double[period]; - int halfPeriod = (period + 1) / 2; - double weightSum = 0; - - // Calculate weights and sum in one pass - for (int i = 0; i < period; i++) - { - kernel[i] = i < halfPeriod ? i + 1 : period - i; - weightSum += kernel[i]; - } - - // Normalize using multiplication instead of division - double invWeightSum = 1.0 / weightSum; - for (int i = 0; i < period; i++) - { - kernel[i] *= invWeightSum; - } - - return kernel; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - IsHot = _index >= WarmupPeriod; - - return convolutionResult.Value; - } -} diff --git a/lib/averages/Vidya.cs b/lib/averages/Vidya.cs deleted file mode 100644 index 187a8c7b..00000000 --- a/lib/averages/Vidya.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VIDYA: Variable Index Dynamic Average -/// An adaptive moving average that adjusts its smoothing based on the ratio of -/// short-term to long-term volatility. This allows the average to become more -/// responsive during volatile periods and more stable during quiet periods. -/// -/// -/// The VIDYA calculation process: -/// 1. Calculates standard deviation for short and long periods -/// 2. Uses ratio of short/long volatility to determine smoothing -/// 3. Applies variable smoothing factor to price data -/// 4. Adapts automatically to changing market conditions -/// -/// Key characteristics: -/// - Adaptive smoothing based on volatility -/// - More responsive during volatile periods -/// - More stable during quiet periods -/// - Uses standard deviation for volatility measurement -/// - Combines short and long-term market analysis -/// -/// Sources: -/// Tushar Chande - "Beyond Technical Analysis" -/// https://www.investopedia.com/terms/v/vidya.asp -/// -public class Vidya : AbstractBase -{ - private readonly int _longPeriod; - private readonly double _alpha; - private readonly CircularBuffer _shortBuffer; - private readonly CircularBuffer _longBuffer; - private double _lastVIDYA, _p_lastVIDYA; - - /// The number of periods for short-term volatility calculation. - /// The number of periods for long-term volatility calculation (default is 4x shortPeriod). - /// The alpha parameter controlling the base smoothing factor (default 0.2). - /// Thrown when shortPeriod is less than 1. - public Vidya(int shortPeriod, int longPeriod = 0, double alpha = 0.2) - { - if (shortPeriod < 1) - { - throw new System.ArgumentException("Short period must be greater than or equal to 1.", nameof(shortPeriod)); - } - _longPeriod = (longPeriod == 0) ? shortPeriod * 4 : longPeriod; - _alpha = alpha; - _shortBuffer = new CircularBuffer(shortPeriod); - _longBuffer = new CircularBuffer(_longPeriod); - WarmupPeriod = _longPeriod; - Name = $"Vidya({shortPeriod},{_longPeriod})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods for short-term volatility calculation. - /// The number of periods for long-term volatility calculation (default is 4x shortPeriod). - /// The alpha parameter controlling the base smoothing factor (default 0.2). - public Vidya(object source, int shortPeriod, int longPeriod = 0, double alpha = 0.2) - : this(shortPeriod, longPeriod, alpha) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _lastVIDYA = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _p_lastVIDYA = _lastVIDYA; - } - else - { - _lastVIDYA = _p_lastVIDYA; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double CalculateStdDev(CircularBuffer buffer) - { - double mean = buffer.Average(); - double sumSquaredDiff = 0; - var span = buffer.GetSpan(); - - for (int i = 0; i < buffer.Count; i++) - { - double diff = span[i] - mean; - sumSquaredDiff += diff * diff; - } - - return System.Math.Sqrt(sumSquaredDiff / buffer.Count); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateVidya(double shortStdDev, double longStdDev) - { - double s = _alpha * (shortStdDev / longStdDev); - return (s * Input.Value) + ((1.0 - s) * _lastVIDYA); - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - _shortBuffer.Add(Input.Value, Input.IsNew); - _longBuffer.Add(Input.Value, Input.IsNew); - - double vidya; - if (_index <= _longPeriod) - { - vidya = _shortBuffer.Average(); - } - else - { - double shortStdDev = CalculateStdDev(_shortBuffer); - double longStdDev = CalculateStdDev(_longBuffer); - vidya = CalculateVidya(shortStdDev, longStdDev); - } - - _lastVIDYA = vidya; - IsHot = _index >= WarmupPeriod; - - return vidya; - } -} diff --git a/lib/averages/Wma.cs b/lib/averages/Wma.cs deleted file mode 100644 index 04c2eff6..00000000 --- a/lib/averages/Wma.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// WMA: Weighted Moving Average -/// A moving average that assigns linearly decreasing weights to older data points. -/// The most recent price has the highest weight, and each older price receives -/// linearly less weight, creating a more responsive average than SMA. -/// -/// -/// The WMA calculation process: -/// 1. Assigns weights linearly decreasing with age -/// 2. Most recent price gets weight of period -/// 3. Each older price gets decremented weight -/// 4. Normalizes weights by sum of weights -/// 5. Applies weights through convolution -/// -/// Key characteristics: -/// - Linear weight distribution -/// - More responsive than SMA -/// - Less lag than SMA -/// - Emphasizes recent prices -/// - Implemented using efficient convolution operations -/// -/// Sources: -/// https://www.investopedia.com/articles/technical/060401.asp -/// https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:weighted_moving_average -/// -public class Wma : AbstractBase -{ - private readonly Convolution _convolution; - - /// The number of data points used in the WMA calculation. - /// Thrown when period is less than 1. - public Wma(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - double[] _kernel = GenerateWmaKernel(period); - _convolution = new Convolution(_kernel); - Name = "Wma"; - WarmupPeriod = period; - Init(); - } - - /// The data source object that publishes updates. - /// The number of data points used in the WMA calculation. - public Wma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - /// - /// Generates the linearly weighted convolution kernel for the WMA calculation. - /// - /// The period for which to generate the kernel. - /// An array of normalized linearly decreasing weights for the convolution operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double[] GenerateWmaKernel(int period) - { - double[] kernel = new double[period]; - double weightSum = period * (period + 1) * 0.5; // Multiply by 0.5 instead of dividing by 2 - double invWeightSum = 1.0 / weightSum; - - for (int i = 0; i < period; i++) - { - kernel[i] = (period - i) * invWeightSum; - } - - return kernel; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - var convolutionResult = _convolution.Calc(Input); - IsHot = _index >= WarmupPeriod; - - return convolutionResult.Value; - } -} diff --git a/lib/averages/Zlema.cs b/lib/averages/Zlema.cs deleted file mode 100644 index 8a4dc5eb..00000000 --- a/lib/averages/Zlema.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ZLEMA: Zero Lag Exponential Moving Average -/// A modified exponential moving average designed to reduce lag by incorporating -/// error correction based on predicted values. It estimates and removes lag by -/// extrapolating the trend using the difference between current and lagged prices. -/// -/// -/// The ZLEMA calculation process: -/// 1. Calculates lag period as (period - 1) / 2 -/// 2. Gets error correction term: 2 * price - lag_price -/// 3. Applies EMA to error-corrected price -/// 4. Results in reduced lag compared to standard EMA -/// -/// Key characteristics: -/// - Significantly reduced lag compared to EMA -/// - More responsive to price changes -/// - Uses error correction mechanism -/// - Maintains smoothness despite reduced lag -/// - Better trend following capabilities -/// -/// Sources: -/// John Ehlers and Ric Way - "Zero Lag (Well, Almost)" -/// Technical Analysis of Stocks and Commodities, 2010 -/// -public class Zlema : AbstractBase -{ - private readonly CircularBuffer _buffer; - private readonly int _lag; - private readonly Ema _ema; - private double _lastZLEMA, _p_lastZLEMA; - - /// The number of periods used in the ZLEMA calculation. - /// Thrown when period is less than 1. - public Zlema(int period) - { - if (period < 1) - { - throw new System.ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - WarmupPeriod = period; - _lag = (int)(0.5 * (period - 1)); - _buffer = new CircularBuffer(_lag + 1); - _ema = new Ema(period, useSma: false); - Name = $"Zlema({period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods used in the ZLEMA calculation. - public Zlema(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _ema.Init(); - _lastZLEMA = 0; - _p_lastZLEMA = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _p_lastZLEMA = _lastZLEMA; - } - else - { - _lastZLEMA = _p_lastZLEMA; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateErrorCorrection() - { - double lagValue = _buffer[System.Math.Max(0, _buffer.Count - 1 - _lag)]; - return (2.0 * Input.Value) - lagValue; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateZlema(double errorCorrection) - { - var tempValue = new TValue(Input.Time, errorCorrection, Input.IsNew); - return _ema.Calc(tempValue).Value; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - // Calculate error correction and apply EMA - double errorCorrection = CalculateErrorCorrection(); - double zlema = CalculateZlema(errorCorrection); - - _lastZLEMA = zlema; - IsHot = _index >= WarmupPeriod; - - return zlema; - } -} diff --git a/lib/averages/_list.md b/lib/averages/_list.md deleted file mode 100644 index 2492f1bf..00000000 --- a/lib/averages/_list.md +++ /dev/null @@ -1,36 +0,0 @@ -# Averages indicators - -✔️ AFIRMA - Adaptive FIR Moving Average -✔️ ALMA - Arnaud Legoux Moving Average -✔️ CONVOLUTION - 1D Convolution with sliding kernel -✔️ DEMA - Double Exponential Moving Average -✔️ DSMA - Dynamic Simple Moving Average -✔️ DWMA - Dynamic Weighted Moving Average -✔️ EMA - Exponential Moving Average -✔️ EPMA - Endpoint Moving Average -✔️ FRAMA - Fractal Adaptive Moving Average -✔️ FWMA - Forward Weighted Moving Average -✔️ GMA - Gaussian Moving Average -✔️ HMA - Hull Moving Average -✔️ HTIT - Hilbert Transform Instantaneous Trendline -✔️ HWMA - Hann Weighted Moving Average -✔️ JMA - Jurik Moving Average -✔️ KAMA - Kaufman Adaptive Moving Average -✔️ LTMA - Linear Time Moving Average -✔️ MAAF - Moving Average Adaptive Filter -✔️ MAMA - MESA Adaptive Moving Average (MAMA, FAMA) -✔️ MGDI - McGinley Dynamic Indicator -✔️ MMA - Modified Moving Average -✔️ PWMA - Parabolic Weighted Moving Average -✔️ QEMA - Quick Exponential Moving Average -✔️ REMA - Regularized Exponential Moving Average -✔️ RMA - Running Moving Average -✔️ SINEMA - Sine-weighted Moving Average -✔️ SMA - Simple Moving Average -✔️ SMMA - Smoothed Moving Average -✔️ T3 - Triple Exponential Moving Average (T3) -✔️ TEMA - Triple Exponential Moving Average -✔️ TRIMA - Triangular Moving Average -✔️ VIDYA - Variable Index Dynamic Average -✔️ WMA - Weighted Moving Average -✔️ ZLEMA - Zero-Lag Exponential Moving Average diff --git a/lib/class_types.md b/lib/class_types.md deleted file mode 100644 index 57198155..00000000 --- a/lib/class_types.md +++ /dev/null @@ -1,86 +0,0 @@ -# QuanTAlib Class Types by Input Requirements - -## Two TValues Required -- Huber -- Mae -- Mapd -- Mape -- Mase -- Mda -- Me -- Mpe -- Mse -- Msle -- Rae -- Rmse -- Rmsle -- Rse -- Rsquared -- Smape -- Beta (asset vs market returns) -- Corr (correlation between two series) -- Covar (covariance between two series) -- Granger (Granger causality test) -- Kendall (Kendall rank correlation) -- Spearman (Spearman rank correlation) -- Theil (Theil's U statistic) - -## One TValue Required -- Curvature -- Entropy -- Hurst -- Kurtosis -- Max -- Median -- Min -- Mode -- Percentile -- Skew -- Slope -- Stddev -- Tsf -- Variance -- Zscore -- Apo -- Dpo -- Macd -- Mom -- Pmo -- Po -- Ppo -- Roc -- Trix -- Vel -- Ac -- Ao -- Bop -- Cci -- Cfo -- Chop -- Cmo -- Cog -- Coppock -- Crsi -- Cti -- Dosc -- Efi -- Fisher -- Rsi -- Rsx -- Smi -- Srsi -- Stc -- Stoch -- Tsi -- Uo -- Willr - -## One TBar Required -- Aroon (uses high/low) -- Vortex (uses high/low/close) - -## Two TBars Required -- Adx (requires two bars for true range calculation) -- Adxr (requires two bars for directional movement) -- Dmi (requires two bars for directional movement) -- Dmx (requires two bars for directional comparison) diff --git a/lib/core/AbstractBarBase.cs b/lib/core/AbstractBarBase.cs deleted file mode 100644 index 1cbaf47f..00000000 --- a/lib/core/AbstractBarBase.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Provides a base implementation for financial indicators that work with bar data in the QuanTAlib library. -/// -/// -/// This abstract class implements the iTValue interface and defines common properties -/// and methods used by inheriting indicator types. It handles the basic flow of -/// receiving bar data, performing calculations, and publishing results. -/// -public abstract class AbstractBarBase : ITValue -{ - public System.DateTime Time { get; set; } - public double Value { get; set; } - public bool IsNew { get; set; } - public bool IsHot { get; set; } - public TBar Input { get; set; } - public string Name { get; set; } = ""; - public int WarmupPeriod { get; set; } - - public TValue Tick => new(Time, Value, IsNew, IsHot); - - public event ValueSignal Pub = delegate { }; - - protected int _index; - protected double _lastValidValue; - - protected AbstractBarBase() - { - // Add parameters into constructor if needed - } - - /// - /// Subscribes to bar data updates. - /// - /// The source of the bar data. - /// The event arguments containing the bar data. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Sub(object source, in TBarEventArgs args) => Calc(args.Bar); - - /// - /// Initializes the indicator's state. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Init() - { - _index = 0; - _lastValidValue = 0; - } - - /// - /// Checks if the input value is valid (not NaN or Infinity). - /// - /// The value to check. - /// True if the value is valid, false otherwise. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected static bool IsValidValue(double value) - { - return !double.IsNaN(value) && !double.IsInfinity(value); - } - - /// - /// Creates a new TValue with the current state. - /// - /// The value to use. - /// A new TValue instance. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected TValue CreateTValue(double value) - { - return new TValue(Time: Input.Time, Value: value, IsNew: Input.IsNew, IsHot: IsHot); - } - - /// - /// Calculates the indicator value based on the input bar. - /// - /// The input bar data. - /// A TValue containing the calculated result. - public virtual TValue Calc(TBar input) - { - Input = input; - if (!IsValidValue(input.Close)) - { - return Process(CreateTValue(GetLastValid())); - } - - Value = Calculation(); - return Process(CreateTValue(Value)); - } - - /// - /// Retrieves the last valid calculated value. - /// - /// The last valid value of the indicator. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual double GetLastValid() - { - return Value; - } - - /// - /// Manages the state of the indicator based on whether a new bar is being processed. - /// - /// Indicates whether the current input is a new bar. - protected abstract void ManageState(bool isNew); - - /// - /// Performs the actual calculation of the indicator value. - /// - /// The calculated indicator value. - protected abstract double Calculation(); - - /// - /// Processes the calculated value, updates the indicator's own state, - /// and publishes the result through an event. - /// - /// The calculated TValue to process. - /// The processed TValue. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual TValue Process(TValue value) - { - Time = value.Time; - Value = value.Value; - IsNew = value.IsNew; - IsHot = value.IsHot; - Pub?.Invoke(this, new ValueEventArgs(value)); - return value; - } -} diff --git a/lib/core/SimdExtensions.cs b/lib/core/SimdExtensions.cs new file mode 100644 index 00000000..1113f135 --- /dev/null +++ b/lib/core/SimdExtensions.cs @@ -0,0 +1,280 @@ +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace QuanTAlib; + +/// +/// SIMD-accelerated extension methods for high-performance array operations. +/// Uses Vector for 4-8x speedup on supported hardware with automatic scalar fallback. +/// +public static class SimdExtensions +{ + /// + /// Calculates sum using SIMD vectorization when available. + /// 4-8x faster than scalar loop on AVX2/AVX-512 hardware. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double SumSIMD(this ReadOnlySpan span) + { + if (span.IsEmpty) return 0.0; + + if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count) + { + Vector sum = Vector.Zero; + int vectorSize = Vector.Count; + int i = 0; + + // Process in vector chunks + for (; i <= span.Length - vectorSize; i += vectorSize) + { + var vector = new Vector(span.Slice(i, vectorSize)); + sum += vector; + } + + // Horizontal sum of vector + double result = 0.0; + for (int j = 0; j < vectorSize; j++) + result += sum[j]; + + // Process remaining elements + for (; i < span.Length; i++) + result += span[i]; + + return result; + } + + // Scalar fallback + double scalar = 0.0; + for (int i = 0; i < span.Length; i++) + scalar += span[i]; + return scalar; + } + + /// + /// Calculates minimum value using SIMD vectorization when available. + /// 4-6x faster than scalar loop on AVX2/AVX-512 hardware. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinSIMD(this ReadOnlySpan span) + { + if (span.IsEmpty) return double.NaN; + if (span.Length == 1) return span[0]; + + if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count) + { + int vectorSize = Vector.Count; + var minVec = new Vector(span.Slice(0, vectorSize)); + int i = vectorSize; + + // Process in vector chunks + for (; i <= span.Length - vectorSize; i += vectorSize) + { + var vector = new Vector(span.Slice(i, vectorSize)); + minVec = Vector.Min(minVec, vector); + } + + // Find minimum within vector + double result = minVec[0]; + for (int j = 1; j < vectorSize; j++) + { + if (minVec[j] < result) + result = minVec[j]; + } + + // Process remaining elements + for (; i < span.Length; i++) + { + if (span[i] < result) + result = span[i]; + } + + return result; + } + + // Scalar fallback + double min = span[0]; + for (int i = 1; i < span.Length; i++) + { + if (span[i] < min) + min = span[i]; + } + return min; + } + + /// + /// Calculates maximum value using SIMD vectorization when available. + /// 4-6x faster than scalar loop on AVX2/AVX-512 hardware. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxSIMD(this ReadOnlySpan span) + { + if (span.IsEmpty) return double.NaN; + if (span.Length == 1) return span[0]; + + if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count) + { + int vectorSize = Vector.Count; + var maxVec = new Vector(span.Slice(0, vectorSize)); + int i = vectorSize; + + // Process in vector chunks + for (; i <= span.Length - vectorSize; i += vectorSize) + { + var vector = new Vector(span.Slice(i, vectorSize)); + maxVec = Vector.Max(maxVec, vector); + } + + // Find maximum within vector + double result = maxVec[0]; + for (int j = 1; j < vectorSize; j++) + { + if (maxVec[j] > result) + result = maxVec[j]; + } + + // Process remaining elements + for (; i < span.Length; i++) + { + if (span[i] > result) + result = span[i]; + } + + return result; + } + + // Scalar fallback + double max = span[0]; + for (int i = 1; i < span.Length; i++) + { + if (span[i] > max) + max = span[i]; + } + return max; + } + + /// + /// Calculates average using SIMD vectorization when available. + /// 4-8x faster than scalar loop on AVX2/AVX-512 hardware. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageSIMD(this ReadOnlySpan span) + { + if (span.IsEmpty) return double.NaN; + return span.SumSIMD() / span.Length; + } + + /// + /// Calculates variance using SIMD vectorization (Welford's online algorithm adapted). + /// More numerically stable than naive two-pass algorithm. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double VarianceSIMD(this ReadOnlySpan span, double? mean = null) + { + if (span.Length < 2) return double.NaN; + + double m = mean ?? span.AverageSIMD(); + + if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count) + { + var meanVec = new Vector(m); + Vector sumSq = Vector.Zero; + int vectorSize = Vector.Count; + int i = 0; + + // Process in vector chunks + for (; i <= span.Length - vectorSize; i += vectorSize) + { + var vector = new Vector(span.Slice(i, vectorSize)); + var diff = vector - meanVec; + sumSq += diff * diff; + } + + // Horizontal sum of vector + double result = 0.0; + for (int j = 0; j < vectorSize; j++) + result += sumSq[j]; + + // Process remaining elements + for (; i < span.Length; i++) + { + double diff = span[i] - m; + result += diff * diff; + } + + return result / (span.Length - 1); + } + + // Scalar fallback + double sumSquares = 0.0; + for (int i = 0; i < span.Length; i++) + { + double diff = span[i] - m; + sumSquares += diff * diff; + } + return sumSquares / (span.Length - 1); + } + + /// + /// Calculates standard deviation using SIMD vectorization. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double StdDevSIMD(this ReadOnlySpan span, double? mean = null) + { + return Math.Sqrt(span.VarianceSIMD(mean)); + } + + /// + /// Finds both min and max in a single pass using SIMD vectorization. + /// More efficient than calling MinSIMD and MaxSIMD separately. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static (double Min, double Max) MinMaxSIMD(this ReadOnlySpan span) + { + if (span.IsEmpty) return (double.NaN, double.NaN); + if (span.Length == 1) return (span[0], span[0]); + + if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count) + { + int vectorSize = Vector.Count; + var minVec = new Vector(span.Slice(0, vectorSize)); + var maxVec = minVec; + int i = vectorSize; + + // Process in vector chunks + for (; i <= span.Length - vectorSize; i += vectorSize) + { + var vector = new Vector(span.Slice(i, vectorSize)); + minVec = Vector.Min(minVec, vector); + maxVec = Vector.Max(maxVec, vector); + } + + // Find min/max within vectors + double min = minVec[0]; + double max = maxVec[0]; + for (int j = 1; j < vectorSize; j++) + { + if (minVec[j] < min) min = minVec[j]; + if (maxVec[j] > max) max = maxVec[j]; + } + + // Process remaining elements + for (; i < span.Length; i++) + { + if (span[i] < min) min = span[i]; + if (span[i] > max) max = span[i]; + } + + return (min, max); + } + + // Scalar fallback + double scalarMin = span[0]; + double scalarMax = span[0]; + for (int i = 1; i < span.Length; i++) + { + if (span[i] < scalarMin) scalarMin = span[i]; + if (span[i] > scalarMax) scalarMax = span[i]; + } + return (scalarMin, scalarMax); + } +} diff --git a/lib/core/abstractBase.cs b/lib/core/abstractBase.cs deleted file mode 100644 index 26ff9c07..00000000 --- a/lib/core/abstractBase.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Provides a base implementation for financial indicators in the QuanTAlib library. -/// -/// -/// This abstract class implements the iTValue interface and defines common properties -/// and methods used by inheriting indicator types. It handles the basic flow of -/// receiving data, performing calculations, and publishing results. -/// -public abstract class AbstractBase : ITValue -{ - public System.DateTime Time { get; set; } - public double Value { get; set; } - public bool IsNew { get; set; } - public bool IsHot { get; set; } - public TValue Input { get; set; } - public TValue Input2 { get; set; } - public TBar BarInput { get; set; } - public TBar BarInput2 { get; set; } - public string Name { get; set; } = ""; - public int WarmupPeriod { get; set; } - public TValue Tick => new(Time, Value, IsNew, IsHot); - public event ValueSignal Pub = delegate { }; - protected int _index; - protected double _lastValidValue; - - protected AbstractBase() - { - // Add parameters into constructor if needed - } - - /// - /// Checks if the input value is valid (not NaN or Infinity). - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected static bool IsValidValue(double value) - { - return !double.IsNaN(value) && !double.IsInfinity(value); - } - - /// - /// Creates a new TValue with the current state. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected static TValue CreateTValue(System.DateTime time, double value, bool isNew, bool isHot = false) - { - return new TValue(time, value, isNew, isHot); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Sub(object source, in ValueEventArgs args) => Calc(args.Tick); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Sub(object source1, object source2, in ValueEventArgs args1, in ValueEventArgs args2) => - Calc(args1.Tick, args2.Tick); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Sub(object source, in TBarEventArgs args) => Calc(args.Bar); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Init() - { - _index = 0; - _lastValidValue = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual TValue Calc(TValue input) - { - Input = input; - Input2 = CreateTValue(input.Time, double.NaN, input.IsNew, input.IsHot); - return Process(input.Value, input.Time, input.IsNew); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual TValue Calc(double value, bool isNew) - { - Input = CreateTValue(Time, value, isNew); - Input2 = CreateTValue(Time, double.NaN, false); - return Process(Input.Value, Input.Time, Input.IsNew); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual TValue Calc(TBar barInput) - { - BarInput = barInput; - return Process(barInput.Close, barInput.Time, barInput.IsNew); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual TValue Calc(TValue input1, TValue input2) - { - Input = input1; - Input2 = input2; - return Process(input1.Value, input2.Value, input1.Time, input1.IsNew); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual TValue Calc(TBar input1, TBar input2) - { - BarInput = input1; - BarInput2 = input2; - return Process(input1.Close, input2.Close, input1.Time, input1.IsNew); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual TValue Calc(double value1, double value2) - { - var now = System.DateTime.Now; - Input = CreateTValue(now, value1, true, true); - Input2 = CreateTValue(now, value2, true, true); - return Process(value1, value2, now, true); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual TValue Process(double value, System.DateTime time, bool isNew) - { - if (!IsValidValue(value)) - { - return Process(CreateTValue(time, GetLastValid(), isNew, IsHot)); - } - Value = Calculation(); - return Process(CreateTValue(time, Value, isNew, IsHot)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual TValue Process(double value1, double value2, System.DateTime time, bool isNew) - { - if (!IsValidValue(value1) || !IsValidValue(value2)) - { - return Process(CreateTValue(time, GetLastValid(), isNew, IsHot)); - } - Value = Calculation(); - return Process(CreateTValue(time, Value, isNew, IsHot)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual TValue Process(TValue value) - { - Time = value.Time; - Value = value.Value; - IsNew = value.IsNew; - IsHot = value.IsHot; - Pub?.Invoke(this, new ValueEventArgs(value)); - return value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual double GetLastValid() - { - return Value; - } - - protected abstract void ManageState(bool isNew); - - protected abstract double Calculation(); -} diff --git a/lib/core/circularbuffer.cs b/lib/core/circularbuffer.cs deleted file mode 100644 index a203a8e9..00000000 --- a/lib/core/circularbuffer.cs +++ /dev/null @@ -1,443 +0,0 @@ -using System.Collections; -using System.Runtime.CompilerServices; -using System.Numerics; - -namespace QuanTAlib; - -/// -/// Represents a circular buffer of double values with fixed capacity. -/// -/// -/// This class provides efficient operations for adding, accessing, and manipulating -/// a fixed-size buffer of double values. It uses SIMD operations for improved performance -/// on supported hardware. -/// -[SkipLocalsInit] -public class CircularBuffer : IEnumerable -{ - private readonly double[] _buffer; - private readonly int _capacity; - private int _start = 0; - private int _size = 0; - - /// - /// Gets the maximum number of elements that can be contained in the buffer. - /// - public int Capacity => _capacity; - - /// - /// Gets the number of elements currently contained in the buffer. - /// - public int Count => _size; - - /// - /// Initializes a new instance of the CircularBuffer class with the specified capacity. - /// - /// The maximum number of elements the buffer can hold. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CircularBuffer(int capacity) - { - _capacity = capacity; - _buffer = GC.AllocateArray(capacity, pinned: true); - } - - /// - /// Adds an item to the buffer. - /// - /// The item to add to the buffer. - /// Indicates whether the item is a new value or an update to the last added value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(double item, bool isNew = true) - { - if (_size == 0 || isNew) - { - if (_size < _capacity) - { - _buffer[(_start + _size) % _capacity] = item; - _size++; - } - else - { - _buffer[_start] = item; - _start = (_start + 1) % _capacity; - } - } - else - { - _buffer[(_start + _size - 1) % _capacity] = item; - } - } - - /// - /// Gets or sets the element at the specified index. - /// - /// The zero-based index of the element to get or set. - /// The element at the specified index. - public double this[Index index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - int actualIndex = index.IsFromEnd ? _size - index.Value : index.Value; - actualIndex = Math.Clamp(actualIndex, 0, _size - 1); - return _buffer[(_start + actualIndex) % _capacity]; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - int actualIndex = index.IsFromEnd ? _size - index.Value : index.Value; - actualIndex = Math.Clamp(actualIndex, 0, _size - 1); - _buffer[(_start + actualIndex) % _capacity] = value; - } - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void ThrowArgumentOutOfRangeException(string paramName) - { - throw new ArgumentOutOfRangeException(paramName, "Index is out of range."); - } - - /// - /// Gets the newest (most recently added) element in the buffer. - /// - /// The newest element in the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Newest() - { - if (_size == 0) - return 0; - return _buffer[(_start + _size - 1) % _capacity]; - } - - /// - /// Gets the oldest element in the buffer. - /// - /// The oldest element in the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Oldest() - { - if (_size == 0) - ThrowInvalidOperationException(); - return _buffer[_start]; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void ThrowInvalidOperationException() - { - throw new InvalidOperationException("Buffer is empty."); - } - - /// - /// Returns an enumerator that iterates through the buffer. - /// - /// An enumerator for the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new(this); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Represents an enumerator for the CircularBuffer. - /// - public readonly struct Enumerator : IEnumerator - { - private readonly CircularBuffer _buffer; - private readonly int _size; - private readonly int _index; - private readonly double _current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Enumerator(CircularBuffer buffer) - { - _buffer = buffer; - _size = buffer._size; - _index = -1; - _current = default; - } - - /// - /// Advances the enumerator to the next element of the buffer. - /// - /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - if (_index + 1 >= _size) - return false; - - Unsafe.AsRef(in _index)++; - Unsafe.AsRef(in _current) = _buffer[_index]; - return true; - } - - /// - /// Gets the element in the buffer at the current position of the enumerator. - /// - public double Current => _current; - object IEnumerator.Current => Current; - - /// - /// Sets the enumerator to its initial position, which is before the first element in the buffer. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset() - { - Unsafe.AsRef(in _index) = -1; - Unsafe.AsRef(in _current) = default; - } - - /// - /// Disposes the enumerator. - /// - public void Dispose() { } - } - - /// - /// Copies the elements of the buffer to an array, starting at a particular array index. - /// - /// The one-dimensional array that is the destination of the elements copied from the buffer. - /// The zero-based index in array at which copying begins. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(double[] destination, int destinationIndex) - { - if (_size == 0) - return; - - if (_start + _size <= _capacity) - { - Array.Copy(_buffer, _start, destination, destinationIndex, _size); - } - else - { - int firstPartLength = _capacity - _start; - Array.Copy(_buffer, _start, destination, destinationIndex, firstPartLength); - Array.Copy(_buffer, 0, destination, destinationIndex + firstPartLength, _size - firstPartLength); - } - } - - /// - /// Returns a read-only span over the contents of the buffer. - /// - /// A read-only span over the buffer contents. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetSpan() - { - if (_size == 0) - return ReadOnlySpan.Empty; - - if (_start + _size <= _capacity) - { - return new ReadOnlySpan(_buffer, _start, _size); - } - - return new ReadOnlySpan(ToArray()); - } - - /// - /// Gets the internal buffer array. - /// - public double[] InternalBuffer => _buffer; - - /// - /// Returns a read-only span over the entire internal buffer. - /// - /// A read-only span over the entire internal buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetInternalSpan() => _buffer.AsSpan(); - - /// - /// Removes all elements from the buffer. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() - { - Array.Clear(_buffer, 0, _buffer.Length); - _start = 0; - _size = 0; - } - - /// - /// Returns the maximum value in the buffer. - /// - /// The maximum value in the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Max() - { - if (_size == 0) - ThrowInvalidOperationException(); - - return MaxSimd(); - } - - /// - /// Returns the minimum value in the buffer. - /// - /// The minimum value in the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Min() - { - if (_size == 0) - ThrowInvalidOperationException(); - - return MinSimd(); - } - - /// - /// Computes the sum of all values in the buffer. - /// - /// The sum of all values in the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Sum() - { - return SumSimd(); - } - - /// - /// Computes the average of all values in the buffer. - /// - /// The average of all values in the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Average() - { - if (_size == 0) - ThrowInvalidOperationException(); - - return SumSimd() / _size; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double MaxSimd() - { - var span = GetSpan(); - var vectorSize = Vector.Count; - var maxVector = new Vector(double.MinValue); - - int i = 0; - ref double spanRef = ref System.Runtime.InteropServices.MemoryMarshal.GetReference(span); - - for (; i <= span.Length - vectorSize; i += vectorSize) - { - maxVector = Vector.Max(maxVector, Unsafe.As>(ref Unsafe.Add(ref spanRef, i))); - } - - double max = double.MinValue; - for (int j = 0; j < vectorSize; j++) - { - max = Math.Max(max, maxVector[j]); - } - - for (; i < span.Length; i++) - { - max = Math.Max(max, span[i]); - } - - return max; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double MinSimd() - { - var span = GetSpan(); - var vectorSize = Vector.Count; - var minVector = new Vector(double.MaxValue); - - int i = 0; - ref double spanRef = ref System.Runtime.InteropServices.MemoryMarshal.GetReference(span); - - for (; i <= span.Length - vectorSize; i += vectorSize) - { - minVector = Vector.Min(minVector, Unsafe.As>(ref Unsafe.Add(ref spanRef, i))); - } - - double min = double.MaxValue; - for (int j = 0; j < vectorSize; j++) - { - min = Math.Min(min, minVector[j]); - } - - for (; i < span.Length; i++) - { - min = Math.Min(min, span[i]); - } - - return min; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double SumSimd() - { - var span = GetSpan(); - var vectorSize = Vector.Count; - var sumVector = Vector.Zero; - - int i = 0; - ref double spanRef = ref System.Runtime.InteropServices.MemoryMarshal.GetReference(span); - - for (; i <= span.Length - vectorSize; i += vectorSize) - { - sumVector += Unsafe.As>(ref Unsafe.Add(ref spanRef, i)); - } - - double sum = 0; - for (int j = 0; j < vectorSize; j++) - { - sum += sumVector[j]; - } - - for (; i < span.Length; i++) - { - sum += span[i]; - } - - return sum; - } - - /// - /// Copies the buffer elements to a new array. - /// - /// An array containing copies of the buffer elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double[] ToArray() - { - double[] array = new double[_size]; - CopyTo(array, 0); - return array; - } - - /// - /// Performs a parallel operation on the buffer elements. - /// - /// The operation to perform on each partition of the buffer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ParallelOperation(Func operation) - { - const int MinimumPartitionSize = 1024; - - if (_size < MinimumPartitionSize) - { - var span = GetSpan(); - var array = span.ToArray(); - operation(array, 0, array.Length); - return; - } - - int partitionCount = Environment.ProcessorCount; - int partitionSize = _size / partitionCount; - - if (partitionSize < MinimumPartitionSize) - { - partitionCount = Math.Max(1, _size / MinimumPartitionSize); - partitionSize = _size / partitionCount; - } - - var buffer = ToArray(); - var results = GC.AllocateUninitializedArray(partitionCount); - - Parallel.For(0, partitionCount, i => - { - int start = i * partitionSize; - int length = (i == partitionCount - 1) ? _size - start : partitionSize; - results[i] = operation(buffer, start, length); - }); - } -} diff --git a/lib/core/formatters.cs b/lib/core/formatters.cs deleted file mode 100644 index 9e567ce7..00000000 --- a/lib/core/formatters.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Microsoft.DotNet.Interactive.Formatting; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace QuanTAlib; -public static class Formatters -{ - const string smallfont = "smaller"; - const string pad = "18"; - public static void Initialize() - { - Formatter.Register((tick, writer) => - { - var sb = new StringBuilder(); - sb.Append(""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append("
{tick.Time:yyyy-MM-dd HH:mm:ss}{tick.Value:F2}{(tick.IsHot ? "🔥" : "❄️")}
"); - writer.Write(sb.ToString()); - }, HtmlFormatter.MimeType); - - Formatter.Register((series, writer) => - { - var sb = new StringBuilder(); - sb.Append(""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append(""); - - for (int i = 0; i < Math.Min(100, series.Count); i++) - { - TValue item = series[i]; - sb.Append(""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append(""); - } - sb.Append("
{series.Name}IndexValue
{item.Time:yyyy-MM-dd HH:mm:ss}{i}{item.Value:F2}{(item.IsHot ? "🔥" : "❄️")}
"); - if (series.Count > 100) - { - sb.Append("

Showing first 100 items. Total items: " + series.Count + "

"); - } - writer.Write(sb.ToString()); - }, HtmlFormatter.MimeType); - - Formatter.Register((bar, writer) => - { - var sb = new StringBuilder(); - sb.Append(""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append("
{bar.Time:yyyy-MM-dd HH:mm:ss}{bar.Open:F2}{bar.High:F2}{bar.Low:F2}{bar.Close:F2} {bar.Volume:F2}
"); - writer.Write(sb.ToString()); - }, HtmlFormatter.MimeType); - - Formatter.Register((series, writer) => - { - var sb = new StringBuilder(); - sb.Append(""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append(""); - for (int i = 0; i < Math.Min(100, series.Count); i++) - { - TBar item = series[i]; - sb.Append(""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append($""); - sb.Append(""); - } - sb.Append("
{series.Name}IndexOpenHighLowCloseVolume
{item.Time:yyyy-MM-dd HH:mm:ss}{i}{item.Open:F2}{item.High:F2}{item.Low:F2}{item.Close:F2}{item.Volume:F2}
"); - if (series.Count > 100) - { - sb.Append("

Showing first 100 items. Total items: " + series.Count + "

"); - } - writer.Write(sb.ToString()); - }, HtmlFormatter.MimeType); - } -} diff --git a/lib/core/tbar.cs b/lib/core/tbar.cs index 5e949861..4f51a63b 100644 --- a/lib/core/tbar.cs +++ b/lib/core/tbar.cs @@ -2,60 +2,79 @@ using System.Runtime.CompilerServices; namespace QuanTAlib; -public interface ITBar -{ - DateTime Time { get; } - double Open { get; } - double High { get; } - double Low { get; } - double Close { get; } - double Volume { get; } - bool IsNew { get; } -} - +/// +/// A lightweight struct representing an OHLCV bar. +/// Pure data type: 48 bytes (long + 5 doubles). +/// [SkipLocalsInit] -public readonly record struct TBar(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : ITBar +public readonly struct TBar : IEquatable { - public DateTime Time { get; init; } = Time; - public double Open { get; init; } = Open; - public double High { get; init; } = High; - public double Low { get; init; } = Low; - public double Close { get; init; } = Close; - public double Volume { get; init; } = Volume; - public bool IsNew { get; init; } = IsNew; + public readonly long Time; + public readonly double Open; + public readonly double High; + public readonly double Low; + public readonly double Close; + public readonly double Volume; + public DateTime AsDateTime => new(Time, DateTimeKind.Utc); + + // TValue conversions (Zero-copy / lightweight creation) + public TValue O { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Time, Open); } + public TValue H { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Time, High); } + public TValue L { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Time, Low); } + public TValue C { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Time, Close); } + public TValue V { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Time, Volume); } + + // Computed properties (calculated on demand, no storage overhead) public double HL2 => (High + Low) * 0.5; public double OC2 => (Open + Close) * 0.5; - public double OHL3 => (Open + High + Low) / 3; - public double HLC3 => (High + Low + Close) / 3; + public double OHL3 => (Open + High + Low) / 3.0; + public double HLC3 => (High + Low + Close) / 3.0; public double OHLC4 => (Open + High + Low + Close) * 0.25; public double HLCC4 => (High + Low + Close + Close) * 0.25; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { } + public TBar(long time, double open, double high, double low, double close, double volume) + { + Time = time; + Open = open; + High = high; + Low = low; + Close = close; + Volume = volume; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBar(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) - : this(DateTime.UtcNow, Open, High, Low, Close, Volume, IsNew) { } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBar(double value) - : this(Time: DateTime.UtcNow, Open: value, High: value, Low: value, Close: value, Volume: value, IsNew: true) { } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBar(TValue value) - : this(Time: value.Time, Open: value.Value, High: value.Value, Low: value.Value, Close: value.Value, Volume: value.Value, IsNew: value.IsNew) { } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBar(TBar v) - : this(Time: v.Time, Open: v.Open, High: v.High, Low: v.Low, Close: v.Close, Volume: v.Volume, IsNew: true) { } + public TBar(DateTime time, double open, double high, double low, double close, double volume) + { + Time = time.Ticks; + Open = open; + High = high; + Low = low; + Close = close; + Volume = volume; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator double(TBar bar) => bar.Close; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator DateTime(TBar tv) => tv.Time; + public static implicit operator DateTime(TBar bar) => new(bar.Time, DateTimeKind.Utc); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]"; + public override string ToString() => $"[{AsDateTime:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]"; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(TBar other) => + Time == other.Time && + Open == other.Open && + High == other.High && + Low == other.Low && + Close == other.Close && + Volume == other.Volume; + + public override bool Equals(object? obj) => obj is TBar other && Equals(other); + public override int GetHashCode() => HashCode.Combine(Time, Open, High, Low, Close, Volume); + public static bool operator ==(TBar left, TBar right) => left.Equals(right); + public static bool operator !=(TBar left, TBar right) => !left.Equals(right); } diff --git a/lib/core/tbarseries.cs b/lib/core/tbarseries.cs index 32163238..3098c9b8 100644 --- a/lib/core/tbarseries.cs +++ b/lib/core/tbarseries.cs @@ -1,110 +1,147 @@ +using System.Collections; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace QuanTAlib; -public delegate void BarSignal(object source, in TBarEventArgs args); - -[SkipLocalsInit] -public sealed class TBarEventArgs : EventArgs +/// +/// A high-performance OHLCV time series implementation using Structure of Arrays (SoA) layout. +/// Stores Time, Open, High, Low, Close, Volume in separate contiguous arrays for SIMD efficiency. +/// Exposes TSeries views for each component that share the underlying Time array. +/// +public class TBarSeries : IReadOnlyList { - public readonly TBar Bar; + // Internal storage: SoA layout + protected readonly List _t = new(); + protected readonly List _o = new(); + protected readonly List _h = new(); + protected readonly List _l = new(); + protected readonly List _c = new(); + protected readonly List _v = new(); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBarEventArgs(TBar bar) => Bar = bar; -} + public string Name { get; set; } = "Bar"; + public event Action? Pub; -[SkipLocalsInit] -public class TBarSeries : List -{ - private static readonly TBar Default = new(DateTime.MinValue, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN); + // Public properties are Views into the main data + public TSeries Open { get; } + public TSeries High { get; } + public TSeries Low { get; } + public TSeries Close { get; } + public TSeries Volume { get; } - public TSeries Open { get; init; } - public TSeries High { get; init; } - public TSeries Low { get; init; } - public TSeries Close { get; init; } - public TSeries Volume { get; init; } + // Aliases for convenience + public TSeries O => Open; + public TSeries H => High; + public TSeries L => Low; + public TSeries C => Close; + public TSeries V => Volume; - public TBar Last => Count > 0 ? this[^1] : Default; - public TBar First => Count > 0 ? this[0] : Default; - public int Length => Count; - public string Name { get; set; } - public event BarSignal Pub = delegate { }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] public TBarSeries() { - Name = "Bar"; - Open = new TSeries(); - High = new TSeries(); - Low = new TSeries(); - Close = new TSeries(); - Volume = new TSeries(); + // Initialize views sharing the same Time list but different Value lists + Open = new TSeries(_t, _o) { Name = "Open" }; + High = new TSeries(_t, _h) { Name = "High" }; + Low = new TSeries(_t, _l) { Name = "Low" }; + Close = new TSeries(_t, _c) { Name = "Close" }; + Volume = new TSeries(_t, _v) { Name = "Volume" }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TBarSeries(object source) : this() + /// + /// Constructor with capacity hint to avoid List growth overhead. + /// + public TBarSeries(int capacity) { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); + _t = new List(capacity); + _o = new List(capacity); + _h = new List(capacity); + _l = new List(capacity); + _c = new List(capacity); + _v = new List(capacity); + + // Initialize views sharing the same Time list but different Value lists + Open = new TSeries(_t, _o) { Name = "Open" }; + High = new TSeries(_t, _h) { Name = "High" }; + Low = new TSeries(_t, _l) { Name = "Low" }; + Close = new TSeries(_t, _c) { Name = "Close" }; + Volume = new TSeries(_t, _v) { Name = "Volume" }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public new virtual void Add(TBar bar) + public int Count { - if (bar.IsNew || base.Count == 0) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _c.Count; + } + + public TBar this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new(_t[index], _o[index], _h[index], _l[index], _c[index], _v[index]); + } + + public TBar Last + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _c.Count > 0 ? new(_t[^1], _o[^1], _h[^1], _l[^1], _c[^1], _v[^1]) : default; + } + + public long LastTime { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _t.Count > 0 ? _t[^1] : 0; } + public double LastOpen { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _o.Count > 0 ? _o[^1] : double.NaN; } + public double LastHigh { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _h.Count > 0 ? _h[^1] : double.NaN; } + public double LastLow { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _l.Count > 0 ? _l[^1] : double.NaN; } + public double LastClose { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _c.Count > 0 ? _c[^1] : double.NaN; } + public double LastVolume { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _v.Count > 0 ? _v[^1] : double.NaN; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(TBar bar, bool isNew = true) + { + if (isNew || _c.Count == 0) { - base.Add(bar); + _t.Add(bar.Time); + _o.Add(bar.Open); + _h.Add(bar.High); + _l.Add(bar.Low); + _c.Add(bar.Close); + _v.Add(bar.Volume); } else { - this[^1] = bar; + int lastIdx = _c.Count - 1; + _t[lastIdx] = bar.Time; + _o[lastIdx] = bar.Open; + _h[lastIdx] = bar.High; + _l[lastIdx] = bar.Low; + _c[lastIdx] = bar.Close; + _v[lastIdx] = bar.Volume; } - Pub?.Invoke(this, new TBarEventArgs(bar)); - - Open.Add(bar.Time, bar.Open, IsNew: bar.IsNew, IsHot: true); - High.Add(bar.Time, bar.High, IsNew: bar.IsNew, IsHot: true); - Low.Add(bar.Time, bar.Low, IsNew: bar.IsNew, IsHot: true); - Close.Add(bar.Time, bar.Close, IsNew: bar.IsNew, IsHot: true); - Volume.Add(bar.Time, bar.Volume, IsNew: bar.IsNew, IsHot: true); + Pub?.Invoke(bar); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) => - Add(new TBar(Time, Open, High, Low, Close, Volume, IsNew)); + public void Add(long time, double open, double high, double low, double close, double volume, bool isNew = true) => + Add(new TBar(time, open, high, low, close, volume), isNew); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) => - Add(new TBar(DateTime.Now, Open, High, Low, Close, Volume, IsNew)); + public void Add(DateTime time, double open, double high, double low, double close, double volume, bool isNew = true) => + Add(new TBar(time.Ticks, open, high, low, close, volume), isNew); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(TBarSeries series) + public void Add(IEnumerable t, IEnumerable o, IEnumerable h, IEnumerable l, IEnumerable c, IEnumerable v) { - if (series == this) + _t.AddRange(t); + _o.AddRange(o); + _h.AddRange(h); + _l.AddRange(l); + _c.AddRange(c); + _v.AddRange(v); + } + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < _c.Count; i++) { - // If adding itself, create a copy to avoid modification during enumeration - var copy = new TBarSeries { Name = Name }; - copy.AddRange(this); - AddRange(copy); - } - else - { - AddRange(series); + yield return new TBar(_t[i], _o[i], _h[i], _l[i], _c[i], _v[i]); } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public new virtual void AddRange(IEnumerable collection) - { - foreach (var item in collection) - { - Add(item); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Sub(object source, in TBarEventArgs args) - { - Add(args.Bar); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/lib/core/tseries.cs b/lib/core/tseries.cs index acbe3ac6..2d1b26f7 100644 --- a/lib/core/tseries.cs +++ b/lib/core/tseries.cs @@ -1,122 +1,146 @@ +using System.Collections; using System.Runtime.CompilerServices; -using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace QuanTAlib; -public delegate void ValueSignal(object source, in ValueEventArgs args); - -[SkipLocalsInit] -public sealed class ValueEventArgs : EventArgs +/// +/// A high-performance time series implementation using Structure of Arrays (SoA) layout. +/// Stores Time (long) and Value (double) in separate contiguous arrays for SIMD efficiency. +/// Supports "New Bar" vs "Update Last" streaming semantics. +/// +public class TSeries : IReadOnlyList { - public readonly TValue Tick; + // Internal storage: SoA layout + // We use List for dynamic sizing but access internal arrays via CollectionsMarshal for speed + protected readonly List _t; + protected readonly List _v; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEventArgs(TValue value) => Tick = value; -} + public string Name { get; set; } = "Data"; -[SkipLocalsInit] -public class TSeries : List -{ - private static readonly TValue Default = new(DateTime.MinValue, double.NaN); + // Event optimization: Use Action to avoid EventArgs allocation + // Note: Events are generally discouraged in the hot path of this high-perf design, + // but kept for compatibility/chaining. + public event Action? Pub; - public IEnumerable t => this.Select(item => item.t); - public IEnumerable v => this.Select(item => item.v); - public TValue Last => Count > 0 ? this[^1] : Default; - public TValue First => Count > 0 ? this[0] : Default; - public int Length => Count; - public string Name { get; set; } + public TSeries() + { + _t = new List(); + _v = new List(); + } /// - /// Event that publishes value updates to subscribers. This event is used in the pub/sub pattern - /// where TSeries instances can subscribe to updates from other data sources through the Sub method, - /// and publish their own updates to downstream subscribers. + /// Constructor with capacity hint to avoid List growth overhead. /// - [SuppressMessage("Minor Code Smell", "S3264:Events should be invoked", Justification = "Event is invoked through delegate")] - public event ValueSignal Pub = delegate { }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSeries() + public TSeries(int capacity) { - Name = "Data"; + _t = new List(capacity); + _v = new List(capacity); + } + + /// + /// Constructor for wrapping existing lists (e.g. from TBarSeries). + /// + public TSeries(List time, List values) + { + _t = time; + _v = values; + } + + public int Count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _v.Count; + } + + public TValue this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new(_t[index], _v[index]); + } + + public TValue Last + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _v.Count > 0 ? new(_t[^1], _v[^1]) : default; + } + + public double LastValue + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _v.Count > 0 ? _v[^1] : double.NaN; + } + + public long LastTime + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _t.Count > 0 ? _t[^1] : 0; + } + + /// + /// Direct access to the underlying Value array as a Span for SIMD operations. + /// + public ReadOnlySpan Values + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => CollectionsMarshal.AsSpan(_v); + } + + /// + /// Direct access to the underlying Time array as a Span. + /// + public ReadOnlySpan Times + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => CollectionsMarshal.AsSpan(_t); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSeries(object source) : this() + public virtual void Add(TValue value, bool isNew) { - var pubEvent = source.GetType().GetEvent("Pub"); - if (pubEvent != null) + if (isNew || _v.Count == 0) { - pubEvent.AddEventHandler(source, new ValueSignal(Sub)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator List(TSeries series) => series.Select(item => item.Value).ToList(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator double[](TSeries series) => series.Select(item => item.Value).ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public new virtual void Add(TValue tick) - { - if (tick.IsNew || base.Count == 0) - { - base.Add(tick); + _t.Add(value.Time); + _v.Add(value.Value); } else { - this[^1] = tick; + // Update last bar + int lastIdx = _v.Count - 1; + _t[lastIdx] = value.Time; + _v[lastIdx] = value.Value; } - Pub?.Invoke(this, new ValueEventArgs(tick)); + Pub?.Invoke(value); } + // Overload for backward compatibility (assumes isNew=true) [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Add(DateTime Time, double Value, bool IsNew = true, bool IsHot = true) => - Add(new TValue(Time, Value, IsNew, IsHot)); + public virtual void Add(TValue value) => Add(value, true); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Add(double Value, bool IsNew = true, bool IsHot = true) => - Add(new TValue(DateTime.UtcNow, Value, IsNew, IsHot)); + public void Add(long time, double value, bool isNew = true) => Add(new TValue(time, value), isNew); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(DateTime time, double value, bool isNew = true) => Add(new TValue(time.Ticks, value), isNew); + public void Add(IEnumerable values) { - var valueList = values.ToList(); - int count = valueList.Count; - DateTime startTime = DateTime.UtcNow - TimeSpan.FromHours(count); - - for (int i = 0; i < count; i++) + long t = DateTime.UtcNow.Ticks; + foreach (var v in values) { - Add(startTime, valueList[i]); - startTime = startTime.AddHours(1); + Add(new TValue(t, v), isNew: true); + t += TimeSpan.TicksPerMinute; // Dummy time increment } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(TSeries series) + // IEnumerable implementation + public IEnumerator GetEnumerator() { - if (series == this) + for (int i = 0; i < _v.Count; i++) { - // If adding itself, create a copy to avoid modification during enumeration - var copy = new TSeries { Name = Name }; - copy.AddRange(this); - AddRange(copy); - } - else - { - AddRange(series); + yield return new TValue(_t[i], _v[i]); } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public new virtual void AddRange(IEnumerable collection) - { - foreach (var item in collection) - { - Add(item); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Sub(object source, in ValueEventArgs args) => Add(args.Tick); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/lib/core/tvalue.cs b/lib/core/tvalue.cs index 04f4e517..49050c18 100644 --- a/lib/core/tvalue.cs +++ b/lib/core/tvalue.cs @@ -2,40 +2,56 @@ using System.Runtime.CompilerServices; namespace QuanTAlib; -public interface ITValue -{ - DateTime Time { get; } - double Value { get; } - bool IsNew { get; } - bool IsHot { get; } -} - +/// +/// A lightweight struct representing a time-value pair. +/// Pure data type: 16 bytes (long + double). +/// [SkipLocalsInit] -public readonly record struct TValue(DateTime Time, double Value, bool IsNew = true, bool IsHot = true) : ITValue +public readonly struct TValue : IEquatable { - public DateTime Time { get; init; } = Time; - public double Value { get; init; } = Value; - public bool IsNew { get; init; } = IsNew; - public bool IsHot { get; init; } = IsHot; - public DateTime t => Time; - public double v => Value; + /// + /// Time in ticks (UTC). + /// + public readonly long Time; + + /// + /// The value. + /// + public readonly double Value; + + /// + /// Convenience property to get DateTime from Ticks. + /// + public DateTime AsDateTime => new(Time, DateTimeKind.Utc); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TValue() : this(DateTime.UtcNow, 0) { } + public TValue(long time, double value) + { + Time = time; + Value = value; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TValue(double value, bool isNew = true, bool isHot = true) - : this(DateTime.UtcNow, value, IsNew: isNew, IsHot: isHot) { } + public TValue(DateTime time, double value) + { + Time = time.Ticks; + Value = value; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator double(TValue tv) => tv.Value; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator DateTime(TValue tv) => tv.Time; + public static implicit operator DateTime(TValue tv) => new(tv.Time, DateTimeKind.Utc); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator TValue(double value) => new TValue(DateTime.UtcNow, value); + public override string ToString() => $"[{AsDateTime:yyyy-MM-dd HH:mm:ss}, {Value:F2}]"; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}, {Value:F2}, IsNew: {IsNew}, IsHot: {IsHot}]"; + public bool Equals(TValue other) => Time == other.Time && Value == other.Value; + + public override bool Equals(object? obj) => obj is TValue other && Equals(other); + public override int GetHashCode() => HashCode.Combine(Time, Value); + public static bool operator ==(TValue left, TValue right) => left.Equals(right); + public static bool operator !=(TValue left, TValue right) => !left.Equals(right); } diff --git a/lib/errors/Huber.cs b/lib/errors/Huber.cs deleted file mode 100644 index ffe7a0a1..00000000 --- a/lib/errors/Huber.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Huber Loss: A robust error metric that combines squared error for small deviations -/// and absolute error for large deviations. This provides a balance between the high -/// sensitivity of MSE to outliers and the constant gradient of MAE. -/// -/// -/// The Huber Loss calculation process: -/// 1. For each point, calculates error between actual and predicted values -/// 2. If absolute error ≤ delta: uses squared error (like MSE) -/// 3. If absolute error > delta: uses linear error (like MAE) -/// 4. Averages the losses over the period -/// -/// Key characteristics: -/// - Combines benefits of MSE and MAE -/// - Less sensitive to outliers than MSE -/// - More sensitive to small errors than MAE -/// - Differentiable at all points -/// - Adjustable via delta parameter -/// -/// Formula: -/// For error e = actual - predicted: -/// L(e) = 0.5 * e² if |e| ≤ δ -/// L(e) = δ * (|e| - 0.5δ) if |e| > δ -/// -/// Sources: -/// Peter J. Huber - "Robust Estimation of a Location Parameter" -/// https://projecteuclid.org/euclid.aoms/1177703732 -/// -[SkipLocalsInit] -public sealed class Huber : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - private readonly double _delta; - private readonly double _halfDelta; - - /// The number of points over which to calculate the loss. - /// The threshold between squared and linear loss (default 1.0). - /// Thrown when period is less than 1 or delta is not positive. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Huber(int period, double delta = 1.0) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(delta, 0); - - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - _delta = delta; - _halfDelta = delta * 0.5; - Name = $"Huberloss(period={period}, delta={delta})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the loss. - /// The threshold between squared and linear loss (default 1.0). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Huber(object source, int period, double delta = 1.0) : this(period, delta) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateHuberLoss(double error) - { - double absError = Math.Abs(error); - if (absError <= _delta) - { - // Squared error for small deviations - return 0.5 * error * error; - } - // Linear error for large deviations - return _delta * (absError - _halfDelta); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double huberloss = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumLoss = 0; - for (int i = 0; i < actualValues.Length; i++) - { - double error = actualValues[i] - predictedValues[i]; - sumLoss += CalculateHuberLoss(error); - } - - huberloss = sumLoss / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return huberloss; - } -} diff --git a/lib/errors/Mae.cs b/lib/errors/Mae.cs deleted file mode 100644 index 2399f74d..00000000 --- a/lib/errors/Mae.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MAE: Mean Absolute Error -/// A straightforward error metric that measures the average magnitude of errors -/// between predicted and actual values, without considering their direction. -/// MAE treats all individual differences equally in the average. -/// -/// -/// The MAE calculation process: -/// 1. Calculates absolute difference between each actual and predicted value -/// 2. Sums all absolute differences -/// 3. Divides by the number of observations -/// -/// Key characteristics: -/// - Linear scale (all differences weighted equally) -/// - Robust to outliers compared to MSE -/// - Easy to interpret (same units as data) -/// - Constant gradient for optimization -/// - Less sensitive to large errors than MSE -/// -/// Formula: -/// MAE = (1/n) * Σ|actual - predicted| -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mean_absolute_error -/// https://www.statisticshowto.com/absolute-error/ -/// -[SkipLocalsInit] -public sealed class Mae : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MAE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mae(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Mae(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MAE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mae(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double mae = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumAbsoluteError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumAbsoluteError += Math.Abs(actualValues[i] - predictedValues[i]); - } - - mae = sumAbsoluteError / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return mae; - } -} diff --git a/lib/errors/Mapd.cs b/lib/errors/Mapd.cs deleted file mode 100644 index a4b32b77..00000000 --- a/lib/errors/Mapd.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MAPD: Mean Absolute Percentage Deviation -/// A percentage-based error metric that measures the average absolute percentage -/// difference between predicted and actual values. MAPD expresses accuracy as a -/// percentage, making it scale-independent and easy to interpret. -/// -/// -/// The MAPD calculation process: -/// 1. Calculates absolute percentage difference for each point -/// 2. Sums all absolute percentage differences -/// 3. Divides by the number of observations -/// -/// Key characteristics: -/// - Scale-independent (percentage-based) -/// - Easy to interpret (0-100% range) -/// - Useful for comparing different scales -/// - Cannot handle zero actual values -/// - Asymmetric (treats over/under predictions differently) -/// -/// Formula: -/// MAPD = (1/n) * Σ|((actual - predicted) / actual)| -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mean_absolute_percentage_error -/// https://www.statisticshowto.com/mean-absolute-percentage-error-mape/ -/// -/// Note: Also known as MAPE (Mean Absolute Percentage Error) in some contexts -/// -[SkipLocalsInit] -public sealed class Mapd : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MAPD. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mapd(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Mapd(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MAPD. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mapd(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculatePercentageDeviation(double actual, double predicted) - { - return actual >= double.Epsilon ? Math.Abs((actual - predicted) / actual) : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double mapd = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumAbsolutePercentageDeviation = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumAbsolutePercentageDeviation += CalculatePercentageDeviation(actualValues[i], predictedValues[i]); - } - - mapd = sumAbsolutePercentageDeviation / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return mapd; - } -} diff --git a/lib/errors/Mape.cs b/lib/errors/Mape.cs deleted file mode 100644 index 40307397..00000000 --- a/lib/errors/Mape.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MAPE: Mean Absolute Percentage Error -/// A percentage-based error metric that measures the average absolute percentage -/// difference between predicted and actual values. MAPE expresses accuracy as a -/// percentage, making it scale-independent and easy to interpret. -/// -/// -/// The MAPE calculation process: -/// 1. Calculates absolute percentage error for each point -/// 2. Sums all absolute percentage errors -/// 3. Divides by the number of observations -/// -/// Key characteristics: -/// - Scale-independent (percentage-based) -/// - Easy to interpret (0-100% range) -/// - Useful for comparing different scales -/// - Cannot handle zero actual values -/// - Asymmetric (treats over/under predictions differently) -/// -/// Formula: -/// MAPE = (1/n) * Σ|((actual - predicted) / actual)| * 100% -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mean_absolute_percentage_error -/// https://www.statisticshowto.com/mean-absolute-percentage-error-mape/ -/// -/// Note: Also known as MAPD (Mean Absolute Percentage Deviation) in some contexts -/// -[SkipLocalsInit] -public sealed class Mape : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MAPE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mape(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Mape(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MAPE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mape(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculatePercentageError(double actual, double predicted) - { - return actual >= double.Epsilon ? Math.Abs((actual - predicted) / actual) : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double mape = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumAbsolutePercentageError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumAbsolutePercentageError += CalculatePercentageError(actualValues[i], predictedValues[i]); - } - - mape = sumAbsolutePercentageError / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return mape; - } -} diff --git a/lib/errors/Mase.cs b/lib/errors/Mase.cs deleted file mode 100644 index 096ecedf..00000000 --- a/lib/errors/Mase.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MASE: Mean Absolute Scaled Error -/// A scale-free error metric that compares the mean absolute error of the forecast -/// with the mean absolute error of the naive forecast. MASE is particularly useful -/// for comparing forecast accuracy across different datasets. -/// -/// -/// The MASE calculation process: -/// 1. Calculates mean absolute error of the forecast -/// 2. Calculates mean absolute error of naive forecast (using previous value) -/// 3. Divides forecast error by naive forecast error -/// -/// Key characteristics: -/// - Scale-free (independent of data scale) -/// - Handles zero values unlike percentage errors -/// - Symmetric (treats over/under predictions equally) -/// - Easy interpretation (MASE < 1 means better than naive forecast) -/// - Robust to outliers -/// -/// Formula: -/// MASE = MAE(forecast) / MAE(naive_forecast) -/// where naive_forecast[t] = actual[t-1] -/// -/// Sources: -/// Rob J. Hyndman - "Another Look at Forecast-Accuracy Metrics for Intermittent Demand" -/// https://robjhyndman.com/papers/another-look-at-measures-of-forecast-accuracy/ -/// -[SkipLocalsInit] -public sealed class Mase : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - private readonly CircularBuffer _naiveBuffer; - - /// The number of points over which to calculate the MASE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mase(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - _naiveBuffer = new CircularBuffer(period); - Name = $"Mase(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MASE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mase(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - _naiveBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - // Naive forecast uses previous actual value - if (_actualBuffer.Count > 1) - { - _naiveBuffer.Add(_actualBuffer.GetSpan()[^2], Input.IsNew); - } - - double mase = CalculateMase(); - - IsHot = _index >= WarmupPeriod; - return mase; - } - - /// - /// Calculates the MASE value by comparing forecast error to naive forecast error. - /// - /// The calculated MASE value, or positive infinity if naive error is zero. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateMase() - { - if (_actualBuffer.Count <= 1) return 0; - - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - ReadOnlySpan naiveValues = _naiveBuffer.GetSpan(); - - double sumAbsoluteError = CalculateSumAbsoluteError(actualValues, predictedValues); - double naiveForecastError = CalculateNaiveForecastError(actualValues, naiveValues); - - return naiveForecastError >= double.Epsilon ? (sumAbsoluteError / _actualBuffer.Count) / naiveForecastError : double.PositiveInfinity; - } - - /// - /// Calculates the sum of absolute errors between actual and predicted values. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSumAbsoluteError(ReadOnlySpan actualValues, ReadOnlySpan predictedValues) - { - double sum = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sum += Math.Abs(actualValues[i] - predictedValues[i]); - } - return sum; - } - - /// - /// Calculates the naive forecast error using the previous value as prediction. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateNaiveForecastError(ReadOnlySpan actualValues, ReadOnlySpan naiveValues) - { - double sum = 0; - for (int i = 1; i < actualValues.Length; i++) - { - sum += Math.Abs(actualValues[i] - naiveValues[i - 1]); - } - return sum / (actualValues.Length - 1); - } -} diff --git a/lib/errors/Mda.cs b/lib/errors/Mda.cs deleted file mode 100644 index 57586f94..00000000 --- a/lib/errors/Mda.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MDA: Mean Directional Accuracy -/// A metric that measures how well a forecast predicts the direction of change -/// rather than the magnitude. MDA focuses on whether the predicted movement -/// (up or down) matches the actual movement. -/// -/// -/// The MDA calculation process: -/// 1. For each consecutive pair of points: -/// - Calculate direction of actual change -/// - Calculate direction of predicted change -/// - Compare directions (match = 1, mismatch = 0) -/// 2. Average the directional matches -/// -/// Key characteristics: -/// - Scale-independent (only considers direction) -/// - Range is 0 to 1 (easy interpretation) -/// - Useful for trend prediction evaluation -/// - Ignores magnitude of changes -/// - Equal weight to all directional changes -/// -/// Formula: -/// MDA = (1/(n-1)) * Σ(sign(actual[t] - actual[t-1]) == sign(pred[t] - pred[t-1])) -/// -/// Sources: -/// https://www.sciencedirect.com/science/article/abs/pii/S0169207016000121 -/// "Evaluating Forecasting Performance" - International Journal of Forecasting -/// -[SkipLocalsInit] -public sealed class Mda : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MDA. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mda(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Mda(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MDA. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mda(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static int CompareDirections(double current, double previous) - { - return Math.Sign(current - previous); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double mda = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumDirectionalAccuracy = 0; - for (int i = 1; i < actualValues.Length; i++) - { - int actualDirection = CompareDirections(actualValues[i], actualValues[i - 1]); - int predictedDirection = CompareDirections(predictedValues[i], predictedValues[i - 1]); - sumDirectionalAccuracy += (actualDirection == predictedDirection) ? 1 : 0; - } - - mda = sumDirectionalAccuracy / (actualValues.Length - 1); - } - - IsHot = _index >= WarmupPeriod; - return mda; - } -} diff --git a/lib/errors/Me.cs b/lib/errors/Me.cs deleted file mode 100644 index e4ce1dcb..00000000 --- a/lib/errors/Me.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ME: Mean Error -/// A basic error metric that measures the average difference between actual and -/// predicted values. Unlike MAE, it allows positive and negative errors to cancel -/// out, making it useful for detecting systematic bias in predictions. -/// -/// -/// The ME calculation process: -/// 1. Calculates error (actual - predicted) for each point -/// 2. Sums all errors (allowing cancellation) -/// 3. Divides by the number of observations -/// -/// Key characteristics: -/// - Same units as input data -/// - Can detect systematic bias -/// - Positive ME indicates underprediction -/// - Negative ME indicates overprediction -/// - Errors can cancel out -/// -/// Formula: -/// ME = (1/n) * Σ(actual - predicted) -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mean_signed_difference -/// https://www.statisticshowto.com/mean-error/ -/// -/// Note: Also known as Mean Bias Error (MBE) or Mean Signed Difference (MSD) -/// -[SkipLocalsInit] -public sealed class Me : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the ME. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Me(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Me(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the ME. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Me(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateError(double actual, double predicted) - { - return actual - predicted; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double me = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumError += CalculateError(actualValues[i], predictedValues[i]); - } - - me = sumError / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return me; - } -} diff --git a/lib/errors/Mpe.cs b/lib/errors/Mpe.cs deleted file mode 100644 index d9d21719..00000000 --- a/lib/errors/Mpe.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MPE: Mean Percentage Error -/// A percentage-based error metric that measures the average percentage difference -/// between actual and predicted values. Like ME, it allows positive and negative -/// errors to cancel out, but expresses the bias in percentage terms. -/// -/// -/// The MPE calculation process: -/// 1. Calculates percentage error for each point -/// 2. Sums all percentage errors (allowing cancellation) -/// 3. Divides by the number of observations -/// -/// Key characteristics: -/// - Scale-independent (percentage-based) -/// - Can detect systematic bias -/// - Positive MPE indicates underprediction -/// - Negative MPE indicates overprediction -/// - Cannot handle zero actual values -/// - Errors can cancel out -/// -/// Formula: -/// MPE = (1/n) * Σ((actual - predicted) / actual) * 100% -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mean_percentage_error -/// https://www.statisticshowto.com/mean-percentage-error/ -/// -/// Note: Similar to MAPE but allows error cancellation -/// -[SkipLocalsInit] -public sealed class Mpe : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MPE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mpe(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Mpe(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MPE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mpe(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculatePercentageError(double actual, double predicted) - { - return actual >= double.Epsilon ? (actual - predicted) / actual : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double mpe = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumPercentageError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumPercentageError += CalculatePercentageError(actualValues[i], predictedValues[i]); - } - - mpe = sumPercentageError / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return mpe; - } -} diff --git a/lib/errors/Mse.cs b/lib/errors/Mse.cs deleted file mode 100644 index 1f7d0369..00000000 --- a/lib/errors/Mse.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MSE: Mean Squared Error -/// A fundamental error metric that measures the average of squared differences -/// between predicted and actual values. MSE heavily penalizes large errors due -/// to the squaring operation. -/// -/// -/// The MSE calculation process: -/// 1. Calculates error (actual - predicted) for each point -/// 2. Squares each error value -/// 3. Averages the squared errors -/// -/// Key characteristics: -/// - Heavily penalizes large errors -/// - Always non-negative -/// - Units are squared (harder to interpret) -/// - More sensitive to outliers than MAE -/// - Differentiable (useful for optimization) -/// -/// Formula: -/// MSE = (1/n) * Σ(actual - predicted)² -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mean_squared_error -/// https://www.statisticshowto.com/probability-and-statistics/statistics-definitions/mean-squared-error/ -/// -/// Note: Often used in optimization due to its mathematical properties -/// -[SkipLocalsInit] -public sealed class Mse : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MSE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mse(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Mse(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MSE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mse(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSquaredError(double actual, double predicted) - { - double error = actual - predicted; - return error * error; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double mse = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumSquaredError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumSquaredError += CalculateSquaredError(actualValues[i], predictedValues[i]); - } - - mse = sumSquaredError / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return mse; - } -} diff --git a/lib/errors/Msle.cs b/lib/errors/Msle.cs deleted file mode 100644 index 2a794fc9..00000000 --- a/lib/errors/Msle.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MSLE: Mean Squared Logarithmic Error -/// A variation of MSE that operates on log-transformed values. MSLE is particularly -/// useful for data with exponential growth or when errors in larger values should -/// not be penalized more heavily than errors in smaller values. -/// -/// -/// The MSLE calculation process: -/// 1. Adds 1 to both actual and predicted values (to handle zeros) -/// 2. Takes natural log of both values -/// 3. Calculates squared difference of logs -/// 4. Averages the squared differences -/// -/// Key characteristics: -/// - Scale-independent due to log transformation -/// - Penalizes underestimates more than overestimates -/// - Handles exponential trends well -/// - More sensitive to relative differences -/// - Can handle zero values (adds 1 before log) -/// -/// Formula: -/// MSLE = (1/n) * Σ(log(actual + 1) - log(predicted + 1))² -/// -/// Sources: -/// https://scikit-learn.org/stable/modules/model_evaluation.html#mean-squared-logarithmic-error -/// https://medium.com/analytics-vidhya/root-mean-square-log-error-rmse-vs-rmlse-935c6cc1802a -/// -/// Note: Often used in cases where target values follow exponential growth -/// -[SkipLocalsInit] -public sealed class Msle : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the MSLE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Msle(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Msle(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the MSLE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Msle(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSquaredLogError(double actual, double predicted) - { - double logActual = Math.Log(actual + 1); - double logPredicted = Math.Log(predicted + 1); - double error = logActual - logPredicted; - return error * error; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double msle = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumSquaredLogError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumSquaredLogError += CalculateSquaredLogError(actualValues[i], predictedValues[i]); - } - - msle = sumSquaredLogError / actualValues.Length; - } - - IsHot = _index >= WarmupPeriod; - return msle; - } -} diff --git a/lib/errors/Rae.cs b/lib/errors/Rae.cs deleted file mode 100644 index cdee3f54..00000000 --- a/lib/errors/Rae.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RAE: Relative Absolute Error -/// A normalized error metric that compares the total absolute error to the total -/// magnitude of actual values. RAE provides a scale-independent measure of error -/// that is robust to the overall magnitude of the data. -/// -/// -/// The RAE calculation process: -/// 1. Calculates sum of absolute errors -/// 2. Calculates sum of absolute actual values -/// 3. Divides total error by total actual magnitude -/// -/// Key characteristics: -/// - Scale-independent (normalized by actual values) -/// - Range typically between 0 and 1 -/// - Easy to interpret (0 is perfect, 1 means error equals data magnitude) -/// - Robust to data scale changes -/// - Less sensitive to outliers than squared errors -/// -/// Formula: -/// RAE = Σ|actual - predicted| / Σ|actual| -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Relative_absolute_error -/// https://www.sciencedirect.com/topics/engineering/relative-absolute-error -/// -/// Note: Values greater than 1 indicate predictions worse than using zero -/// -[SkipLocalsInit] -public sealed class Rae : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the RAE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rae(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Rae(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the RAE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rae(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double error, double magnitude) CalculateErrorAndMagnitude(double actual, double predicted) - { - return (Math.Abs(actual - predicted), Math.Abs(actual)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double rae = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumAbsoluteError = 0; - double sumAbsoluteActual = 0; - for (int i = 0; i < actualValues.Length; i++) - { - var (error, magnitude) = CalculateErrorAndMagnitude(actualValues[i], predictedValues[i]); - sumAbsoluteError += error; - sumAbsoluteActual += magnitude; - } - - rae = sumAbsoluteActual > 0 ? sumAbsoluteError / sumAbsoluteActual : 0; - } - - IsHot = _index >= WarmupPeriod; - return rae; - } -} diff --git a/lib/errors/Rmse.cs b/lib/errors/Rmse.cs deleted file mode 100644 index 09067a36..00000000 --- a/lib/errors/Rmse.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RMSE: Root Mean Square Error -/// A widely used error metric that measures the square root of the average squared -/// differences between predicted and actual values. RMSE provides error measurements -/// in the same units as the original data. -/// -/// -/// The RMSE calculation process: -/// 1. Calculates error (actual - predicted) for each point -/// 2. Squares each error value -/// 3. Averages the squared errors -/// 4. Takes the square root of the average -/// -/// Key characteristics: -/// - Same units as input data (unlike MSE) -/// - Penalizes large errors more than small ones -/// - Always non-negative -/// - More interpretable than MSE -/// - Commonly used in regression problems -/// -/// Formula: -/// RMSE = √((1/n) * Σ(actual - predicted)²) -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Root-mean-square_deviation -/// https://www.statisticshowto.com/probability-and-statistics/regression-analysis/rmse-root-mean-square-error/ -/// -/// Note: Square root of MSE, making it more interpretable in original units -/// -[SkipLocalsInit] -public sealed class Rmse : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the RMSE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rmse(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Rmse(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the RMSE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rmse(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSquaredError(double actual, double predicted) - { - double error = actual - predicted; - return error * error; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double rmse = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumSquaredError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumSquaredError += CalculateSquaredError(actualValues[i], predictedValues[i]); - } - - rmse = Math.Sqrt(sumSquaredError / actualValues.Length); - } - - IsHot = _index >= WarmupPeriod; - return rmse; - } -} diff --git a/lib/errors/Rmsle.cs b/lib/errors/Rmsle.cs deleted file mode 100644 index 83e6e1d2..00000000 --- a/lib/errors/Rmsle.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RMSLE: Root Mean Square Logarithmic Error -/// A variation of RMSE that operates on log-transformed values. RMSLE is particularly -/// useful for data with exponential growth or when relative errors in larger values -/// should be treated similarly to relative errors in smaller values. -/// -/// -/// The RMSLE calculation process: -/// 1. Adds 1 to both actual and predicted values (to handle zeros) -/// 2. Takes natural log of both values -/// 3. Calculates squared difference of logs -/// 4. Averages the squared differences -/// 5. Takes the square root -/// -/// Key characteristics: -/// - Scale-independent due to log transformation -/// - Penalizes underestimates more than overestimates -/// - Handles exponential trends well -/// - More sensitive to relative differences -/// - Can handle zero values (adds 1 before log) -/// -/// Formula: -/// RMSLE = √((1/n) * Σ(log(actual + 1) - log(predicted + 1))²) -/// -/// Sources: -/// https://www.kaggle.com/wiki/RootMeanSquaredLogarithmicError -/// https://medium.com/analytics-vidhya/root-mean-square-log-error-rmse-vs-rmlse-935c6cc1802a -/// -/// Note: Square root of MSLE, useful for data with exponential growth -/// -[SkipLocalsInit] -public sealed class Rmsle : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the RMSLE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rmsle(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Rmsle(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the RMSLE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rmsle(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSquaredLogError(double actual, double predicted) - { - double logActual = Math.Log(actual + 1); - double logPredicted = Math.Log(predicted + 1); - double error = logActual - logPredicted; - return error * error; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double rmsle = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumSquaredLogError = 0; - for (int i = 0; i < actualValues.Length; i++) - { - sumSquaredLogError += CalculateSquaredLogError(actualValues[i], predictedValues[i]); - } - - rmsle = Math.Sqrt(sumSquaredLogError / actualValues.Length); - } - - IsHot = _index >= WarmupPeriod; - return rmsle; - } -} diff --git a/lib/errors/Rse.cs b/lib/errors/Rse.cs deleted file mode 100644 index 2c3d1ffd..00000000 --- a/lib/errors/Rse.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RSE: Relative Squared Error -/// A normalized error metric that compares the squared error of predictions to -/// the variance of actual values. RSE provides a scale-independent measure of -/// prediction accuracy relative to the inherent variability in the data. -/// -/// -/// The RSE calculation process: -/// 1. Calculates sum of squared prediction errors -/// 2. Calculates sum of squared deviations from mean (variance) -/// 3. Divides squared error by variance and takes square root -/// -/// Key characteristics: -/// - Scale-independent (normalized by data variance) -/// - Range typically between 0 and 1 -/// - Easy interpretation relative to data variance -/// - Penalizes large errors more than small ones -/// - Accounts for data variability -/// -/// Formula: -/// RSE = √(Σ(actual - predicted)² / Σ(actual - mean(actual))²) -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Relative_squared_error -/// https://www.sciencedirect.com/topics/engineering/relative-squared-error -/// -/// Note: Values less than 1 indicate predictions better than using mean -/// -[SkipLocalsInit] -public sealed class Rse : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the RSE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rse(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Rse(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the RSE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rse(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double squaredError, double squaredDeviation) CalculateErrors(double actual, double predicted, double meanActual) - { - double error = actual - predicted; - double deviation = actual - meanActual; - return (error * error, deviation * deviation); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double rse = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumSquaredError = 0; - double sumSquaredActual = 0; - double meanActual = _actualBuffer.Average(); - - for (int i = 0; i < actualValues.Length; i++) - { - var (squaredError, squaredDeviation) = CalculateErrors(actualValues[i], predictedValues[i], meanActual); - sumSquaredError += squaredError; - sumSquaredActual += squaredDeviation; - } - - rse = sumSquaredActual > 0 ? Math.Sqrt(sumSquaredError / sumSquaredActual) : 0; - } - - IsHot = _index >= WarmupPeriod; - return rse; - } -} diff --git a/lib/errors/Rsquared.cs b/lib/errors/Rsquared.cs deleted file mode 100644 index 5712c38c..00000000 --- a/lib/errors/Rsquared.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// R-squared: Coefficient of Determination -/// A statistical measure that represents the proportion of variance in the dependent -/// variable that is predictable from the independent variable. R-squared provides -/// a measure of how well the predictions approximate the actual data. -/// -/// -/// The R-squared calculation process: -/// 1. Calculates total sum of squares (variance from mean) -/// 2. Calculates residual sum of squares (prediction errors) -/// 3. Computes 1 - (residual SS / total SS) -/// -/// Key characteristics: -/// - Range is typically 0 to 1 -/// - 1 indicates perfect prediction -/// - 0 indicates prediction no better than mean -/// - Scale-independent -/// - Widely used in regression analysis -/// -/// Formula: -/// R² = 1 - (Σ(actual - predicted)² / Σ(actual - mean(actual))²) -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Coefficient_of_determination -/// https://www.statisticshowto.com/probability-and-statistics/coefficient-of-determination-r-squared/ -/// -/// Note: Can be negative if predictions are worse than using the mean -/// -[SkipLocalsInit] -public sealed class Rsquared : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - - /// The number of points over which to calculate the R-squared value. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsquared(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Rsquared(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the R-squared value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsquared(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double squaredResidual, double squaredTotal) CalculateSquaredErrors(double actual, double predicted, double meanActual) - { - double deviation = actual - meanActual; - double error = actual - predicted; - return (error * error, deviation * deviation); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double rsquared = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double meanActual = _actualBuffer.Average(); - double sumSquaredTotal = 0; - double sumSquaredResidual = 0; - - for (int i = 0; i < actualValues.Length; i++) - { - var (squaredResidual, squaredTotal) = CalculateSquaredErrors(actualValues[i], predictedValues[i], meanActual); - sumSquaredResidual += squaredResidual; - sumSquaredTotal += squaredTotal; - } - - rsquared = sumSquaredTotal >= double.Epsilon ? 1 - (sumSquaredResidual / sumSquaredTotal) : 0; - } - - IsHot = _index >= WarmupPeriod; - return rsquared; - } -} diff --git a/lib/errors/Smape.cs b/lib/errors/Smape.cs deleted file mode 100644 index cb523938..00000000 --- a/lib/errors/Smape.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SMAPE: Symmetric Mean Absolute Percentage Error -/// A variation of MAPE that treats positive and negative errors symmetrically. -/// SMAPE uses the average of actual and predicted values in the denominator, -/// making it more robust than MAPE for values close to zero. -/// -/// -/// The SMAPE calculation process: -/// 1. Calculates absolute difference between actual and predicted -/// 2. Divides by sum of absolute actual and predicted values -/// 3. Averages these ratios and multiplies by 200% -/// -/// Key characteristics: -/// - Symmetric treatment of errors -/// - Range is 0% to 200% -/// - More robust than MAPE near zero -/// - Scale-independent -/// - Handles both positive and negative values -/// -/// Formula: -/// SMAPE = (200/n) * Σ|actual - predicted| / (|actual| + |predicted|) -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error -/// https://www.sciencedirect.com/science/article/abs/pii/0169207085900059 -/// -/// Note: More stable than MAPE when actual values are close to zero -/// -[SkipLocalsInit] -public sealed class Smape : AbstractBase -{ - private readonly CircularBuffer _actualBuffer; - private readonly CircularBuffer _predictedBuffer; - private const double Epsilon = 1e-10; - - /// The number of points over which to calculate the SMAPE. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Smape(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - WarmupPeriod = period; - _actualBuffer = new CircularBuffer(period); - _predictedBuffer = new CircularBuffer(period); - Name = $"Smape(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points over which to calculate the SMAPE. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Smape(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actualBuffer.Clear(); - _predictedBuffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSymmetricError(double actual, double predicted) - { - double denominator = Math.Abs(actual) + Math.Abs(predicted); - return denominator > Epsilon ? Math.Abs(actual - predicted) / denominator : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double actual = Input.Value; - _actualBuffer.Add(actual, Input.IsNew); - - // If no predicted value provided, use mean of actual values - double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value; - _predictedBuffer.Add(predicted, Input.IsNew); - - double smape = 0; - if (_actualBuffer.Count > 0) - { - ReadOnlySpan actualValues = _actualBuffer.GetSpan(); - ReadOnlySpan predictedValues = _predictedBuffer.GetSpan(); - - double sumSymmetricAbsolutePercentageError = 0; - int validCount = 0; - - for (int i = 0; i < actualValues.Length; i++) - { - double error = CalculateSymmetricError(actualValues[i], predictedValues[i]); - if (error > 0) - { - sumSymmetricAbsolutePercentageError += error; - validCount++; - } - } - - smape = validCount > 0 ? (200 * sumSymmetricAbsolutePercentageError / validCount) : 0; - } - - IsHot = _index >= WarmupPeriod; - return smape; - } -} diff --git a/lib/errors/_list.md b/lib/errors/_list.md deleted file mode 100644 index 03ecde4b..00000000 --- a/lib/errors/_list.md +++ /dev/null @@ -1,16 +0,0 @@ -✔️ HUBER - Huber Loss -✔️ MAE - Mean Absolute Error -✔️ MAPD - Mean Absolute Percentage Deviation -✔️ MAPE - Mean Absolute Percentage Error -✔️ MASE - Mean Absolute Scaled Error -✔️ MDA - Mean Directional Accuracy -✔️ ME - Mean Error -✔️ MPE - Mean Percentage Error -✔️ MSE - Mean Squared Error -✔️ MSLE - Mean Squared Logarithmic Error -✔️ RAE - Relative Absolute Error -✔️ RMSE - Root Mean Squared Error -✔️ RMSLE - Root Mean Squared Logarithmic Error -✔️ RSE - Relative Squared Error -✔️ RSQUARED - R-Squared (Coefficient of Determination) -✔️ SMAPE - Symmetric Mean Absolute Percentage Error diff --git a/lib/feeds/CsvFeed.cs b/lib/feeds/CsvFeed.cs new file mode 100644 index 00000000..0c6a93f0 --- /dev/null +++ b/lib/feeds/CsvFeed.cs @@ -0,0 +1,196 @@ +using System.Globalization; +using System.Runtime.CompilerServices; + +namespace QuanTAlib; + +/// +/// CSV file feed for loading historical OHLCV data. +/// Loads data in constructor and streams through it with Next() or returns batches with Fetch(). +/// CSV format: timestamp,open,high,low,close,volume (header required) +/// Timestamp format: YYYY-MM-DD (UTC midnight assumed) +/// +public class CsvFeed : IFeed +{ + private readonly TBarSeries _data; + + // Streaming state + private int _currentIndex; + private TBar _currentBar; + private bool _hasCurrentBar; + + /// + /// Loads CSV file and prepares data for streaming. + /// Data is reversed to chronological order (oldest first). + /// + /// Path to CSV file + public CsvFeed(string filePath) + { + if (string.IsNullOrWhiteSpace(filePath)) + throw new ArgumentException("File path cannot be null or empty", nameof(filePath)); + + if (!File.Exists(filePath)) + throw new FileNotFoundException($"CSV file not found: {filePath}", filePath); + + _data = LoadFromCsv(filePath); + _currentIndex = 0; + } + + /// + /// Parses CSV file into TBarSeries. + /// Expected format: timestamp,open,high,low,close,volume + /// + private static TBarSeries LoadFromCsv(string filePath) + { + var lines = File.ReadAllLines(filePath); + + if (lines.Length == 0) + throw new InvalidDataException("CSV file is empty"); + + // Skip header, reverse to chronological order (oldest first) + var dataLines = lines.Skip(1).Reverse().ToArray(); + + if (dataLines.Length == 0) + throw new InvalidDataException("CSV file contains only header, no data"); + + var series = new TBarSeries(dataLines.Length); + + for (int i = 0; i < dataLines.Length; i++) + { + var line = dataLines[i]; + if (string.IsNullOrWhiteSpace(line)) + continue; + + var parts = line.Split(','); + if (parts.Length != 6) + throw new FormatException($"Invalid CSV format at line {i + 2}. Expected 6 columns, found {parts.Length}"); + + try + { + // Parse timestamp (YYYY-MM-DD format, assume UTC midnight) + var timestamp = DateTime.ParseExact(parts[0].Trim(), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); + + // Parse OHLCV values + double open = double.Parse(parts[1].Trim(), CultureInfo.InvariantCulture); + double high = double.Parse(parts[2].Trim(), CultureInfo.InvariantCulture); + double low = double.Parse(parts[3].Trim(), CultureInfo.InvariantCulture); + double close = double.Parse(parts[4].Trim(), CultureInfo.InvariantCulture); + double volume = double.Parse(parts[5].Trim(), CultureInfo.InvariantCulture); + + series.Add(timestamp, open, high, low, close, volume, isNew: true); + } + catch (Exception ex) when (ex is FormatException or OverflowException) + { + throw new FormatException($"Failed to parse CSV line {i + 2}: {line}", ex); + } + } + + return series; + } + + /// + /// Gets the next bar with full bidirectional control. + /// When end of data reached, returns last bar and sets isNew=false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TBar Next(ref bool isNew) + { + if (_data.Count == 0) + { + isNew = false; + return default; + } + + if (isNew || !_hasCurrentBar) + { + // Request for new bar + if (_currentIndex >= _data.Count) + { + // End of data - return last bar and signal no more data + isNew = false; + return _currentBar; + } + + _currentBar = _data[_currentIndex]; + _currentIndex++; + _hasCurrentBar = true; + } + else + { + // Update current bar - CSV has no intra-bar updates, return same bar + // No change to _currentBar or _currentIndex + } + + return _currentBar; + } + + /// + /// Gets the next bar with simple control. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TBar Next(bool isNew = true) + { + return Next(ref isNew); + } + + /// + /// Returns a filtered subset of data matching the criteria. + /// Resets streaming position to start of returned data. + /// + public TBarSeries Fetch(int count, long startTime, TimeSpan interval) + { + if (count <= 0) + throw new ArgumentException("Count must be positive", nameof(count)); + + var result = new TBarSeries(count); + + // Find starting index + int startIndex = 0; + for (int i = 0; i < _data.Count; i++) + { + if (_data[i].Time >= startTime) + { + startIndex = i; + break; + } + } + + // Collect bars matching interval + long expectedTime = startTime; + int collected = 0; + + for (int i = startIndex; i < _data.Count && collected < count; i++) + { + var bar = _data[i]; + + // Check if bar time matches expected time (within tolerance) + long timeDiff = Math.Abs(bar.Time - expectedTime); + long tolerance = interval.Ticks / 2; // Allow 50% tolerance + + if (timeDiff <= tolerance) + { + result.Add(bar, isNew: true); + collected++; + expectedTime += interval.Ticks; + } + else if (bar.Time > expectedTime) + { + // Gap in data - skip forward + long gaps = (bar.Time - expectedTime) / interval.Ticks; + expectedTime += (gaps + 1) * interval.Ticks; + + if (Math.Abs(bar.Time - expectedTime + interval.Ticks) <= tolerance) + { + result.Add(bar, isNew: true); + collected++; + expectedTime += interval.Ticks; + } + } + } + + // Reset streaming to start of returned data + _currentIndex = startIndex; + _hasCurrentBar = false; + + return result; + } +} diff --git a/lib/feeds/GbmFeed.cs b/lib/feeds/GbmFeed.cs deleted file mode 100644 index fcaa2ae8..00000000 --- a/lib/feeds/GbmFeed.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Security.Cryptography; - -namespace QuanTAlib; - -public class GbmFeed : TBarSeries -{ - private readonly double _mu, _sigma; - private readonly RandomNumberGenerator _rng; - private double _lastClose; - - public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2) - { - _lastClose = initialPrice; - _mu = mu; - _sigma = sigma; - _rng = RandomNumberGenerator.Create(); - this.Name = $"GBM({_sigma:F2})"; - } - - public void Add(bool isNew = true) => Add(time: DateTime.Now, isNew: isNew); - public void Add(DateTime time, bool isNew = true) => base.Add(Generate(time, isNew)); - public void Add(int count) - { - DateTime startTime = DateTime.UtcNow - TimeSpan.FromHours(count); - for (int i = 0; i < count; i++) - { - Add(startTime, isNew: true); - startTime = startTime.AddHours(1); - } - } - - public TBar Generate(DateTime time, bool isNew = true) - { - double dt = 1.0 / 252; - double drift = (_mu - (0.5 * _sigma * _sigma)) * dt; - double diffusion = _sigma * Math.Sqrt(dt) * GenerateNormalRandom(); - - double open = _lastClose; - double close = open * Math.Exp(drift + diffusion); - - // Generate intra-bar price movements - double maxMove = Math.Abs(close - open) * 1.5; // Allow for some extra movement within the bar - double high = Math.Max(open, close) + (maxMove * GenerateRandomDouble()); - double low = Math.Min(open, close) - (maxMove * GenerateRandomDouble()); - - // Ensure high is always greater than or equal to both open and close - high = Math.Max(high, Math.Max(open, close)); - - // Ensure low is always less than or equal to both open and close - low = Math.Min(low, Math.Min(open, close)); - - double volume = 1000 + (GenerateRandomDouble() * 1000); - - if (isNew) - { - _lastClose = close; - } - - return new TBar(time, open, high, low, close, volume, isNew); - } - - private double GenerateNormalRandom() - { - // Box-Muller transform to generate standard normal random variable - double u1 = 1.0 - GenerateRandomDouble(); // Uniform(0,1] random doubles - double u2 = 1.0 - GenerateRandomDouble(); - return Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); - } - - private double GenerateRandomDouble() - { - byte[] bytes = new byte[8]; - _rng.GetBytes(bytes); - return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue; - } -} diff --git a/lib/feeds/IFeed.cs b/lib/feeds/IFeed.cs new file mode 100644 index 00000000..d3b7ba54 --- /dev/null +++ b/lib/feeds/IFeed.cs @@ -0,0 +1,35 @@ +namespace QuanTAlib; + +/// +/// Interface for data feeds that provide TBar (OHLCV) data. +/// Implementations include synthetic generators (GBM), API-based feeds (AlphaVantage), +/// file readers (CSV), and real-time streams (WebSocket). +/// +public interface IFeed +{ + /// + /// Gets the next bar from the feed with full bidirectional control. + /// + /// + /// Input: Request for new bar (true) or update current bar (false). + /// Output: Actual behavior - may differ if feed cannot honor request (e.g., end of data). + /// + /// The bar (new or updated) + TBar Next(ref bool isNew); + + /// + /// Gets the next bar from the feed with simple control. + /// + /// Request for new bar (true) or update current bar (false). Defaults to true. + /// The bar (new or updated) + TBar Next(bool isNew = true); + + /// + /// Gets multiple bars in batch with explicit time parameters. + /// + /// Number of bars to retrieve + /// Starting timestamp for first bar (in ticks) + /// Time interval between bars + /// Series containing the requested bars + TBarSeries Fetch(int count, long startTime, TimeSpan interval); +} diff --git a/lib/feeds/gbm.cs b/lib/feeds/gbm.cs new file mode 100644 index 00000000..1912fa07 --- /dev/null +++ b/lib/feeds/gbm.cs @@ -0,0 +1,211 @@ +using System; +using System.Runtime.CompilerServices; + +namespace QuanTAlib; + +/// +/// Geometric Brownian Motion (GBM) generator for simulating OHLCV data. +/// Generates realistic price data for testing indicators and strategies. +/// Stateless design - only maintains minimal state needed for price continuity. +/// +public class GBM : IFeed +{ + private readonly Random _rnd = new(); + + private double _lastPrice; + private long _lastTime; + + private readonly double _mu; + private readonly double _sigma; + private readonly double _dt; + + // Precomputed GBM constants + private readonly double _drift; + private readonly double _vol; + private readonly long _defaultTimeStep; + + // State for streaming bar formation (only when isNew=false) + private TBar _currentBar; + private bool _hasCurrentBar; + + // Box-Muller optimization: cache second normal + private double _cachedZ; + private bool _hasCachedZ; + + /// + /// Creates a new GBM generator. + /// + /// Initial price (default: 100.0) + /// Annual drift/return rate (default: 0.05 = 5%) + /// Annual volatility (default: 0.2 = 20%) + /// Default timeframe for bars (default: 1 minute) + public GBM( + double startPrice = 100.0, + double mu = 0.05, + double sigma = 0.2, + TimeSpan? defaultTimeframe = null) + { + _lastPrice = startPrice; + _lastTime = DateTime.UtcNow.Ticks; + + _mu = mu; + _sigma = sigma; + + // Use provided timeframe or default to 1 minute + var timeframe = defaultTimeframe ?? TimeSpan.FromMinutes(1); + _defaultTimeStep = timeframe.Ticks; + + // Calculate dt based on timeframe (assuming 252 trading days/year, 6.5 hours/day) + double minutesPerYear = 252.0 * 6.5 * 60.0; + _dt = timeframe.TotalMinutes / minutesPerYear; + + _drift = (mu - 0.5 * sigma * sigma) * _dt; + _vol = sigma * Math.Sqrt(_dt); + } + + /// + /// Generates next standard normal using Box-Muller transform with caching. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private double NextNormal() + { + if (_hasCachedZ) + { + _hasCachedZ = false; + return _cachedZ; + } + + double u1 = 1.0 - _rnd.NextDouble(); + double u2 = 1.0 - _rnd.NextDouble(); + double mag = Math.Sqrt(-2.0 * Math.Log(u1)); + double angle = 2.0 * Math.PI * u2; + + _cachedZ = mag * Math.Sin(angle); + _hasCachedZ = true; + + return mag * Math.Cos(angle); + } + + /// + /// Gets the next bar with full bidirectional control. + /// GBM always honors the request - isNew parameter unchanged on return. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TBar Next(ref bool isNew) + { + // GBM always honors request - parameter unchanged + + if (isNew || !_hasCurrentBar) + { + // Generate new bar + long currentTime = _lastTime + _defaultTimeStep; + + double z = NextNormal(); + double price = _lastPrice * Math.Exp(_drift + _vol * z); + double volume = 1000 + _rnd.NextDouble() * 1000; + + double open = _lastPrice; + double close = price; + double high = Math.Max(open, close) * (1.0 + _rnd.NextDouble() * 0.01); + double low = Math.Min(open, close) * (1.0 - _rnd.NextDouble() * 0.01); + + _currentBar = new TBar(currentTime, open, high, low, close, volume); + _hasCurrentBar = true; + + _lastPrice = close; + _lastTime = currentTime; + } + else + { + // Update current bar (intra-bar tick) + double z = NextNormal(); + double price = _lastPrice * Math.Exp(_drift + _vol * z); + double volume = 1000 + _rnd.NextDouble() * 1000; + + var bar = _currentBar; + double newClose = price; + double newHigh = Math.Max(bar.High, newClose); + double newLow = Math.Min(bar.Low, newClose); + + _currentBar = new TBar(bar.Time, bar.Open, newHigh, newLow, newClose, volume); + _lastPrice = newClose; + } + + return _currentBar; + } + + /// + /// Gets the next bar with simple control. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TBar Next(bool isNew = true) + { + // Delegate to ref version + return Next(ref isNew); + } + + /// + /// Generates a batch of bars using optimized batch processing with explicit time parameters. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TBarSeries Fetch(int count, long startTime, TimeSpan interval) + { + if (count <= 0) + throw new ArgumentException("Count must be positive", nameof(count)); + + var series = new TBarSeries(count); + + // Pre-allocate arrays for SoA layout + long[] t = new long[count]; + double[] o = new double[count]; + double[] h = new double[count]; + double[] l = new double[count]; + double[] c = new double[count]; + double[] v = new double[count]; + + // Calculate dt for this specific interval + double minutesPerYear = 252.0 * 6.5 * 60.0; + double dt = interval.TotalMinutes / minutesPerYear; + double drift = (_mu - 0.5 * _sigma * _sigma) * dt; + double vol = _sigma * Math.Sqrt(dt); + + long timeStep = interval.Ticks; + double currentPrice = _lastPrice; + long currentTime = startTime; + + for (int i = 0; i < count; i++) + { + double z = NextNormal(); + double price = currentPrice * Math.Exp(drift + vol * z); + + double open = currentPrice; + double close = price; + + double rnd1 = _rnd.NextDouble(); + double rnd2 = _rnd.NextDouble(); + double rnd3 = _rnd.NextDouble(); + + t[i] = currentTime; + o[i] = open; + c[i] = close; + h[i] = Math.Max(open, close) * (1.0 + rnd1 * 0.01); + l[i] = Math.Min(open, close) * (1.0 - rnd2 * 0.01); + v[i] = 1000 + rnd3 * 1000; + + currentPrice = price; + currentTime += timeStep; + } + + // Update internal state to continue from end of batch + _lastPrice = currentPrice; + _lastTime = currentTime - timeStep; // Last bar time, not next bar time + + // Bulk add to series + series.Add(t, o, h, l, c, v); + + // Reset streaming state after batch + _hasCurrentBar = false; + + return series; + } +} diff --git a/lib/momentum/Adx.cs b/lib/momentum/Adx.cs deleted file mode 100644 index 8cab3ce6..00000000 --- a/lib/momentum/Adx.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ADX: Average Directional Movement Index -/// A technical analysis indicator used to measure the strength of a trend, -/// regardless of its direction. ADX combines the Positive and Negative -/// Directional Movement Indicators to determine trend strength. -/// -/// -/// The ADX calculation process: -/// 1. Calculate True Range (TR) -/// 2. Calculate +DM (Positive Directional Movement) -/// 3. Calculate -DM (Negative Directional Movement) -/// 4. Smooth TR, +DM, and -DM using Wilder's smoothing -/// 5. Calculate +DI and -DI -/// 6. Calculate DX (Directional Index) -/// 7. Smooth DX to get ADX -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Values above 25 indicate strong trend -/// - Values below 20 indicate weak or no trend -/// - Can be used with +DI and -DI for trade signals -/// - Does not indicate trend direction, only strength -/// -/// Formula: -/// TR = max(high-low, abs(high-prevClose), abs(low-prevClose)) -/// +DM = if(high-prevHigh > prevLow-low) then max(high-prevHigh, 0) else 0 -/// -DM = if(prevLow-low > high-prevHigh) then max(prevLow-low, 0) else 0 -/// +DI = 100 * smoothed(+DM) / smoothed(TR) -/// -DI = 100 * smoothed(-DM) / smoothed(TR) -/// DX = 100 * abs(+DI - -DI) / (+DI + -DI) -/// ADX = smoothed(DX) -/// -/// Sources: -/// J. Welles Wilder Jr. - "New Concepts in Technical Trading Systems" (1978) -/// https://www.investopedia.com/terms/a/adx.asp -/// -/// Note: Default period of 14 was recommended by Wilder -/// -[SkipLocalsInit] -public sealed class Adx : AbstractBarBase -{ - private readonly Rma _smoothedTr; - private readonly Rma _smoothedPlusDm; - private readonly Rma _smoothedMinusDm; - private readonly Rma _smoothedDx; - private double _prevHigh, _prevLow, _prevClose; - private double _p_prevHigh, _p_prevLow, _p_prevClose; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 14; - - /// The number of periods used in the ADX calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adx(int period = DefaultPeriod) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - _smoothedTr = new(period, useSma: true); - _smoothedPlusDm = new(period, useSma: true); - _smoothedMinusDm = new(period, useSma: true); - _smoothedDx = new(period, useSma: true); - _index = 0; - WarmupPeriod = period * 2; // Need extra period for DX smoothing - Name = $"ADX({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the ADX calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adx(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevHigh = _prevHigh; - _p_prevLow = _prevLow; - _p_prevClose = _prevClose; - } - else - { - _prevHigh = _p_prevHigh; - _prevLow = _p_prevLow; - _prevClose = _p_prevClose; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateTrueRange(double high, double low, double prevClose) - { - double hl = high - low; - double hpc = Math.Abs(high - prevClose); - double lpc = Math.Abs(low - prevClose); - return Math.Max(hl, Math.Max(hpc, lpc)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double plusDm, double minusDm) CalculateDirectionalMovement( - double high, double low, double prevHigh, double prevLow) - { - double upMove = high - prevHigh; - double downMove = prevLow - low; - - double plusDm = 0.0; - double minusDm = 0.0; - - if (upMove > downMove && upMove > 0) - plusDm = upMove; - else if (downMove > upMove && downMove > 0) - minusDm = downMove; - - return (plusDm, minusDm); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateDx(double plusDi, double minusDi) - { - double sum = plusDi + minusDi; - if (sum > 0) - return ScalingFactor * Math.Abs(plusDi - minusDi) / sum; - return 0.0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index == 1) - { - _prevHigh = Input.High; - _prevLow = Input.Low; - _prevClose = Input.Close; - return 0.0; - } - - // Calculate True Range and Directional Movement - double tr = CalculateTrueRange(Input.High, Input.Low, _prevClose); - var (plusDm, minusDm) = CalculateDirectionalMovement( - Input.High, Input.Low, _prevHigh, _prevLow); - - // Update previous values - _prevHigh = Input.High; - _prevLow = Input.Low; - _prevClose = Input.Close; - - // Smooth the indicators using Wilder's method - _smoothedTr.Calc(tr, Input.IsNew); - _smoothedPlusDm.Calc(plusDm, Input.IsNew); - _smoothedMinusDm.Calc(minusDm, Input.IsNew); - - // Calculate +DI and -DI - double smoothedTr = _smoothedTr.Value; - if (smoothedTr > 0) - { - double plusDi = ScalingFactor * _smoothedPlusDm.Value / smoothedTr; - double minusDi = ScalingFactor * _smoothedMinusDm.Value / smoothedTr; - - // Calculate DX - double dx = CalculateDx(plusDi, minusDi); - - // Smooth DX to get ADX - _smoothedDx.Calc(dx, Input.IsNew); - return _smoothedDx.Value; - } - - return 0.0; - } -} diff --git a/lib/momentum/Adxr.cs b/lib/momentum/Adxr.cs deleted file mode 100644 index 75969c59..00000000 --- a/lib/momentum/Adxr.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ADXR: Average Directional Movement Index Rating -/// A momentum indicator that measures the strength of a trend by comparing -/// the current ADX value with its value from a specified number of periods ago. -/// -/// -/// The ADXR calculation process: -/// 1. Calculate current ADX -/// 2. Get ADX value from n periods ago -/// 3. Average the two values -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Values above 25 indicate strong trend -/// - Values below 20 indicate weak or no trend -/// - Can be used to confirm trend strength -/// - Helps identify potential trend reversals -/// -/// Formula: -/// ADXR = (Current ADX + ADX n periods ago) / 2 -/// -/// Sources: -/// J. Welles Wilder Jr. - "New Concepts in Technical Trading Systems" (1978) -/// https://www.investopedia.com/terms/a/adxr.asp -/// -public sealed class Adxr : AbstractBarBase -{ - private readonly Adx _currentAdx; - private readonly CircularBuffer _adxHistory; - private readonly int _period; - - /// The number of periods used in the ADXR calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adxr(int period = 14) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - _currentAdx = new(period); - _adxHistory = new(period); - _period = period; - WarmupPeriod = period * 3; // Need extra periods for ADX calculation and history - Name = $"ADXR({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the ADXR calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adxr(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate current ADX - double currentAdx = _currentAdx.Calc(Input); - _adxHistory.Add(currentAdx, Input.IsNew); - - // Calculate ADXR once we have enough history - if (_index > _period) - { - return (currentAdx + _adxHistory[^_period]) * 0.5; - } - - return currentAdx; - } -} diff --git a/lib/momentum/Apo.cs b/lib/momentum/Apo.cs deleted file mode 100644 index cf23537a..00000000 --- a/lib/momentum/Apo.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// APO: Absolute Price Oscillator -/// A momentum indicator that measures the difference between two moving averages -/// of different periods. Similar to PPO but shows absolute difference instead of percentage. -/// -public sealed class Apo : AbstractBase -{ - private readonly AbstractBase _fastMa, _slowMa; - - /// The period for the faster moving average. - /// The period for the slower moving average. - /// - /// Thrown when fastPeriod or slowPeriod is less than 1, or when fastPeriod is greater than or equal to slowPeriod. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Apo(int fastPeriod = 12, int slowPeriod = 26) - { - ArgumentOutOfRangeException.ThrowIfLessThan(fastPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(slowPeriod, 1); - ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(fastPeriod, slowPeriod); - - _fastMa = new Ema(fastPeriod); - _slowMa = new Ema(slowPeriod); - WarmupPeriod = slowPeriod; - Name = $"APO({fastPeriod},{slowPeriod})"; - } - - /// The data source object that publishes updates. - /// The period for the faster moving average. - /// The period for the slower moving average. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Apo(object source, int fastPeriod, int slowPeriod) : this(fastPeriod, slowPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _lastValidValue = Input.Value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _fastMa.Calc(Input); - _slowMa.Calc(Input); - return _fastMa.Value - _slowMa.Value; - } -} diff --git a/lib/momentum/Dmi.cs b/lib/momentum/Dmi.cs deleted file mode 100644 index 432e2c53..00000000 --- a/lib/momentum/Dmi.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DMI: Directional Movement Index -/// A technical indicator that identifies the directional movement of price by -/// comparing successive highs and lows. DMI consists of two lines: +DI and -DI, -/// which help determine trend direction and strength. -/// -/// -/// The DMI calculation process: -/// 1. Calculate True Range (TR) -/// 2. Calculate +DM (Positive Directional Movement) -/// 3. Calculate -DM (Negative Directional Movement) -/// 4. Smooth TR, +DM, and -DM using Wilder's smoothing -/// 5. Calculate +DI and -DI as percentages -/// -/// Key characteristics: -/// - Both +DI and -DI oscillate between 0 and 100 -/// - When +DI > -DI, uptrend is indicated -/// - When -DI > +DI, downtrend is indicated -/// - Crossovers of +DI and -DI signal potential trend changes -/// - Used in conjunction with ADX for trend trading -/// -/// Formula: -/// TR = max(high-low, abs(high-prevClose), abs(low-prevClose)) -/// +DM = if(high-prevHigh > prevLow-low && high-prevHigh > 0) then high-prevHigh else 0 -/// -DM = if(prevLow-low > high-prevHigh && prevLow-low > 0) then prevLow-low else 0 -/// Smoothed TR = Wilder's smoothing of TR (ATR) -/// Smoothed +DM = Wilder's smoothing of +DM -/// Smoothed -DM = Wilder's smoothing of -DM -/// +DI = 100 * Smoothed(+DM) / Smoothed(TR) -/// -DI = 100 * Smoothed(-DM) / Smoothed(TR) -/// -/// Sources: -/// J. Welles Wilder Jr. - "New Concepts in Technical Trading Systems" (1978) -/// https://www.investopedia.com/terms/d/dmi.asp -/// -/// Note: Default period of 14 was recommended by Wilder -/// -[SkipLocalsInit] -public sealed class Dmi : AbstractBase -{ - private readonly Atr _atr; - private readonly Rma _smoothedPlusDm; - private readonly Rma _smoothedMinusDm; - private double _prevHigh, _prevLow; - private double _p_prevHigh, _p_prevLow; - private double _plusDi, _minusDi; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 14; - - public double PlusDI => _plusDi; - public double MinusDI => _minusDi; - - public Dmi(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - _atr = new(period); - _smoothedPlusDm = new(period); - _smoothedMinusDm = new(period); - WarmupPeriod = period + 1; - Name = $"DMI({period})"; - } - - public override void Init() - { - base.Init(); - _atr.Init(); - _smoothedPlusDm.Init(); - _smoothedMinusDm.Init(); - _prevHigh = _prevLow = double.NaN; - _p_prevHigh = _p_prevLow = double.NaN; - _plusDi = _minusDi = 0; - _index = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevHigh = _prevHigh; - _p_prevLow = _prevLow; - } - else - { - _prevHigh = _p_prevHigh; - _prevLow = _p_prevLow; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double plusDm, double minusDm) CalculateDirectionalMovement( - double high, double low, double prevHigh, double prevLow) - { - double upMove = high - prevHigh; - double downMove = prevLow - low; - - double plusDm = (upMove > downMove && upMove > 0) ? upMove : 0; - double minusDm = (downMove > upMove && downMove > 0) ? downMove : 0; - - return (plusDm, minusDm); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - if (double.IsNaN(_prevHigh)) - { - _prevHigh = BarInput.High; - _prevLow = BarInput.Low; - return 0.0; - } - - // Calculate ATR - double atr = _atr.Calc(BarInput).Value; - - // Calculate Directional Movement - var (plusDm, minusDm) = CalculateDirectionalMovement( - BarInput.High, BarInput.Low, _prevHigh, _prevLow); - - // Update previous values for next calculation - _prevHigh = BarInput.High; - _prevLow = BarInput.Low; - - // Smooth DM values using Wilder's method - double smoothedPlusDm = _smoothedPlusDm.Calc(plusDm, BarInput.IsNew).Value; - double smoothedMinusDm = _smoothedMinusDm.Calc(minusDm, BarInput.IsNew).Value; - - // Calculate DI values - if (atr > 0) - { - _plusDi = ScalingFactor * smoothedPlusDm / atr; - _minusDi = ScalingFactor * smoothedMinusDm / atr; - return _plusDi - _minusDi; - } - - _plusDi = 0.0; - _minusDi = 0.0; - return 0.0; - } -} diff --git a/lib/momentum/Dmx.cs b/lib/momentum/Dmx.cs deleted file mode 100644 index a5acf5e6..00000000 --- a/lib/momentum/Dmx.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DMX: Enhanced Directional Movement Index using JMA smoothing -/// An improvement over the traditional DMI indicator that uses Jurik Moving Average (JMA) -/// for smoothing. This enhancement provides better noise reduction while maintaining -/// responsiveness to significant price movements. -/// -/// -/// The DMX calculation process: -/// 1. Calculate DMI using the standard Dmi class -/// 2. Apply JMA smoothing to the +DI and -DI values -/// -/// Key improvements over DMI: -/// - Uses JMA's adaptive volatility-based smoothing -/// - Better noise reduction in the directional movement signals -/// - Maintains responsiveness to significant price movements -/// - Reduced lag through JMA's phase-shifting -/// -/// Formula: -/// DMI calculation as per standard DMI -/// DMX +DI = JMA(DMI +DI) -/// DMX -DI = JMA(DMI -DI) -/// -/// Sources: -/// Original DMI by J. Welles Wilder Jr. - "New Concepts in Technical Trading Systems" (1978) -/// Enhanced with JMA smoothing by Mark Jurik -/// -[SkipLocalsInit] -public sealed class Dmx : AbstractBarBase -{ - private readonly Dmi _dmi; - private readonly Jma _smoothedPlusDi; - private readonly Jma _smoothedMinusDi; - private double _plusDi, _minusDi; - private const int DefaultDmiPeriod = 14; - private const int DefaultJmaPeriod = 7; - private const int DefaultPhase = 100; - private const double DefaultFactor = 0.25; - - /// - /// Gets the most recent smoothed +DI value - /// - public double PlusDI => _plusDi; - - /// - /// Gets the most recent smoothed -DI value - /// - public double MinusDI => _minusDi; - - /// The number of periods used in the DMI calculation (default 14). - /// The number of periods used in the JMA smoothing (default 10). - /// The phase for the JMA smoothing (default 100). - /// The factor for the JMA smoothing (default 0.25). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dmx(int period = DefaultDmiPeriod, int jmaPeriod = DefaultJmaPeriod, int phase = DefaultPhase, double factor = DefaultFactor) - { - if (period < 1 || jmaPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(period), "Periods must be greater than or equal to 1."); - _dmi = new(period); - _smoothedPlusDi = new(jmaPeriod, phase, factor); - _smoothedMinusDi = new(jmaPeriod, phase, factor); - WarmupPeriod = period + jmaPeriod; - Name = $"DMX({period},{jmaPeriod})"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate DMI - _dmi.Calc(Input); - - // Smooth the DMI values using JMA - _plusDi = _smoothedPlusDi.Calc(_dmi.PlusDI, Input.IsNew).Value; - _minusDi = _smoothedMinusDi.Calc(_dmi.MinusDI, Input.IsNew).Value; - - return _plusDi - _minusDi; // Return the difference as main value - } -} diff --git a/lib/momentum/Dpo.cs b/lib/momentum/Dpo.cs deleted file mode 100644 index 1ba8e4c7..00000000 --- a/lib/momentum/Dpo.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DPO: Detrended Price Oscillator -/// A momentum indicator that removes the trend from price by comparing the current price -/// to a past moving average, helping to identify cycles in the price. -/// -/// -/// The DPO calculation process: -/// 1. Calculate the period shifted back by (period / 2 + 1) days -/// 2. Calculate SMA for the shifted period -/// 3. DPO = Price - SMA(Price, period) shifted back -/// -/// Key characteristics: -/// - Removes long-term trends -/// - Helps identify cycles -/// - Oscillates above and below zero -/// - Default period is 20 days -/// - Uses price displacement -/// -/// Formula: -/// DPO = Price - SMA(Price, period) shifted (period/2 + 1) bars back -/// -/// Market Applications: -/// - Cycle identification -/// - Overbought/Oversold conditions -/// - Price momentum -/// - Trading signals -/// - Market timing -/// -/// Sources: -/// Donald Dorsey - Original development -/// https://www.investopedia.com/terms/d/detrended-price-oscillator-dpo.asp -/// -/// Note: DPO helps identify cycles by removing the trend component from the price data -/// -[SkipLocalsInit] -public sealed class Dpo : AbstractBase -{ - private readonly int _shift; - private readonly CircularBuffer _prices; - private readonly CircularBuffer _sma; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dpo(int period = 20) - { - _shift = (period / 2) + 1; - WarmupPeriod = period + _shift; - Name = $"DPO({period})"; - _prices = new CircularBuffer(WarmupPeriod); - _sma = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dpo(object source, int period = 20) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prices.Clear(); - _sma.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Add current price to buffer - _prices.Add(BarInput.Close, BarInput.IsNew); - // Need enough prices for the shifted SMA calculation - - if (_index <= _shift) - { - return 0; - } - - // Add price from shift periods ago to SMA buffer - _sma.Add(_prices[_shift]); - - // Calculate DPO - double dpo = BarInput.Close - _sma.Average(); - - IsHot = _index >= WarmupPeriod; - return dpo; - } -} diff --git a/lib/momentum/Macd.cs b/lib/momentum/Macd.cs deleted file mode 100644 index 263c80ec..00000000 --- a/lib/momentum/Macd.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MACD: Moving Average Convergence Divergence -/// A trend-following momentum indicator that shows the relationship between two moving -/// averages of an asset's price. MACD is calculated by subtracting the longer-period -/// EMA from the shorter-period EMA. The result is then used to calculate a signal line -/// (EMA of MACD) and histogram (MACD - Signal). -/// -/// -/// The MACD calculation process: -/// 1. Calculate the fast EMA (default 12 periods) -/// 2. Calculate the slow EMA (default 26 periods) -/// 3. MACD Line = Fast EMA - Slow EMA -/// 4. Signal Line = EMA of MACD Line (default 9 periods) -/// 5. MACD Histogram = MACD Line - Signal Line -/// -/// Key characteristics: -/// - Centerline crossovers signal trend changes -/// - Signal line crossovers indicate trading opportunities -/// - Histogram shows momentum of price movement -/// - Divergences can signal potential reversals -/// -/// Formula: -/// MACD Line = EMA(fast) - EMA(slow) -/// Signal Line = EMA(MACD Line, signal) -/// Histogram = MACD Line - Signal Line -/// -/// Sources: -/// https://www.investopedia.com/terms/m/macd.asp -/// https://school.stockcharts.com/doku.php?id=technical_indicators:macd -/// -[SkipLocalsInit] -public sealed class Macd : AbstractBase -{ - private readonly Ema _fastEma; - private readonly Ema _slowEma; - private readonly Ema _signalEma; - private const int DefaultFastPeriod = 12; - private const int DefaultSlowPeriod = 26; - private const int DefaultSignalPeriod = 9; - private double _macdLine; - private double _signalLine; - - /// - /// Gets the MACD line value (Fast EMA - Slow EMA) - /// - public double MacdLine => _macdLine; - - /// - /// Gets the Signal line value (EMA of MACD line) - /// - public double SignalLine => _signalLine; - - /// The number of periods for the fast EMA (default 12). - /// The number of periods for the slow EMA (default 26). - /// The number of periods for the signal line EMA (default 9). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Macd(int fastPeriod = DefaultFastPeriod, int slowPeriod = DefaultSlowPeriod, int signalPeriod = DefaultSignalPeriod) - { - ArgumentOutOfRangeException.ThrowIfLessThan(fastPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(slowPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(signalPeriod, 1); - - if (fastPeriod >= slowPeriod) - { - throw new ArgumentOutOfRangeException(nameof(fastPeriod), "Fast period must be less than slow period"); - } - - _fastEma = new(fastPeriod); - _slowEma = new(slowPeriod); - _signalEma = new(signalPeriod); - WarmupPeriod = slowPeriod + signalPeriod; - Name = $"MACD({fastPeriod},{slowPeriod},{signalPeriod})"; - } - - /// The data source object that publishes updates. - /// The number of periods for the fast EMA. - /// The number of periods for the slow EMA. - /// The number of periods for the signal line EMA. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Macd(object source, int fastPeriod, int slowPeriod, int signalPeriod) : this(fastPeriod, slowPeriod, signalPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate MACD line - double fastEma = _fastEma.Calc(Input.Value, Input.IsNew); - double slowEma = _slowEma.Calc(Input.Value, Input.IsNew); - _macdLine = fastEma - slowEma; - - // Calculate Signal line - _signalLine = _signalEma.Calc(_macdLine, Input.IsNew); - - // Return histogram - return _macdLine - _signalLine; - } -} diff --git a/lib/momentum/Mom.cs b/lib/momentum/Mom.cs deleted file mode 100644 index 41f1c113..00000000 --- a/lib/momentum/Mom.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Mom: Momentum -/// A basic momentum indicator that measures the change in price over a specified -/// period, helping identify the strength and speed of price movements. -/// -/// -/// The Momentum calculation process: -/// 1. Store historical prices in a circular buffer -/// 2. Calculate absolute difference between current and historical price -/// 3. No scaling factor applied to maintain raw price difference -/// -/// Key characteristics: -/// - Basic momentum measurement -/// - Shows absolute price changes -/// - Zero line crossovers signal trend changes -/// - Foundation for other momentum indicators -/// -/// Formula: -/// Mom = Price - PriceN -/// where PriceN is the price N periods ago -/// -/// Sources: -/// Technical Analysis of Financial Markets by John J. Murphy -/// Technical Analysis Using Multiple Timeframes by Brian Shannon -/// -[SkipLocalsInit] -public sealed class Mom : AbstractBase -{ - private readonly CircularBuffer _priceBuffer; - private const int DefaultPeriod = 10; - - /// The lookback period for momentum calculation (default 10). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mom(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _priceBuffer = new(period + 1); - WarmupPeriod = period; - Name = $"MOM({period})"; - } - - /// The data source object that publishes updates. - /// The lookback period for momentum calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mom(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _priceBuffer.Add(Input.Value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_priceBuffer.Count < _priceBuffer.Capacity) - return 0.0; - - return Input.Value - _priceBuffer[0]; - } -} diff --git a/lib/momentum/Pmo.cs b/lib/momentum/Pmo.cs deleted file mode 100644 index 2728eb9e..00000000 --- a/lib/momentum/Pmo.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PMO: Price Momentum Oscillator -/// A momentum indicator that uses exponential moving averages of ROC (Rate of Change) -/// to identify overbought and oversold conditions in price movements. -/// -/// -/// The PMO calculation process: -/// 1. Calculate ROC (Rate of Change) of closing prices -/// 2. Apply a first smoothing EMA to the ROC values -/// 3. Apply a second smoothing EMA to the result -/// 4. Multiply by a scaling factor for better visualization -/// -/// Key characteristics: -/// - Double-smoothed momentum indicator -/// - Helps identify overbought/oversold conditions -/// - Useful for trend confirmation and divergence analysis -/// - More responsive than traditional momentum oscillators -/// -/// Formula: -/// ROC = (Close - PrevClose) / PrevClose -/// Signal1 = EMA(ROC, Period1) -/// PMO = EMA(Signal1, Period2) * ScalingFactor -/// -/// Sources: -/// Developed by Carl Swenlin -/// Technical Analysis of Stocks and Commodities magazine -/// -[SkipLocalsInit] -public sealed class Pmo : AbstractBase -{ - private readonly Ema _smoothing1; - private readonly Ema _smoothing2; - private double _prevClose; - private double _p_prevClose; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod1 = 35; - private const int DefaultPeriod2 = 20; - - /// The first smoothing period (default 35). - /// The second smoothing period (default 20). - /// Thrown when either period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pmo(int period1 = DefaultPeriod1, int period2 = DefaultPeriod2) - { - if (period1 < 1 || period2 < 1) - throw new ArgumentOutOfRangeException(nameof(period1)); - - _smoothing1 = new(period1); - _smoothing2 = new(period2); - _index = 0; - WarmupPeriod = period1 + period2; - Name = $"PMO({period1},{period2})"; - } - - /// The data source object that publishes updates. - /// The first smoothing period. - /// The second smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pmo(object source, int period1, int period2) : this(period1, period2) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevClose = _prevClose; - } - else - { - _prevClose = _p_prevClose; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index == 1) - { - _prevClose = Input.Value; - return 0.0; - } - - // Calculate Rate of Change - double roc = (Input.Value - _prevClose) / _prevClose; - _prevClose = Input.Value; - - // Apply double smoothing - double signal1 = _smoothing1.Calc(roc, Input.IsNew); - return _smoothing2.Calc(signal1, Input.IsNew) * ScalingFactor; - } -} diff --git a/lib/momentum/Po.cs b/lib/momentum/Po.cs deleted file mode 100644 index 5dca35ea..00000000 --- a/lib/momentum/Po.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PO: Price Oscillator -/// A momentum indicator that measures the difference between two moving averages -/// of different periods to identify price momentum and potential trend changes. -/// -/// -/// The PO calculation process: -/// 1. Calculate fast EMA of closing prices -/// 2. Calculate slow EMA of closing prices -/// 3. Calculate the difference between fast and slow EMAs -/// 4. Multiply by a scaling factor for better visualization -/// -/// Key characteristics: -/// - Measures momentum through moving average differences -/// - Helps identify trend direction and potential reversals -/// - Zero line crossovers signal trend changes -/// - Similar to MACD but more customizable periods -/// -/// Formula: -/// FastMA = EMA(Close, FastPeriod) -/// SlowMA = EMA(Close, SlowPeriod) -/// PO = (FastMA - SlowMA) * ScalingFactor -/// -/// Sources: -/// Technical Analysis of Financial Markets by John J. Murphy -/// -[SkipLocalsInit] -public sealed class Po : AbstractBase -{ - private readonly Ema _fastEma; - private readonly Ema _slowEma; - private const double ScalingFactor = 1.0; - private const int DefaultFastPeriod = 10; - private const int DefaultSlowPeriod = 21; - - /// The fast EMA period (default 10). - /// The slow EMA period (default 21). - /// Thrown when either period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Po(int fastPeriod = DefaultFastPeriod, int slowPeriod = DefaultSlowPeriod) - { - if (fastPeriod < 1 || slowPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(fastPeriod)); - if (fastPeriod >= slowPeriod) - throw new ArgumentException("Fast period must be less than slow period"); - - _fastEma = new(fastPeriod); - _slowEma = new(slowPeriod); - WarmupPeriod = slowPeriod; - Name = $"PO({fastPeriod},{slowPeriod})"; - } - - /// The data source object that publishes updates. - /// The fast EMA period. - /// The slow EMA period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Po(object source, int fastPeriod, int slowPeriod) : this(fastPeriod, slowPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - // No state management needed for this indicator - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - double fastEma = _fastEma.Calc(Input.Value, Input.IsNew); - double slowEma = _slowEma.Calc(Input.Value, Input.IsNew); - return (fastEma - slowEma) * ScalingFactor; - } -} diff --git a/lib/momentum/Ppo.cs b/lib/momentum/Ppo.cs deleted file mode 100644 index c6c29e76..00000000 --- a/lib/momentum/Ppo.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PPO: Percentage Price Oscillator -/// A momentum indicator that shows the percentage difference between two moving averages -/// of different periods, helping identify price momentum and potential trend changes. -/// -/// -/// The PPO calculation process: -/// 1. Calculate fast EMA of closing prices -/// 2. Calculate slow EMA of closing prices -/// 3. Calculate the percentage difference between fast and slow EMAs -/// 4. Multiply by a scaling factor for better visualization -/// -/// Key characteristics: -/// - Measures momentum through percentage differences -/// - Normalized for comparison across different price levels -/// - Zero line crossovers signal trend changes -/// - Similar to MACD but expressed as a percentage -/// -/// Formula: -/// FastMA = EMA(Close, FastPeriod) -/// SlowMA = EMA(Close, SlowPeriod) -/// PPO = ((FastMA - SlowMA) / SlowMA) * 100 -/// -/// Sources: -/// Technical Analysis of Financial Markets by John J. Murphy -/// StockCharts.com Technical Indicators -/// -[SkipLocalsInit] -public sealed class Ppo : AbstractBase -{ - private readonly Ema _fastEma; - private readonly Ema _slowEma; - private const double ScalingFactor = 100.0; - private const int DefaultFastPeriod = 12; - private const int DefaultSlowPeriod = 26; - - /// The fast EMA period (default 12). - /// The slow EMA period (default 26). - /// Thrown when either period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ppo(int fastPeriod = DefaultFastPeriod, int slowPeriod = DefaultSlowPeriod) - { - if (fastPeriod < 1 || slowPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(fastPeriod)); - if (fastPeriod >= slowPeriod) - throw new ArgumentException("Fast period must be less than slow period"); - - _fastEma = new(fastPeriod); - _slowEma = new(slowPeriod); - WarmupPeriod = slowPeriod; - Name = $"PPO({fastPeriod},{slowPeriod})"; - } - - /// The data source object that publishes updates. - /// The fast EMA period. - /// The slow EMA period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ppo(object source, int fastPeriod, int slowPeriod) : this(fastPeriod, slowPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - // No state management needed for this indicator - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - double fastEma = _fastEma.Calc(Input.Value, Input.IsNew); - double slowEma = _slowEma.Calc(Input.Value, Input.IsNew); - - if (Math.Abs(slowEma) <= double.Epsilon) - return 0.0; - - return ((fastEma - slowEma) / slowEma) * ScalingFactor; - } -} diff --git a/lib/momentum/Prs.cs b/lib/momentum/Prs.cs deleted file mode 100644 index 454c4b8e..00000000 --- a/lib/momentum/Prs.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PRS: Price Relative Strength -/// A momentum indicator that compares the performance of a security against a benchmark, -/// helping identify which is showing stronger relative momentum. -/// -/// -/// The PRS calculation process: -/// 1. Take the current price of the security -/// 2. Take the current price of the benchmark -/// 3. Calculate the ratio between them -/// 4. Multiply by a scaling factor for better visualization -/// -/// Key characteristics: -/// - Measures relative performance against a benchmark -/// - Helps identify market leaders and laggards -/// - Rising PRS indicates outperformance -/// - Falling PRS indicates underperformance -/// -/// Formula: -/// PRS = (Price / Benchmark) * 100 -/// -/// Sources: -/// Technical Analysis of Financial Markets by John J. Murphy -/// StockCharts.com Technical Indicators -/// -[SkipLocalsInit] -public sealed class Prs : AbstractBase -{ - private const double ScalingFactor = 100.0; - private double _benchmark; - private double _p_benchmark; - - /// - /// Initializes a new instance of the PRS indicator - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Prs() - { - WarmupPeriod = 1; - Name = "PRS"; - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Prs(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - /// - /// Sets the current benchmark value - /// - /// The benchmark value to compare against - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetBenchmark(double benchmark) - { - _benchmark = benchmark; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _p_benchmark = _benchmark; - else - _benchmark = _p_benchmark; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_benchmark <= double.Epsilon) - return 0.0; - - return (Input.Value / _benchmark) * ScalingFactor; - } -} diff --git a/lib/momentum/Roc.cs b/lib/momentum/Roc.cs deleted file mode 100644 index fc5c6d1e..00000000 --- a/lib/momentum/Roc.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ROC: Rate of Change -/// A momentum indicator that measures the percentage change in price over a specified -/// period, helping identify the speed and strength of price movements. -/// -/// -/// The ROC calculation process: -/// 1. Store historical prices in a circular buffer -/// 2. Calculate percentage change between current and historical price -/// 3. Multiply by scaling factor for better visualization -/// -/// Key characteristics: -/// - Pure momentum indicator -/// - Oscillates around zero line -/// - Helps identify overbought/oversold conditions -/// - Useful for divergence analysis -/// -/// Formula: -/// ROC = ((Price - PriceN) / PriceN) * 100 -/// where PriceN is the price N periods ago -/// -/// Sources: -/// Technical Analysis of Financial Markets by John J. Murphy -/// Technical Analysis of Stock Trends by Robert D. Edwards and John Magee -/// -[SkipLocalsInit] -public sealed class Roc : AbstractBase -{ - private readonly CircularBuffer _priceBuffer; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 12; - - /// The lookback period for ROC calculation (default 12). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Roc(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _priceBuffer = new(period + 1); - WarmupPeriod = period; - Name = $"ROC({period})"; - } - - /// The data source object that publishes updates. - /// The lookback period for ROC calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Roc(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _priceBuffer.Add(Input.Value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_priceBuffer.Count < _priceBuffer.Capacity) - return 0.0; - - double oldPrice = _priceBuffer[0]; - if (oldPrice <= double.Epsilon) - return 0.0; - - return ((Input.Value - oldPrice) / oldPrice) * ScalingFactor; - } -} diff --git a/lib/momentum/Trix.cs b/lib/momentum/Trix.cs deleted file mode 100644 index ddb1ee09..00000000 --- a/lib/momentum/Trix.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TRIX: Triple Exponential Average Rate of Change -/// A momentum oscillator that shows the percentage rate of change of a triple exponentially -/// smoothed moving average. TRIX filters out insignificant price movements and helps identify -/// overbought/oversold conditions and divergences. -/// -/// -/// The TRIX calculation process: -/// 1. Calculate Triple Exponential Moving Average (TEMA) -/// 2. Calculate 1-day Rate of Change (ROC) of the TEMA -/// -/// Key characteristics: -/// - Combines trend-following and momentum in one indicator -/// - Filters out price movements deemed insignificant -/// - Oscillates around zero line -/// - Useful for identifying divergences -/// - Helps spot overbought/oversold conditions -/// -/// Formula: -/// TEMA = 3*EMA1 - 3*EMA2 + EMA3 -/// TRIX = ROC(TEMA, 1) = ((TEMA - TEMA_prev) / TEMA_prev) * 100 -/// -/// Sources: -/// Jack Hutson - "Technical Analysis of Stocks and Commodities" magazine, 1983 -/// John J. Murphy - "Technical Analysis of the Financial Markets" -/// -[SkipLocalsInit] -public sealed class Trix : AbstractBase -{ - private readonly Tema _tema; - private readonly CircularBuffer _temaBuffer; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 18; - - /// The lookback period for TEMA calculation (default 18). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Trix(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _tema = new(period); - _temaBuffer = new(2); // We only need current and previous TEMA values - WarmupPeriod = period + 1; // TEMA period + 1 for ROC - Name = $"TRIX({period})"; - } - - /// The data source object that publishes updates. - /// The lookback period for TEMA calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Trix(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - double temaValue = _tema.Calc(Input); - _temaBuffer.Add(temaValue); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_temaBuffer.Count < _temaBuffer.Capacity) - return 0.0; - - double oldTema = _temaBuffer[0]; - if (oldTema <= double.Epsilon) - return 0.0; - - double currentTema = _temaBuffer[^1]; - return ((currentTema - oldTema) / oldTema) * ScalingFactor; - } -} diff --git a/lib/momentum/Vel.cs b/lib/momentum/Vel.cs deleted file mode 100644 index 20fffb21..00000000 --- a/lib/momentum/Vel.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Vel: Velocity -/// An enhanced momentum indicator that applies Jurik Moving Average (JMA) smoothing -/// to the basic momentum calculation, providing better noise reduction while -/// maintaining responsiveness to significant price movements. -/// -/// -/// The Velocity calculation process: -/// 1. Calculate basic momentum (price difference) -/// 2. Apply JMA smoothing to the momentum values -/// 3. No scaling factor applied to maintain price-based units -/// -/// Key characteristics: -/// - Enhanced momentum measurement with JMA smoothing -/// - Better noise reduction than basic momentum -/// - Maintains responsiveness to significant moves -/// - Reduced lag through JMA's phase-shifting -/// -/// Formula: -/// Mom = Price - PriceN -/// Vel = JMA(Mom, period) -/// -/// Sources: -/// Enhanced with JMA smoothing by Mark Jurik -/// Technical Analysis of Financial Markets by John J. Murphy -/// -[SkipLocalsInit] -public sealed class Vel : AbstractBase -{ - private readonly CircularBuffer _priceBuffer; - private readonly Jma _smoothing; - private const int DefaultPeriod = 10; - private const int DefaultPhase = 100; - private const double DefaultFactor = 0.25; - - /// The lookback period for velocity calculation (default 10). - /// The phase for the JMA smoothing (default 0). - /// The power factor for the JMA smoothing (default 2.0). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vel(int period = DefaultPeriod, int phase = DefaultPhase, double factor = DefaultFactor) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _priceBuffer = new(period + 1); - _smoothing = new(period, phase, factor); - WarmupPeriod = period * 2; // JMA needs more warmup periods - Name = $"VEL({period})"; - } - - /// The data source object that publishes updates. - /// The lookback period for velocity calculation. - /// The phase for the JMA smoothing. - /// The power factor for the JMA smoothing. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vel(object source, int period, int phase = DefaultPhase, double power = DefaultFactor) - : this(period, phase, power) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _priceBuffer.Add(Input.Value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_priceBuffer.Count < _priceBuffer.Capacity) - return 0.0; - - // Calculate basic momentum - double momentum = Input.Value - _priceBuffer[0]; - - // Apply JMA smoothing - return _smoothing.Calc(momentum, Input.IsNew); - } -} diff --git a/lib/momentum/Vortex.cs b/lib/momentum/Vortex.cs deleted file mode 100644 index 2ca77cc6..00000000 --- a/lib/momentum/Vortex.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VORTEX: Vortex Indicator -/// A technical indicator consisting of two oscillating lines that identify trend reversals -/// and confirm current trends based on the highs and lows of the previous period. -/// -/// -/// The Vortex calculation process: -/// 1. Calculate True Range (TR): -/// TR = max(High - Low, |High - Previous Close|, |Low - Previous Close|) -/// 2. Calculate +VM (Positive Movement): -/// +VM = |Current High - Previous Low| -/// 3. Calculate -VM (Negative Movement): -/// -VM = |Current Low - Previous High| -/// 4. Calculate period sums: -/// TR Period Sum = Sum(TR, period) -/// +VM Period Sum = Sum(+VM, period) -/// -VM Period Sum = Sum(-VM, period) -/// 5. Calculate +VI and -VI: -/// +VI = +VM Period Sum / TR Period Sum -/// -VI = -VM Period Sum / TR Period Sum -/// -/// Key characteristics: -/// - Two oscillating lines (+VI and -VI) -/// - No upper or lower bounds -/// - Default period is 14 days -/// - Crossovers signal trend changes -/// - Uses true range normalization -/// -/// Formula: -/// +VI = Sum(+VM, period) / Sum(TR, period) -/// -VI = Sum(-VM, period) / Sum(TR, period) -/// -/// Market Applications: -/// - Trend identification -/// - Trend reversals -/// - Trend confirmation -/// - Trading signals -/// - Market momentum -/// -/// Sources: -/// Etienne Botes and Douglas Siepman - Original development (2010) -/// https://www.investopedia.com/terms/v/vortex-indicator-vi.asp -/// -/// Note: When +VI crosses above -VI, it signals a potential uptrend, and vice versa -/// -[SkipLocalsInit] -public sealed class Vortex : AbstractBase -{ - private readonly CircularBuffer _tr; - private readonly CircularBuffer _vmPlus; - private readonly CircularBuffer _vmMinus; - private double _prevHigh; - private double _prevLow; - private double _prevClose; - public double _viPlus { get; set; } - public double _viMinus { get; set; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vortex(int period = 14) - { - WarmupPeriod = period + 1; // Need one extra period for previous values - Name = $"VORTEX({period})"; - _tr = new CircularBuffer(period); - _vmPlus = new CircularBuffer(period); - _vmMinus = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vortex(object source, int period = 14) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevHigh = 0; - _prevLow = 0; - _prevClose = 0; - _viPlus = 0; - _viMinus = 0; - _tr.Clear(); - _vmPlus.Clear(); - _vmMinus.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous values - if (_index == 1) - { - _prevHigh = BarInput.High; - _prevLow = BarInput.Low; - _prevClose = BarInput.Close; - return 0; - } - - // Calculate True Range - double tr = Math.Max(BarInput.High - BarInput.Low, - Math.Max(Math.Abs(BarInput.High - _prevClose), - Math.Abs(BarInput.Low - _prevClose))); - - // Calculate VM+ and VM- - double vmPlus = Math.Abs(BarInput.High - _prevLow); - double vmMinus = Math.Abs(BarInput.Low - _prevHigh); - - // Add values to buffers - _tr.Add(tr); - _vmPlus.Add(vmPlus); - _vmMinus.Add(vmMinus); - - // Calculate VI+ and VI- - double trSum = _tr.Sum(); - if (Math.Abs(trSum) > double.Epsilon) - { - _viPlus = _vmPlus.Sum() / trSum; - _viMinus = _vmMinus.Sum() / trSum; - } - - // Store current values for next calculation - _prevHigh = BarInput.High; - _prevLow = BarInput.Low; - _prevClose = BarInput.Close; - - // Return the difference between VI+ and VI- - double vortex = _viPlus - _viMinus; - - IsHot = _index >= WarmupPeriod; - return vortex; - } - - /// - /// Gets the positive Vortex line (VI+) - /// - public double ViPlus => _viPlus; - - /// - /// Gets the negative Vortex line (VI-) - /// - public double ViMinus => _viMinus; -} diff --git a/lib/momentum/_list.md b/lib/momentum/_list.md deleted file mode 100644 index a73f18e3..00000000 --- a/lib/momentum/_list.md +++ /dev/null @@ -1,19 +0,0 @@ -# Momentum indicators - -✔️ ADX - Average Directional Movement Index -✔️ ADXR - Average Directional Movement Index Rating -✔️ APO - Absolute Price Oscillator -✔️ DMI - Directional Movement Index (DI+, DI-) -✔️ DMX - Jurik Directional Movement Index -✔️ DPO - Detrended Price Oscillator -✔️ MACD - Moving Average Convergence/Divergence (MACD, Signal, Histogram) -✔️ MOM - Momentum -✔️ PMO - Price Momentum Oscillator -✔️ PO - Price Oscillator -✔️ PPO - Percentage Price Oscillator -✔️ PRS - Price Relative Strength -✔️ ROC - Rate of Change -✔️ TSI - True Strength Index -✔️ TRIX - 1-day ROC of TEMA -✔️ VEL - Jurik Signal Velocity -✔️ VORTEX - Vortex Indicator (VI+, VI-) diff --git a/lib/oscillators/Ac.cs b/lib/oscillators/Ac.cs deleted file mode 100644 index 96bbcd9c..00000000 --- a/lib/oscillators/Ac.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// AC: Acceleration/Deceleration Oscillator -/// A momentum indicator that measures the acceleration and deceleration of the current driving force. -/// It is derived from the Awesome Oscillator (AO) and helps identify potential trend reversals. -/// -/// -/// The AC calculation process: -/// 1. Calculate the Awesome Oscillator (AO) -/// 2. Calculate a 5-period simple moving average of the AO -/// 3. Subtract the 5-period SMA from the current AO value -/// -/// Key characteristics: -/// - Oscillates above and below zero -/// - Measures the acceleration/deceleration of market driving force -/// - Positive values indicate increasing momentum -/// - Negative values indicate decreasing momentum -/// - Can be used to identify potential trend reversals -/// -/// Formula: -/// AC = AO - SMA(AO, 5) -/// -/// Sources: -/// Bill Williams - "Trading Chaos" (1995) -/// https://www.investopedia.com/terms/a/ac.asp -/// -[SkipLocalsInit] -public sealed class Ac : AbstractBase -{ - private readonly Ao _ao; - private readonly Sma _sma5; - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ac(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ac() - { - _ao = new Ao(); - _sma5 = new Sma(5); - WarmupPeriod = 39; // AO requires 34 periods + 5 for AC's SMA - Name = "AC"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - var ao = _ao.Calc(BarInput, BarInput.IsNew); - _sma5.Calc(ao, BarInput.IsNew); - - return ao - _sma5.Value; - } -} diff --git a/lib/oscillators/Ao.cs b/lib/oscillators/Ao.cs deleted file mode 100644 index 3a00eaed..00000000 --- a/lib/oscillators/Ao.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// AO: Awesome Oscillator -/// A momentum indicator that reflects the precise changes in the market driving force. -/// It is used to affirm trends or to anticipate possible reversals. -/// -/// -/// The AO calculation process: -/// 1. Calculates the 5-period simple moving average of the HL2 (High+Low)/2 values. -/// 2. Calculates the 34-period simple moving average of the HL2 (High+Low)/2 values. -/// 3. Subtracts the 34-period SMA from the 5-period SMA. -/// -/// Key characteristics: -/// - Oscillates above and below zero -/// - Positive values indicate bullish momentum -/// - Negative values indicate bearish momentum -/// - Crosses above zero suggest buying opportunities -/// - Crosses below zero suggest selling opportunities -/// -/// Formula: -/// AO = SMA(HL2, 5) - SMA(HL2, 34) -/// -/// Sources: -/// Bill Williams - "Trading Chaos" (1995) -/// https://www.investopedia.com/terms/a/awesomeoscillator.asp -/// -[SkipLocalsInit] -public sealed class Ao : AbstractBase -{ - private readonly Sma _sma5; - private readonly Sma _sma34; - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ao(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ao() - { - _sma5 = new Sma(5); - _sma34 = new Sma(34); - WarmupPeriod = 34; - Name = "AO"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - _sma5.Calc(BarInput.HL2, BarInput.IsNew); - _sma34.Calc(BarInput.HL2, BarInput.IsNew); - - return _sma5.Value - _sma34.Value; - } -} diff --git a/lib/oscillators/Aroon.cs b/lib/oscillators/Aroon.cs deleted file mode 100644 index 618320ac..00000000 --- a/lib/oscillators/Aroon.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// AROON: Aroon Oscillator -/// A trend-following indicator that measures the strength of a trend and the likelihood -/// that the trend will continue. It consists of two lines (Aroon Up and Aroon Down) and -/// their difference forms the Aroon Oscillator. -/// -/// -/// The Aroon calculation process: -/// 1. Tracks the number of periods since the last highest high (Aroon Up) -/// 2. Tracks the number of periods since the last lowest low (Aroon Down) -/// 3. Normalizes both values to a 0-100 scale -/// 4. Calculates the difference (Aroon Oscillator) -/// -/// Key characteristics: -/// - Oscillates between -100 and +100 -/// - Positive values indicate uptrend -/// - Negative values indicate downtrend -/// - Zero line crossovers signal trend changes -/// - Extreme readings suggest strong trends -/// -/// Formula: -/// Aroon Up = ((period - days since highest high) / period) × 100 -/// Aroon Down = ((period - days since lowest low) / period) × 100 -/// Aroon Oscillator = Aroon Up - Aroon Down -/// -/// Sources: -/// Tushar Chande - "The New Technical Trader" (1994) -/// https://www.investopedia.com/terms/a/aroonoscillator.asp -/// -/// Note: Default period of 25 was recommended by Chande -/// -[SkipLocalsInit] -public sealed class Aroon : AbstractBarBase -{ - private readonly CircularBuffer _highPrices; - private readonly CircularBuffer _lowPrices; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 25; - - /// The number of periods used in the Aroon calculation (default 25). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Aroon(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _highPrices = new(period); - _lowPrices = new(period); - _index = 0; - WarmupPeriod = period; - Name = $"AROON({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the Aroon calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Aroon(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _highPrices.Add(Input.High); - _lowPrices.Add(Input.Low); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateAroonLine(int period, int daysSince) - { - return ((period - daysSince) * ScalingFactor) / period; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index < WarmupPeriod) - return double.NaN; - - // Find highest high and lowest low positions - int highestIndex = 0; - int lowestIndex = 0; - double highestHigh = _highPrices[0]; - double lowestLow = _lowPrices[0]; - - for (int i = 1; i < _highPrices.Count; i++) - { - if (_highPrices[i] > highestHigh) - { - highestHigh = _highPrices[i]; - highestIndex = i; - } - if (_lowPrices[i] < lowestLow) - { - lowestLow = _lowPrices[i]; - lowestIndex = i; - } - } - - // Calculate Aroon Up and Down - double aroonUp = CalculateAroonLine(_highPrices.Count, highestIndex); - double aroonDown = CalculateAroonLine(_lowPrices.Count, lowestIndex); - - // Return Aroon Oscillator - return aroonUp - aroonDown; - } -} diff --git a/lib/oscillators/Bop.cs b/lib/oscillators/Bop.cs deleted file mode 100644 index a2a3426c..00000000 --- a/lib/oscillators/Bop.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// BOP: Balance of Power -/// A momentum oscillator that measures the strength of buying and selling pressure by comparing -/// closing prices to their corresponding opening prices. -/// -/// -/// The BOP calculation process: -/// 1. Calculate (Close - Open) / (High - Low) for each period -/// 2. A positive BOP indicates buying pressure (bullish) -/// 3. A negative BOP indicates selling pressure (bearish) -/// -/// Key characteristics: -/// - Oscillates above and below zero -/// - No upper or lower bounds -/// - Zero line acts as equilibrium between buying and selling pressure -/// - Can be used to identify potential trend reversals and divergences -/// -/// Formula: -/// BOP = (Close - Open) / (High - Low) -/// -/// Sources: -/// Igor Livshin (1990s) -/// https://www.investopedia.com/terms/b/bop.asp -/// -[SkipLocalsInit] -public sealed class Bop : AbstractBase -{ - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Bop(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Bop() - { - WarmupPeriod = 1; - Name = "BOP"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - var range = BarInput.High - BarInput.Low; - if (range <= double.Epsilon) return 0; - - return (BarInput.Close - BarInput.Open) / range; - } -} diff --git a/lib/oscillators/Cci.cs b/lib/oscillators/Cci.cs deleted file mode 100644 index 8fde77c1..00000000 --- a/lib/oscillators/Cci.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CCI: Commodity Channel Index -/// A momentum oscillator used to identify cyclical trends and measure the deviation of price -/// from its statistical mean. -/// -/// -/// The CCI calculation process: -/// 1. Calculate Typical Price (TP) = (High + Low + Close) / 3 -/// 2. Calculate Simple Moving Average of TP -/// 3. Calculate Mean Deviation -/// 4. CCI = (TP - SMA(TP)) / (0.015 * Mean Deviation) -/// -/// Key characteristics: -/// - Oscillates above and below zero -/// - Typically ranges between +100 and -100 -/// - Values above +100 indicate overbought conditions -/// - Values below -100 indicate oversold conditions -/// - Can identify trend strength and reversals -/// -/// Formula: -/// CCI = (TypicalPrice - SMA(TypicalPrice, period)) / (0.015 * MeanDeviation) -/// where: -/// - TypicalPrice = (High + Low + Close) / 3 -/// - MeanDeviation = Mean(|TP - SMA(TP)|) -/// -/// Sources: -/// Donald Lambert (1980) -/// https://www.investopedia.com/terms/c/commoditychannelindex.asp -/// -[SkipLocalsInit] -public sealed class Cci : AbstractBase -{ - private readonly int _period; - private readonly Sma _sma; - private readonly double[] _typicalPrices; - private readonly double _constant = 0.015; - - /// The data source object that publishes updates. - /// The calculation period (default: 20) - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cci(object source, int period = 20) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cci(int period = 20) - { - _period = period; - _sma = new Sma(period); - _typicalPrices = new double[period]; - WarmupPeriod = period; - Name = "CCI"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateMeanDeviation(double typicalPrice, double smaValue) - { - var sum = 0.0; - var count = System.Math.Min(_period, _index + 1); - - for (var i = 0; i < count; i++) - { - sum += System.Math.Abs(_typicalPrices[i] - smaValue); - } - - return sum / count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - var typicalPrice = (BarInput.High + BarInput.Low + BarInput.Close) / 3.0; - var idx = _index % _period; - _typicalPrices[idx] = typicalPrice; - - var smaValue = _sma.Calc(typicalPrice, BarInput.IsNew); - if (_index < _period - 1) return double.NaN; - - var meanDeviation = CalculateMeanDeviation(typicalPrice, smaValue); - if (meanDeviation <= double.Epsilon) return 0; - - return (typicalPrice - smaValue) / (_constant * meanDeviation); - } -} diff --git a/lib/oscillators/Cfo.cs b/lib/oscillators/Cfo.cs deleted file mode 100644 index 518bb57e..00000000 --- a/lib/oscillators/Cfo.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CFO: Chande Forecast Oscillator -/// A momentum oscillator that measures the percentage difference between the actual price -/// and its linear regression forecast value. -/// -/// -/// The CFO calculation process: -/// 1. Calculate linear regression forecast value for the current period -/// 2. Calculate percentage difference between actual price and forecast -/// -/// Key characteristics: -/// - Oscillates above and below zero -/// - Measures deviation of price from its forecasted value -/// - Positive values indicate price is above forecast (bullish) -/// - Negative values indicate price is below forecast (bearish) -/// - Can identify potential trend reversals and price divergences -/// -/// Formula: -/// CFO = ((Price - Forecast) / Price) * 100 -/// where: -/// - Price is typically the closing price -/// - Forecast is the linear regression forecast value -/// -/// Sources: -/// Tushar Chande (1990s) -/// Technical Analysis of Stocks and Commodities magazine -/// -[SkipLocalsInit] -public sealed class Cfo : AbstractBase -{ - private readonly int _period; - private readonly double[] _prices; - private double _sumX; - private double _sumY; - private double _sumXY; - private double _sumX2; - - /// The data source object that publishes updates. - /// The calculation period (default: 14) - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cfo(object source, int period = 14) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cfo(int period = 14) - { - _period = period; - _prices = new double[period]; - WarmupPeriod = period; - Name = "CFO"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void UpdateSums(double oldPrice, double newPrice, int oldX, int newX) - { - _sumY -= oldPrice; - _sumY += newPrice; - _sumXY -= oldPrice * oldX; - _sumXY += newPrice * newX; - _sumX -= oldX; - _sumX += newX; - _sumX2 -= oldX * oldX; - _sumX2 += newX * newX; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double CalculateForecast() - { - var count = System.Math.Min(_period, _index + 1); - var n = (double)count; - - // Calculate linear regression coefficients - var slope = ((n * _sumXY) - (_sumX * _sumY)) / ((n * _sumX2) - (_sumX * _sumX)); - var intercept = (_sumY - (slope * _sumX)) / n; - - // Calculate forecast for next period - return intercept + (slope * count); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - var price = Input.Value; - var idx = _index % _period; - var oldPrice = _prices[idx]; - _prices[idx] = price; - - var oldX = idx + 1; - var newX = _index < _period ? idx + 1 : _period; - - UpdateSums(oldPrice, price, oldX, newX); - if (_index < _period - 1) return double.NaN; - - var forecast = CalculateForecast(); - if (price <= double.Epsilon) return 0; - - return ((price - forecast) / price) * 100; - } -} diff --git a/lib/oscillators/Chop.cs b/lib/oscillators/Chop.cs deleted file mode 100644 index 78eea6d4..00000000 --- a/lib/oscillators/Chop.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CHOP: Choppiness Index -/// A technical indicator that measures the market's trendiness versus choppiness. -/// It helps determine if the market is trending or moving sideways by comparing -/// the total movement to the net directional movement over a period. -/// -/// -/// The CHOP calculation process: -/// 1. Calculate ATR sum over period -/// 2. Calculate total price range over period -/// 3. Scale result to oscillate between 0 and 100 -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Values above 61.8 indicate choppy market -/// - Values below 38.2 indicate trending market -/// - Based on ATR and price range -/// - Higher values = more choppy/sideways -/// - Lower values = more trending -/// -/// Formula: -/// CHOP = 100 * LOG10(SUM(ATR,n)/(HIGH(n)-LOW(n))) / LOG10(n) -/// where: -/// n = period -/// ATR = Average True Range -/// HIGH(n) = Highest high over period n -/// LOW(n) = Lowest low over period n -/// -/// Sources: -/// E.W. Dreiss -/// https://www.tradingview.com/support/solutions/43000501980-choppiness-index/ -/// -/// Note: Default period is 14 -/// -[SkipLocalsInit] -public sealed class Chop : AbstractBase -{ - private readonly Atr _atr; - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private readonly CircularBuffer _atrValues; - private readonly double _logPeriod; - private const int DefaultPeriod = 14; - private const double ScalingFactor = 100.0; - - /// The number of periods used in the CHOP calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Chop(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _atr = new(period); - _highs = new(period); - _lows = new(period); - _atrValues = new(period); - _logPeriod = Math.Log10(period); - WarmupPeriod = period; - Name = $"CHOP({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the CHOP calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Chop(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate ATR and store it - double atr = _atr.Calc(BarInput); - _atrValues.Add(atr, BarInput.IsNew); - - // Store high and low prices - _highs.Add(BarInput.High, BarInput.IsNew); - _lows.Add(BarInput.Low, BarInput.IsNew); - - // Calculate highest high and lowest low over period - double highestHigh = _highs.Max(); - double lowestLow = _lows.Min(); - double range = highestHigh - lowestLow; - - // Calculate sum of ATR values - double atrSum = _atrValues.Sum(); - - // Avoid division by zero - if (range < double.Epsilon || _logPeriod < double.Epsilon) - return 0.0; - - // Calculate CHOP - return ScalingFactor * Math.Log10(atrSum / range) / _logPeriod; - } -} diff --git a/lib/oscillators/Cmo.cs b/lib/oscillators/Cmo.cs deleted file mode 100644 index 1248d345..00000000 --- a/lib/oscillators/Cmo.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CMO: Chande Momentum Oscillator -/// A technical momentum indicator that measures the difference between upward and -/// downward momentum. CMO helps identify overbought and oversold conditions, as -/// well as trend strength and potential reversals. -/// -/// -/// The CMO calculation process: -/// 1. Calculates price differences from previous period -/// 2. Separates positive (upward) and negative (downward) movements -/// 3. Sums upward and downward movements over period -/// 4. Calculates: 100 * ((sumUp - sumDown) / (sumUp + sumDown)) -/// -/// Key characteristics: -/// - Oscillates between -100 and +100 -/// - Values above +50 indicate overbought -/// - Values below -50 indicate oversold -/// - Zero line crossovers signal trend changes -/// - High absolute values suggest strong trends -/// -/// Formula: -/// CMO = 100 * ((ΣUp - ΣDown) / (ΣUp + ΣDown)) -/// where: -/// Up = positive price changes -/// Down = absolute negative price changes -/// -/// Sources: -/// Tushar Chande - "The New Technical Trader" (1994) -/// https://www.investopedia.com/terms/c/chandemomentumoscillator.asp -/// -/// Note: Similar to RSI but with different scaling and calculation method -/// -[SkipLocalsInit] -public sealed class Cmo : AbstractBase -{ - private readonly CircularBuffer _sumH; - private readonly CircularBuffer _sumL; - private double _prevValue, _p_prevValue; - private const double Epsilon = 1e-10; - private const double ScalingFactor = 100.0; - - /// The number of periods used in the CMO calculation. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cmo(int period) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - _sumH = new(period); - _sumL = new(period); - - WarmupPeriod = period + 1; - Name = $"CMO({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the CMO calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cmo(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevValue = _prevValue; - } - else - { - _prevValue = _p_prevValue; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double up, double down) CalculateMovements(double diff) - { - return diff > 0 ? (diff, 0) : (0, -diff); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateCmo(double sumH, double sumL) - { - double divisor = sumH + sumL; - return (Math.Abs(divisor) > Epsilon) ? ScalingFactor * ((sumH - sumL) / divisor) : 0.0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index == 0) - { - _prevValue = Input.Value; - } - - // Calculate price difference - double diff = Input.Value - _prevValue; - _prevValue = Input.Value; - - // Separate upward and downward movements - var (up, down) = CalculateMovements(diff); - _sumH.Add(up, Input.IsNew); - _sumL.Add(down, Input.IsNew); - - // Calculate sums and CMO value - return CalculateCmo(_sumH.Sum(), _sumL.Sum()); - } -} diff --git a/lib/oscillators/Cog.cs b/lib/oscillators/Cog.cs deleted file mode 100644 index 1ef3889c..00000000 --- a/lib/oscillators/Cog.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// COG: Ehler's Center of Gravity Oscillator -/// A momentum oscillator that uses the concept of center of gravity from physics -/// to measure price momentum. It calculates a weighted sum where more recent -/// prices have higher weights. -/// -/// -/// The COG calculation process: -/// 1. Calculate weighted sum of prices (numerator) -/// 2. Calculate sum of weights (denominator) -/// 3. Divide to get center of gravity -/// 4. Invert and normalize result -/// -/// Key characteristics: -/// - Oscillates around zero -/// - Leading indicator (less lag than traditional momentum) -/// - Positive values indicate upward momentum -/// - Negative values indicate downward momentum -/// - Zero line crossovers signal trend changes -/// -/// Formula: -/// COG = -((Σ(Price(i) * i)) / (Σ(Price(i))) - (period + 1)/2) -/// where: -/// i = position in period (1 to period) -/// Price(i) = price at position i -/// -/// Sources: -/// John F. Ehlers - "Cybernetic Analysis for Stocks and Futures" -/// https://www.mesasoftware.com/papers/CenterOfGravity.pdf -/// -/// Note: Default period is 10 -/// -[SkipLocalsInit] -public sealed class Cog : AbstractBase -{ - private readonly CircularBuffer _prices; - private readonly int _period; - private const int DefaultPeriod = 10; - - /// The number of periods used in the COG calculation (default 10). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cog(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _period = period; - _prices = new(period); - WarmupPeriod = period; - Name = $"COG({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the COG calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cog(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Add new price to buffer - _prices.Add(Input.Value, Input.IsNew); - - double numerator = 0.0; - double denominator = 0.0; - - // Calculate weighted sums - for (int i = 0; i < _prices.Count; i++) - { - double price = _prices[i]; - double weight = i + 1; - numerator += price * weight; - denominator += price; - } - - // Avoid division by zero - if (Math.Abs(denominator) < double.Epsilon) - return 0.0; - - // Calculate center of gravity and normalize - return -((numerator / denominator) - ((_period + 1.0) / 2.0)); - } -} diff --git a/lib/oscillators/Coppock.cs b/lib/oscillators/Coppock.cs deleted file mode 100644 index ed905b4c..00000000 --- a/lib/oscillators/Coppock.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// COPPOCK: Coppock Curve -/// A long-term momentum oscillator used to identify major bottoms in the market. -/// It is calculated using a weighted moving average of two different Rate of Change calculations. -/// -/// -/// The Coppock Curve calculation process: -/// 1. Calculate 14-period Rate of Change (ROC) -/// 2. Calculate 11-period Rate of Change (ROC) -/// 3. Sum the two ROC values -/// 4. Apply 10-period Weighted Moving Average (WMA) to the sum -/// -/// Key characteristics: -/// - Long-term momentum indicator -/// - Primarily used for monthly data -/// - Buy signals when curve turns up from below zero -/// - Rarely used for sell signals -/// - Designed to identify major bottoms in stock market indices -/// -/// Formula: -/// COPPOCK = WMA(10) of (ROC(14) + ROC(11)) -/// where: -/// ROC(n) = ((Price - Price[n]) / Price[n]) * 100 -/// WMA is weighted moving average -/// -/// Sources: -/// Edwin Coppock - Barron's Magazine (October 1962) -/// https://www.investopedia.com/terms/c/coppockcurve.asp -/// -/// Note: Originally designed for monthly data with parameters (14,11,10), -/// but can be adapted for other timeframes -/// -[SkipLocalsInit] -public sealed class Coppock : AbstractBase -{ - private readonly CircularBuffer _values; - private readonly Wma _wma; - private readonly int _roc1Period; - private readonly int _roc2Period; - private const int DefaultRoc1Period = 14; - private const int DefaultRoc2Period = 11; - private const int DefaultWmaPeriod = 10; - - /// The first ROC period (default 14). - /// The second ROC period (default 11). - /// The WMA smoothing period (default 10). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Coppock(int roc1Period = DefaultRoc1Period, int roc2Period = DefaultRoc2Period, int wmaPeriod = DefaultWmaPeriod) - { - ArgumentOutOfRangeException.ThrowIfLessThan(roc1Period, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(roc2Period, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(wmaPeriod, 1); - - _roc1Period = roc1Period; - _roc2Period = roc2Period; - int maxPeriod = Math.Max(roc1Period, roc2Period); - _values = new(maxPeriod + 1); - _wma = new(wmaPeriod); - WarmupPeriod = maxPeriod + wmaPeriod; - Name = $"COPPOCK({roc1Period},{roc2Period},{wmaPeriod})"; - } - - /// The data source object that publishes updates. - /// The first ROC period. - /// The second ROC period. - /// The WMA smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Coppock(object source, int roc1Period = DefaultRoc1Period, int roc2Period = DefaultRoc2Period, int wmaPeriod = DefaultWmaPeriod) - : this(roc1Period, roc2Period, wmaPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _values.Add(Input.Value); - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateRoc(int period) - { - if (_index <= period) return 0; - double currentValue = _values[0]; - double oldValue = _values[period]; - return ((currentValue - oldValue) / oldValue) * 100.0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate ROC values and their sum - double roc1 = CalculateRoc(_roc1Period); - double roc2 = CalculateRoc(_roc2Period); - double rocSum = roc1 + roc2; - - // Not enough data for WMA calculation - if (_index <= Math.Max(_roc1Period, _roc2Period)) - return 0; - - // Calculate WMA of ROC sums - return _wma.Calc(new TValue(Input.Time, rocSum, Input.IsNew)); - } -} diff --git a/lib/oscillators/Crsi.cs b/lib/oscillators/Crsi.cs deleted file mode 100644 index 1d65c9e8..00000000 --- a/lib/oscillators/Crsi.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CRSI: Connor RSI -/// A momentum oscillator that combines three different RSI time periods to provide -/// a more comprehensive view of price momentum. It helps identify overbought and -/// oversold conditions with higher accuracy than traditional RSI. -/// -/// -/// The CRSI calculation process: -/// 1. Calculate three RSIs with different periods (3,2,1) -/// 2. Sum the three RSI values -/// 3. Divide by 3 to get the average -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - More responsive than traditional RSI -/// - Combines multiple timeframes -/// - Traditional overbought level at 90 -/// - Traditional oversold level at 10 -/// -/// Formula: -/// CRSI = (RSI(3) + RSI(2) + RSI(1)) / 3 -/// where each RSI is calculated using standard RSI formula: -/// RSI = 100 - (100 / (1 + RS)) -/// RS = Average Gain / Average Loss -/// -/// Sources: -/// Larry Connors - "Short-term Trading Strategies That Work" -/// https://www.tradingview.com/script/cYk1LVpw-Connors-RSI-LazyBear/ -/// -/// Note: Default periods are 3,2,1 as recommended by Connors -/// -[SkipLocalsInit] -public sealed class Crsi : AbstractBase -{ - private readonly Rsi _rsi3; - private readonly Rsi _rsi2; - private readonly Rsi _rsi1; - private const int DefaultPeriod1 = 3; - private const int DefaultPeriod2 = 2; - private const int DefaultPeriod3 = 1; - - /// The first RSI period (default 3). - /// The second RSI period (default 2). - /// The third RSI period (default 1). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Crsi(int period1 = DefaultPeriod1, int period2 = DefaultPeriod2, int period3 = DefaultPeriod3) - { - if (period1 < 1) - throw new ArgumentOutOfRangeException(nameof(period1), "Period1 must be greater than 0"); - if (period2 < 1) - throw new ArgumentOutOfRangeException(nameof(period2), "Period2 must be greater than 0"); - if (period3 < 1) - throw new ArgumentOutOfRangeException(nameof(period3), "Period3 must be greater than 0"); - - _rsi3 = new(period1); - _rsi2 = new(period2); - _rsi1 = new(period3); - WarmupPeriod = Math.Max(Math.Max(period1, period2), period3) + 1; - Name = $"CRSI({period1},{period2},{period3})"; - } - - /// The data source object that publishes updates. - /// The first RSI period. - /// The second RSI period. - /// The third RSI period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Crsi(object source, int period1 = DefaultPeriod1, int period2 = DefaultPeriod2, int period3 = DefaultPeriod3) - : this(period1, period2, period3) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate individual RSIs - double rsi3 = _rsi3.Calc(Input); - double rsi2 = _rsi2.Calc(Input); - double rsi1 = _rsi1.Calc(Input); - - // Average the three RSIs - return (rsi3 + rsi2 + rsi1) / 3.0; - } -} diff --git a/lib/oscillators/Cti.cs b/lib/oscillators/Cti.cs deleted file mode 100644 index 53b6158f..00000000 --- a/lib/oscillators/Cti.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CTI: Ehler's Correlation Trend Indicator -/// Measures the correlation between price and an ideal trend line. -/// -/// -/// The CTI calculation process: -/// 1. Correlates price curve with an ideal trend line (negative count due to backwards data storage) -/// 2. Uses Spearman's correlation algorithm -/// 3. Returns values between -1 and 1 -/// -/// Key characteristics: -/// - Oscillates between -1 and 1 -/// - Positive values indicate price follows uptrend -/// - Negative values indicate price follows downtrend -/// -/// Formula: -/// CTI = (n∑xy - ∑x∑y) / sqrt((n∑x² - (∑x)²)(n∑y² - (∑y)²)) -/// where: -/// x = price curve -/// y = -count (ideal trend line) -/// n = period length -/// -/// Sources: -/// John Ehlers - "Cybernetic Analysis for Stocks and Futures" (2004) -/// John Ehlers, Correlation Trend Indicator, Stocks & Commodities May-2020 -/// -[SkipLocalsInit] -public sealed class Cti : AbstractBase -{ - private readonly int _period; - private readonly CircularBuffer _priceBuffer; - private readonly double[] _trendLine; - private const int MinimumPoints = 2; // Minimum points needed for correlation - - /// The data source object that publishes updates. - /// The calculation period (default: 20) - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cti(object source, int period = 20) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cti(int period = 20) - { - _period = period; - _priceBuffer = new CircularBuffer(period); - - // Pre-calculate trend line values since they're static - _trendLine = new double[period]; - for (int i = 0; i < period; i++) - { - _trendLine[i] = -i; // negative count for backwards data - } - - WarmupPeriod = period; - Name = "CTI"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _priceBuffer.Add(Input.Value, Input.IsNew); - - // Use available points for early calculations - int points = Math.Min(_index + 1, _period); - if (points < MinimumPoints) return 0; // Need at least 2 points for correlation - - double sx = 0, sy = 0, sxx = 0, sxy = 0, syy = 0; - - // Calculate correlation components using available points - for (int i = 0; i < points; i++) - { - double x = _priceBuffer[i]; // price curve - double y = _trendLine[i]; // pre-calculated trend line - - sx += x; - sy += y; - sxx += x * x; - sxy += x * y; - syy += y * y; - } - - // Check for numerical stability - double denomX = (points * sxx) - (sx * sx); - double denomY = (points * syy) - (sy * sy); - - if (denomX > 0 && denomY > 0) - { - return ((points * sxy) - (sx * sy)) / Math.Sqrt(denomX * denomY); - } - - return 0; - } -} diff --git a/lib/oscillators/Dosc.cs b/lib/oscillators/Dosc.cs deleted file mode 100644 index 906b2288..00000000 --- a/lib/oscillators/Dosc.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DOSC: Derivative Oscillator -/// A momentum indicator that combines the Relative Strength Index (RSI) and the Moving Average Convergence Divergence (MACD) to identify potential trend reversals. -/// -/// -/// The DOSC calculation process: -/// 1. Calculate the RSI -/// 2. Calculate the MACD of the RSI -/// 3. Calculate the signal line (SMA) of the MACD -/// 4. Subtract the signal line from the MACD to get the DOSC -/// -/// Key characteristics: -/// - Combines RSI and MACD -/// - Oscillates above and below zero -/// - Positive values indicate bullish momentum -/// - Negative values indicate bearish momentum -/// - Crosses above zero suggest buying opportunities -/// - Crosses below zero suggest selling opportunities -/// -/// Formula: -/// DOSC = MACD(RSI) - Signal(MACD(RSI)) -/// -/// Sources: -/// Original development -/// https://www.investopedia.com/terms/d/derivativeoscillator.asp -/// -[SkipLocalsInit] -public sealed class Dosc : AbstractBase -{ - private readonly Rsi _rsi; - private readonly Macd _macd; - private readonly Sma _signal; - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dosc(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dosc() - { - _rsi = new Rsi(); - _macd = new Macd(); - _signal = new Sma(9); - WarmupPeriod = 34; // RSI requires 14 periods + MACD requires 26 periods + 9 for signal line - Name = "DOSC"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - var rsi = _rsi.Calc(BarInput.Close, BarInput.IsNew); - var macd = _macd.Calc(rsi, BarInput.IsNew); - _signal.Calc(macd, BarInput.IsNew); - - return macd - _signal.Value; - } -} diff --git a/lib/oscillators/Efi.cs b/lib/oscillators/Efi.cs deleted file mode 100644 index d2f6d9f5..00000000 --- a/lib/oscillators/Efi.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// EFI: Elder Ray's Force Index -/// A volume-based oscillator that measures the strength of price movements using volume. -/// It helps identify potential trend reversals and confirm price movements. -/// -/// -/// The EFI calculation process: -/// 1. Calculate the difference between the current close and the previous close -/// 2. Multiply the difference by the current volume -/// 3. Apply an exponential moving average (EMA) to smooth the result -/// -/// Key characteristics: -/// - Oscillates above and below zero -/// - Positive values indicate buying pressure -/// - Negative values indicate selling pressure -/// - Crosses above zero suggest buying opportunities -/// - Crosses below zero suggest selling opportunities -/// -/// Formula: -/// EFI = EMA((Close - Close[1]) * Volume, period) -/// -/// Sources: -/// Alexander Elder - "Trading for a Living" (1993) -/// https://www.investopedia.com/terms/f/force-index.asp -/// -/// Note: Default period is 13 -/// -[SkipLocalsInit] -public sealed class Efi : AbstractBase -{ - private readonly Ema _ema; - private double _prevClose; - private double _p_prevClose; - private const int DefaultPeriod = 13; - - /// The smoothing period for EMA calculation (default 13). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Efi(int period = DefaultPeriod) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - _ema = new(period); - WarmupPeriod = period + 1; - Name = $"EFI({period})"; - } - - /// The data source object that publishes updates. - /// The smoothing period for EMA calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Efi(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _ema.Init(); - _prevClose = double.NaN; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevClose = _prevClose; - } - else - { - _prevClose = _p_prevClose; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate raw force index - double priceChange = BarInput.Close - _prevClose; - double forceIndex = priceChange * BarInput.Volume; - - // Update previous close - _prevClose = BarInput.Close; - - // Apply EMA smoothing - return _ema.Calc(forceIndex, BarInput.IsNew); - } -} diff --git a/lib/oscillators/Fisher.cs b/lib/oscillators/Fisher.cs deleted file mode 100644 index aadd5383..00000000 --- a/lib/oscillators/Fisher.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// FISHER: Fisher Transform -/// A technical indicator that converts prices into a Gaussian normal distribution. -/// -/// -/// The Fisher Transform calculation process: -/// 1. Calculate the value of the price relative to its high-low range. -/// 2. Apply the Fisher Transform formula to the normalized price. -/// 3. Smooth the result using an exponential moving average. -/// -/// Key characteristics: -/// - Oscillates between -1 and 1 -/// - Emphasizes price reversals -/// - Can be used to identify overbought and oversold conditions -/// -/// Formula: -/// Fisher Transform = 0.5 * log((1 + x) / (1 - x)) -/// where: -/// x = 2 * ((price - min) / (max - min) - 0.5) -/// -/// Sources: -/// John F. Ehlers - "Rocket Science for Traders" (2001) -/// https://www.investopedia.com/terms/f/fisher-transform.asp -/// -[SkipLocalsInit] -public sealed class Fisher : AbstractBase -{ - private readonly int _period; - private readonly double[] _prices; - private double _prevFisher; - - /// The data source object that publishes updates. - /// The calculation period (default: 10) - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Fisher(object source, int period = 10) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Fisher(int period = 10) - { - _period = period; - _prices = new double[period]; - WarmupPeriod = period; - Name = "FISHER"; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double NormalizePrice(double price, double min, double max) - { - return 2 * (((price - min) / (max - min)) - 0.5); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double FisherTransform(double value) - { - return 0.5 * System.Math.Log((1 + value) / (1 - value)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - var idx = _index % _period; - _prices[idx] = Input.Value; - - if (_index < _period - 1) return double.NaN; - - var min = _prices.Min(); - var max = _prices.Max(); - var normalizedPrice = NormalizePrice(Input.Value, min, max); - var fisherValue = FisherTransform(normalizedPrice); - - var smoothedFisher = 0.5 * (fisherValue + _prevFisher); - _prevFisher = smoothedFisher; - - return smoothedFisher; - } -} diff --git a/lib/oscillators/Rsi.cs b/lib/oscillators/Rsi.cs deleted file mode 100644 index 3db9f953..00000000 --- a/lib/oscillators/Rsi.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RSI: Relative Strength Index -/// A momentum oscillator that measures the speed and magnitude of recent price -/// changes to evaluate overbought or oversold conditions. RSI compares the -/// magnitude of recent gains to recent losses. -/// -/// -/// The RSI calculation process: -/// 1. Calculates price changes from previous period -/// 2. Separates gains and losses -/// 3. Calculates average gain and loss using Wilder's smoothing -/// 4. Computes relative strength (avg gain / avg loss) -/// 5. Normalizes to 0-100 scale: 100 - (100 / (1 + RS)) -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Traditional overbought level at 70 -/// - Traditional oversold level at 30 -/// - Centerline (50) crossovers signal trend changes -/// - Divergences suggest potential reversals -/// -/// Formula: -/// RSI = 100 - (100 / (1 + RS)) -/// where: -/// RS = Average Gain / Average Loss -/// Average Gain/Loss = Wilder's smoothed average over period -/// -/// Sources: -/// J. Welles Wilder Jr. - "New Concepts in Technical Trading Systems" (1978) -/// https://www.investopedia.com/terms/r/rsi.asp -/// -/// Note: Default period of 14 was recommended by Wilder -/// -[SkipLocalsInit] -public sealed class Rsi : AbstractBase -{ - private readonly Rma _avgGain; - private readonly Rma _avgLoss; - private double _prevValue, _p_prevValue; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 14; - - /// The number of periods used in the RSI calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsi(int period = DefaultPeriod) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - _avgGain = new(period, useSma: true); - _avgLoss = new(period, useSma: true); - _index = 0; - WarmupPeriod = period + 1; - Name = $"RSI({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods used in the RSI calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsi(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevValue = _prevValue; - } - else - { - _prevValue = _p_prevValue; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double gain, double loss) CalculateGainLoss(double change) - { - return (Math.Max(change, 0), Math.Max(-change, 0)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateRsi(double avgGain, double avgLoss) - { - return avgLoss > 0 ? ScalingFactor - (ScalingFactor / (1 + (avgGain / avgLoss))) : ScalingFactor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index == 1) - { - _prevValue = Input.Value; - } - - // Calculate price change and separate gains/losses - double change = Input.Value - _prevValue; - var (gain, loss) = CalculateGainLoss(change); - _prevValue = Input.Value; - - // Calculate smoothed averages using Wilder's method - _avgGain.Calc(gain, Input.IsNew); - _avgLoss.Calc(loss, Input.IsNew); - - // Calculate RSI - return CalculateRsi(_avgGain.Value, _avgLoss.Value); - } -} diff --git a/lib/oscillators/Rsx.cs b/lib/oscillators/Rsx.cs deleted file mode 100644 index f8921e96..00000000 --- a/lib/oscillators/Rsx.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RSX: Relative Strength eXtended -/// An enhanced version of RSI developed by Mark Jurik that applies JMA (Jurik Moving -/// Average) smoothing to the RSI calculation. RSX provides smoother signals with -/// less noise while maintaining responsiveness to significant price movements. -/// -/// -/// The RSX calculation process: -/// 1. Calculates traditional RSI values -/// 2. Applies JMA smoothing to RSI output -/// 3. Uses optimized parameters for noise reduction -/// 4. Maintains RSI's 0-100 scale -/// -/// Key characteristics: -/// - Smoother than traditional RSI -/// - Better noise reduction -/// - Maintains responsiveness to significant moves -/// - Same interpretation as RSI (0-100 scale) -/// - Fewer false signals than RSI -/// -/// Formula: -/// RSX = JMA(RSI(price)) -/// where: -/// RSI = standard Relative Strength Index -/// JMA = Jurik Moving Average with optimized parameters -/// -/// Sources: -/// Mark Jurik - "The Jurik RSX" -/// https://www.jurikresearch.com/ -/// -/// Note: Proprietary enhancement of RSI using JMA technology -/// -[SkipLocalsInit] -public sealed class Rsx : AbstractBase -{ - private readonly Rma _avgGain; - private readonly Rma _avgLoss; - private readonly Jma _rsx; - private double _prevValue, _p_prevValue; - private const double ScalingFactor = 100.0; - private const int DefaultPeriod = 14; - private const int DefaultPhase = 0; - private const double DefaultFactor = 0.55; - private const int JmaPeriod = 8; - private const int JmaPower = 100; - private const double JmaPhase = 0.25; - private const int JmaExtra = 3; - - /// The number of periods for RSI calculation (default 14). - /// The phase parameter for JMA smoothing (default 0). - /// The factor parameter for smoothing control (default 0.55). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsx(int period = DefaultPeriod, int phase = DefaultPhase, double factor = DefaultFactor) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - _avgGain = new(period); - _avgLoss = new(period); - _rsx = new(JmaPeriod, JmaPower, JmaPhase, JmaExtra); - _index = 0; - WarmupPeriod = period + 1; - Name = $"RSX({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for RSI calculation. - /// The phase parameter for JMA smoothing. - /// The factor parameter for smoothing control. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsx(object source, int period, int phase = DefaultPhase, double factor = DefaultFactor) : this(period, phase, factor) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevValue = _prevValue; - } - else - { - _prevValue = _p_prevValue; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double gain, double loss) CalculateGainLoss(double change) - { - return (Math.Max(change, 0), Math.Max(-change, 0)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateRsi(double avgGain, double avgLoss) - { - return avgLoss > 0 ? ScalingFactor - (ScalingFactor / (1 + (avgGain / avgLoss))) : ScalingFactor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - if (_index == 1) - { - _prevValue = Input.Value; - } - - // Calculate RSI components - double change = Input.Value - _prevValue; - var (gain, loss) = CalculateGainLoss(change); - _prevValue = Input.Value; - - // Calculate RSI - _avgGain.Calc(gain, Input.IsNew); - _avgLoss.Calc(loss, Input.IsNew); - double rsi = CalculateRsi(_avgGain.Value, _avgLoss.Value); - - // Apply JMA smoothing - _rsx.Calc(rsi, Input.IsNew); - - return _rsx.Value; - } -} diff --git a/lib/oscillators/Smi.cs b/lib/oscillators/Smi.cs deleted file mode 100644 index 989218d1..00000000 --- a/lib/oscillators/Smi.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SMI: Stochastic Momentum Index -/// A double-smoothed momentum indicator that shows where the close is relative -/// to the midpoint of the recent high/low range. It helps identify overbought -/// and oversold conditions with higher accuracy than traditional stochastics. -/// -/// -/// The SMI calculation process: -/// 1. Calculate median price distance (Close - (High + Low)/2) -/// 2. Calculate highest high and lowest low over period -/// 3. First smoothing of median distance and range -/// 4. Second smoothing of first smoothed values -/// 5. Scale to percentage (-100 to +100) -/// -/// Key characteristics: -/// - Oscillates between -100 and +100 -/// - Double smoothing reduces noise -/// - Traditional overbought level at +40 -/// - Traditional oversold level at -40 -/// - Centerline crossovers signal trend changes -/// -/// Formula: -/// D = Close - (High + Low)/2 -/// HL = Highest High - Lowest Low -/// First smoothing: -/// SD = EMA(EMA(D, period1), period2) -/// SHL = EMA(EMA(HL, period1), period2) -/// SMI = 100 * (SD / (SHL/2)) -/// -/// Sources: -/// William Blau - "Momentum, Direction, and Divergence" (1995) -/// https://www.tradingview.com/scripts/stochasticmomentumindex/ -/// -/// Note: Default periods (10,3,3) are commonly used values -/// -[SkipLocalsInit] -public sealed class Smi : AbstractBase -{ - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private readonly Ema _dEma1; - private readonly Ema _dEma2; - private readonly Ema _hlEma1; - private readonly Ema _hlEma2; - private const int DefaultPeriod = 10; - private const int DefaultSmooth1 = 3; - private const int DefaultSmooth2 = 3; - private const double ScalingFactor = 100.0; - - /// The lookback period (default 10). - /// First smoothing period (default 3). - /// Second smoothing period (default 3). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Smi(int period = DefaultPeriod, int smooth1 = DefaultSmooth1, int smooth2 = DefaultSmooth2) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(smooth1, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(smooth2, 1); - - _highs = new(period); - _lows = new(period); - _dEma1 = new(smooth1); - _dEma2 = new(smooth2); - _hlEma1 = new(smooth1); - _hlEma2 = new(smooth2); - WarmupPeriod = period + smooth1 + smooth2; - Name = $"SMI({period},{smooth1},{smooth2})"; - } - - /// The data source object that publishes updates. - /// The lookback period. - /// First smoothing period. - /// Second smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Smi(object source, int period = DefaultPeriod, int smooth1 = DefaultSmooth1, int smooth2 = DefaultSmooth2) - : this(period, smooth1, smooth2) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate median price distance and range - double midpoint = (BarInput.High + BarInput.Low) / 2.0; - double distance = BarInput.Close - midpoint; - double range = _highs.Max() - _lows.Min(); - - // First smoothing - double smoothD1 = _dEma1.Calc(new TValue(BarInput.Time, distance, BarInput.IsNew)); - double smoothHL1 = _hlEma1.Calc(new TValue(BarInput.Time, range, BarInput.IsNew)); - - // Second smoothing - double smoothD2 = _dEma2.Calc(new TValue(BarInput.Time, smoothD1, BarInput.IsNew)); - double smoothHL2 = _hlEma2.Calc(new TValue(BarInput.Time, smoothHL1, BarInput.IsNew)); - - // Calculate SMI - return smoothHL2 >= double.Epsilon ? ScalingFactor * (smoothD2 / (smoothHL2 / 2.0)) : 0; - } -} diff --git a/lib/oscillators/Srsi.cs b/lib/oscillators/Srsi.cs deleted file mode 100644 index bdb2c3df..00000000 --- a/lib/oscillators/Srsi.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SRSI: Stochastic RSI -/// A momentum oscillator that applies the stochastic formula to RSI values -/// instead of price data. It provides a more sensitive indicator than standard -/// RSI or Stochastic oscillators. -/// -/// -/// The SRSI calculation process: -/// 1. Calculate RSI -/// 2. Apply Stochastic formula to RSI values: -/// - Find highest high and lowest low of RSI over period -/// - Calculate where current RSI is within this range -/// 3. Smooth the result with SMA (signal line) -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - More sensitive than standard RSI -/// - Combines benefits of both RSI and Stochastic -/// - Traditional overbought level at 80 -/// - Traditional oversold level at 20 -/// -/// Formula: -/// SRSI = ((RSI - Lowest RSI) / (Highest RSI - Lowest RSI)) * 100 -/// Signal = SMA(SRSI, signalPeriod) -/// -/// Sources: -/// Tushar Chande and Stanley Kroll - "The New Technical Trader" (1994) -/// https://www.investopedia.com/terms/s/stochrsi.asp -/// -/// Note: Default periods (14,14,3,3) are commonly used values -/// -[SkipLocalsInit] -public sealed class Srsi : AbstractBase -{ - private readonly Rsi _rsi; - private readonly CircularBuffer _rsiValues; - private readonly CircularBuffer _srsiValues; - private readonly Sma _signal; - private readonly int _rsiPeriod; - private const int DefaultRsiPeriod = 14; - private const int DefaultStochPeriod = 14; - private const int DefaultSmoothK = 3; - private const int DefaultSmoothD = 3; - private const double ScalingFactor = 100.0; - - /// The RSI period (default 14). - /// The Stochastic period (default 14). - /// K line smoothing period (default 3). - /// D line smoothing period (default 3). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Srsi(int rsiPeriod = DefaultRsiPeriod, int stochPeriod = DefaultStochPeriod, - int smoothK = DefaultSmoothK, int smoothD = DefaultSmoothD) - { - ArgumentOutOfRangeException.ThrowIfLessThan(rsiPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(stochPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(smoothK, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(smoothD, 1); - - _rsiPeriod = rsiPeriod; - _rsi = new(rsiPeriod); - _rsiValues = new(stochPeriod); - _srsiValues = new(smoothK); - _signal = new(smoothD); - WarmupPeriod = rsiPeriod + stochPeriod + Math.Max(smoothK, smoothD); - Name = $"SRSI({rsiPeriod},{stochPeriod},{smoothK},{smoothD})"; - } - - /// The data source object that publishes updates. - /// The RSI period. - /// The Stochastic period. - /// K line smoothing period. - /// D line smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Srsi(object source, int rsiPeriod = DefaultRsiPeriod, int stochPeriod = DefaultStochPeriod, - int smoothK = DefaultSmoothK, int smoothD = DefaultSmoothD) - : this(rsiPeriod, stochPeriod, smoothK, smoothD) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate RSI - double rsiValue = _rsi.Calc(Input); - - if (Input.IsNew) - _rsiValues.Add(rsiValue); - - // Not enough data - if (_index <= _rsiPeriod) - return 0; - - // Calculate Stochastic RSI - double highest = _rsiValues.Max(); - double lowest = _rsiValues.Min(); - double range = highest - lowest; - double srsi = range >= double.Epsilon ? ((rsiValue - lowest) / range) * ScalingFactor : 0; - - if (Input.IsNew) - _srsiValues.Add(srsi); - - // Calculate signal line - return _signal.Calc(new TValue(Input.Time, srsi, Input.IsNew)); - } - - /// - /// Gets the K line value (raw Stochastic RSI) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double K() => _srsiValues[0]; - - /// - /// Gets the D line value (signal line) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double D() => Value; -} diff --git a/lib/oscillators/Stc.cs b/lib/oscillators/Stc.cs deleted file mode 100644 index 8b755952..00000000 --- a/lib/oscillators/Stc.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// STC: Schaff Trend Cycle -/// A trend-following indicator that combines MACD and stochastic concepts -/// to create a smoother, more responsive indicator with less noise. -/// -/// -/// The STC calculation process: -/// 1. Calculate MACD-style momentum using EMAs -/// 2. Apply double stochastic formula to smooth the momentum -/// 3. Scale result to oscillator range -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Combines trend and momentum -/// - Double smoothing reduces noise -/// - Traditional overbought level at 75 -/// - Traditional oversold level at 25 -/// -/// Formula: -/// Momentum = EMA1(Close) - EMA2(Close) -/// First Stochastic: -/// %K1 = 100 * (Momentum - Lowest Low) / (Highest High - Lowest Low) -/// %D1 = EMA(%K1) -/// Second Stochastic: -/// %K2 = 100 * (%D1 - Lowest %D1) / (Highest %D1 - Lowest %D1) -/// STC = EMA(%K2) -/// -/// Sources: -/// Doug Schaff - "The Schaff Trend Cycle" (1999) -/// https://www.tradingview.com/script/o6tSS6Hn-Schaff-Trend-Cycle/ -/// -/// Note: Default periods (23,10,3) were recommended by Schaff -/// -[SkipLocalsInit] -public sealed class Stc : AbstractBase -{ - private readonly Ema _fastEma; - private readonly Ema _slowEma; - private readonly CircularBuffer _macdValues; - private readonly CircularBuffer _k1Values; - private readonly CircularBuffer _d1Values; - private readonly Ema _d1Ema; - private readonly Ema _stcEma; - private const int DefaultCyclePeriod = 10; - private const int DefaultFastPeriod = 23; - private const int DefaultSlowPeriod = 50; - private const int DefaultD1Period = 3; - private const int DefaultStcPeriod = 3; - private const double ScalingFactor = 100.0; - - /// The lookback period for highs/lows (default 10). - /// Fast EMA period (default 23). - /// Slow EMA period (default 50). - /// First %D smoothing period (default 3). - /// Final STC smoothing period (default 3). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Stc(int cyclePeriod = DefaultCyclePeriod, int fastPeriod = DefaultFastPeriod, - int slowPeriod = DefaultSlowPeriod, int d1Period = DefaultD1Period, - int stcPeriod = DefaultStcPeriod) - { - ArgumentOutOfRangeException.ThrowIfLessThan(cyclePeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(fastPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(slowPeriod, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(d1Period, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(stcPeriod, 1); - - if (fastPeriod >= slowPeriod) - { - throw new ArgumentOutOfRangeException(nameof(fastPeriod), "Fast period must be less than slow period"); - } - - _fastEma = new(fastPeriod); - _slowEma = new(slowPeriod); - _macdValues = new(cyclePeriod); - _k1Values = new(cyclePeriod); - _d1Values = new(cyclePeriod); - _d1Ema = new(d1Period); - _stcEma = new(stcPeriod); - - WarmupPeriod = slowPeriod + cyclePeriod + Math.Max(d1Period, stcPeriod); - Name = $"STC({cyclePeriod},{fastPeriod},{slowPeriod},{d1Period},{stcPeriod})"; - } - - /// The data source object that publishes updates. - /// The lookback period for highs/lows. - /// Fast EMA period. - /// Slow EMA period. - /// First %D smoothing period. - /// Final STC smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Stc(object source, int cyclePeriod = DefaultCyclePeriod, int fastPeriod = DefaultFastPeriod, - int slowPeriod = DefaultSlowPeriod, int d1Period = DefaultD1Period, - int stcPeriod = DefaultStcPeriod) - : this(cyclePeriod, fastPeriod, slowPeriod, d1Period, stcPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateStochastic(double value, double highest, double lowest) - { - double range = highest - lowest; - return range >= double.Epsilon ? ((value - lowest) / range) * ScalingFactor : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate MACD-style momentum - double fastEma = _fastEma.Calc(Input); - double slowEma = _slowEma.Calc(Input); - double macd = fastEma - slowEma; - - if (Input.IsNew) - _macdValues.Add(macd); - - // First stochastic - double k1 = CalculateStochastic(macd, _macdValues.Max(), _macdValues.Min()); - if (Input.IsNew) - _k1Values.Add(k1); - - double d1 = _d1Ema.Calc(new TValue(Input.Time, k1, Input.IsNew)); - if (Input.IsNew) - _d1Values.Add(d1); - - // Second stochastic - double k2 = CalculateStochastic(d1, _d1Values.Max(), _d1Values.Min()); - - // Final smoothing - return _stcEma.Calc(new TValue(Input.Time, k2, Input.IsNew)); - } -} diff --git a/lib/oscillators/Stoch.cs b/lib/oscillators/Stoch.cs deleted file mode 100644 index 1f5d30a0..00000000 --- a/lib/oscillators/Stoch.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// STOCH: Stochastic Oscillator -/// A momentum indicator that shows the location of the close relative to -/// high-low range over a period. Consists of %K (fast) and %D (slow) lines. -/// -/// -/// The Stochastic calculation process: -/// 1. Calculate %K (raw stochastic): -/// - Find highest high and lowest low over period -/// - Calculate where current close is within this range -/// 2. Smooth %K with SMA to get Fast %K -/// 3. Smooth Fast %K with SMA to get %D (signal line) -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Traditional overbought level at 80 -/// - Traditional oversold level at 20 -/// - %K/%D crossovers signal momentum shifts -/// - Divergence with price shows potential reversals -/// -/// Formula: -/// Raw %K = 100 * (Close - Lowest Low) / (Highest High - Lowest Low) -/// Fast %K = SMA(Raw %K, smoothK) -/// %D = SMA(Fast %K, smoothD) -/// -/// Sources: -/// George Lane - "Lane's Stochastics" (1950s) -/// https://www.investopedia.com/terms/s/stochasticoscillator.asp -/// -/// Note: Default periods (14,3,3) are commonly used values -/// -[SkipLocalsInit] -public sealed class Stoch : AbstractBase -{ - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private readonly Sma _fastK; - private readonly Sma _slowD; - private readonly CircularBuffer _rawK; - private const int DefaultPeriod = 14; - private const int DefaultSmoothK = 3; - private const int DefaultSmoothD = 3; - private const double ScalingFactor = 100.0; - - /// The lookback period (default 14). - /// %K smoothing period (default 3). - /// %D smoothing period (default 3). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Stoch(int period = DefaultPeriod, int smoothK = DefaultSmoothK, int smoothD = DefaultSmoothD) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(smoothK, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(smoothD, 1); - - _highs = new(period); - _lows = new(period); - _rawK = new(smoothK); - _fastK = new(smoothK); - _slowD = new(smoothD); - WarmupPeriod = period + Math.Max(smoothK, smoothD); - Name = $"STOCH({period},{smoothK},{smoothD})"; - } - - /// The data source object that publishes updates. - /// The lookback period. - /// %K smoothing period. - /// %D smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Stoch(object source, int period = DefaultPeriod, int smoothK = DefaultSmoothK, int smoothD = DefaultSmoothD) - : this(period, smoothK, smoothD) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate raw %K - double highest = _highs.Max(); - double lowest = _lows.Min(); - double range = highest - lowest; - double rawK = range >= double.Epsilon ? ((BarInput.Close - lowest) / range) * ScalingFactor : 0; - - if (BarInput.IsNew) - _rawK.Add(rawK); - - // Calculate Fast %K (first smoothing) - double fastK = _fastK.Calc(new TValue(BarInput.Time, rawK, BarInput.IsNew)); - - // Calculate %D (second smoothing) - return _slowD.Calc(new TValue(BarInput.Time, fastK, BarInput.IsNew)); - } - - /// - /// Gets the %K line value (Fast Stochastic) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double K() => _fastK.Value; - - /// - /// Gets the %D line value (Slow Stochastic) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double D() => Value; -} diff --git a/lib/oscillators/Tsi.cs b/lib/oscillators/Tsi.cs deleted file mode 100644 index 98f214ea..00000000 --- a/lib/oscillators/Tsi.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TSI: True Strength Index -/// A momentum oscillator that shows both trend direction and overbought/oversold conditions. -/// Uses two EMAs of price change momentum to help identify short-term trends and reversals. -/// -/// -/// The TSI calculation process: -/// 1. Calculate price change (PC): Current close - Previous close -/// 2. Calculate absolute price change (APC): Absolute value of PC -/// 3. First smoothing: EMA1 of PC and EMA1 of APC -/// 4. Second smoothing: EMA2 of EMA1(PC) and EMA2 of EMA1(APC) -/// 5. TSI = 100 * (Double smoothed PC / Double smoothed APC) -/// -/// Key characteristics: -/// - Oscillates around zero -/// - Shows momentum and trend direction -/// - Identifies overbought/oversold conditions -/// - Generates signals through centerline/signal line crossovers -/// - Shows momentum divergence with price -/// -/// Formula: -/// TSI = 100 * (EMA2(EMA1(PC)) / EMA2(EMA1(APC))) -/// where: -/// PC = Current Price - Previous Price -/// APC = |PC| -/// Default periods: First EMA = 25, Second EMA = 13 -/// -/// Sources: -/// William Blau - "Momentum, Direction, and Divergence" (1995) -/// https://www.investopedia.com/terms/t/tsi.asp -/// -/// Note: Default periods (25,13) were recommended by Blau -/// -[SkipLocalsInit] -public sealed class Tsi : AbstractBase -{ - private readonly Ema _pcEma1; - private readonly Ema _pcEma2; - private readonly Ema _apcEma1; - private readonly Ema _apcEma2; - private double _prevPrice; - private const int DefaultFirstPeriod = 25; - private const int DefaultSecondPeriod = 13; - private const double ScalingFactor = 100.0; - - /// The first EMA smoothing period (default 25). - /// The second EMA smoothing period (default 13). - /// Thrown when any period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tsi(int firstPeriod = DefaultFirstPeriod, int secondPeriod = DefaultSecondPeriod) - { - if (firstPeriod < 1 || secondPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(firstPeriod), "All periods must be greater than 0"); - - _pcEma1 = new(firstPeriod); - _pcEma2 = new(secondPeriod); - _apcEma1 = new(firstPeriod); - _apcEma2 = new(secondPeriod); - WarmupPeriod = firstPeriod + secondPeriod; - Name = $"TSI({firstPeriod},{secondPeriod})"; - } - - /// The data source object that publishes updates. - /// The first EMA smoothing period. - /// The second EMA smoothing period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tsi(object source, int firstPeriod = DefaultFirstPeriod, int secondPeriod = DefaultSecondPeriod) - : this(firstPeriod, secondPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - if (_index == 0) - _prevPrice = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Calculate price changes - double priceChange = Input.Value - _prevPrice; - double absPriceChange = Math.Abs(priceChange); - - if (Input.IsNew) - _prevPrice = Input.Value; - - // First smoothing - double smoothPc = _pcEma1.Calc(new TValue(Input.Time, priceChange, Input.IsNew)); - double smoothApc = _apcEma1.Calc(new TValue(Input.Time, absPriceChange, Input.IsNew)); - - // Second smoothing - double doubleSmoothedPc = _pcEma2.Calc(new TValue(Input.Time, smoothPc, Input.IsNew)); - double doubleSmoothedApc = _apcEma2.Calc(new TValue(Input.Time, smoothApc, Input.IsNew)); - - // Calculate TSI - return doubleSmoothedApc >= double.Epsilon ? ScalingFactor * (doubleSmoothedPc / doubleSmoothedApc) : 0; - } -} diff --git a/lib/oscillators/Uo.cs b/lib/oscillators/Uo.cs deleted file mode 100644 index 38a98129..00000000 --- a/lib/oscillators/Uo.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// UO: Ultimate Oscillator -/// A momentum oscillator that uses three different time periods to reduce volatility -/// and false signals. It incorporates a weighted average of three oscillator calculations -/// using different periods. -/// -/// -/// The UO calculation process: -/// 1. Calculate buying pressure (BP): Close - Min(Low, Prior Close) -/// 2. Calculate true range (TR): Max(High, Prior Close) - Min(Low, Prior Close) -/// 3. Calculate average of BP/TR for each period -/// 4. Apply weights to each period's average -/// 5. Scale result to oscillator range -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Uses multiple timeframes to reduce false signals -/// - Weighted sum of three periods -/// - Traditional overbought level at 70 -/// - Traditional oversold level at 30 -/// -/// Formula: -/// UO = 100 * ((4 * Average7) + (2 * Average14) + Average28) / (4 + 2 + 1) -/// where: -/// Average7 = 7-period average of BP/TR -/// Average14 = 14-period average of BP/TR -/// Average28 = 28-period average of BP/TR -/// -/// Sources: -/// Larry Williams - "New Trading Dimensions" (1998) -/// https://www.investopedia.com/terms/u/ultimateoscillator.asp -/// -/// Note: Default periods (7,14,28) and weights (4,2,1) were recommended by Williams -/// -[SkipLocalsInit] -public sealed class Uo : AbstractBase -{ - private readonly CircularBuffer _bp1; - private readonly CircularBuffer _tr1; - private readonly CircularBuffer _bp2; - private readonly CircularBuffer _tr2; - private readonly CircularBuffer _bp3; - private readonly CircularBuffer _tr3; - private readonly double _weight1; - private readonly double _weight2; - private readonly double _weight3; - private double _prevClose; - private const int DefaultPeriod1 = 7; - private const int DefaultPeriod2 = 14; - private const int DefaultPeriod3 = 28; - private const double DefaultWeight1 = 4.0; - private const double DefaultWeight2 = 2.0; - private const double DefaultWeight3 = 1.0; - private const double ScalingFactor = 100.0; - - /// The first period (default 7). - /// The second period (default 14). - /// The third period (default 28). - /// Weight for first period (default 4). - /// Weight for second period (default 2). - /// Weight for third period (default 1). - /// Thrown when any period is less than 1 or any weight is less than or equal to 0. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Uo(int period1 = DefaultPeriod1, int period2 = DefaultPeriod2, int period3 = DefaultPeriod3, - double weight1 = DefaultWeight1, double weight2 = DefaultWeight2, double weight3 = DefaultWeight3) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period1, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(period2, 1); - ArgumentOutOfRangeException.ThrowIfLessThan(period3, 1); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(weight1, 0); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(weight2, 0); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(weight3, 0); - - _weight1 = weight1; - _weight2 = weight2; - _weight3 = weight3; - - _bp1 = new(period1); - _tr1 = new(period1); - _bp2 = new(period2); - _tr2 = new(period2); - _bp3 = new(period3); - _tr3 = new(period3); - - WarmupPeriod = period3; - Name = $"UO({period1},{period2},{period3})"; - } - - /// The data source object that publishes updates. - /// The first period. - /// The second period. - /// The third period. - /// Weight for first period. - /// Weight for second period. - /// Weight for third period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Uo(object source, int period1 = DefaultPeriod1, int period2 = DefaultPeriod2, int period3 = DefaultPeriod3, - double weight1 = DefaultWeight1, double weight2 = DefaultWeight2, double weight3 = DefaultWeight3) - : this(period1, period2, period3, weight1, weight2, weight3) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - if (_index == 0) - _prevClose = BarInput.Close; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateAverage(CircularBuffer bp, CircularBuffer tr) - { - double trSum = tr.Sum(); - return trSum >= double.Epsilon ? bp.Sum() / trSum : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate buying pressure and true range - double minLowPrevClose = Math.Min(BarInput.Low, _prevClose); - double maxHighPrevClose = Math.Max(BarInput.High, _prevClose); - double bp = BarInput.Close - minLowPrevClose; - double tr = maxHighPrevClose - minLowPrevClose; - - if (BarInput.IsNew) - { - // Add values to buffers - _bp1.Add(bp); - _tr1.Add(tr); - _bp2.Add(bp); - _tr2.Add(tr); - _bp3.Add(bp); - _tr3.Add(tr); - _prevClose = BarInput.Close; - } - - // Not enough data - if (_index <= 1) return 0; - - // Calculate averages for each period - double avg1 = CalculateAverage(_bp1, _tr1); - double avg2 = CalculateAverage(_bp2, _tr2); - double avg3 = CalculateAverage(_bp3, _tr3); - - // Calculate weighted sum - double weightSum = _weight1 + _weight2 + _weight3; - return ScalingFactor * (((_weight1 * avg1) + (_weight2 * avg2) + (_weight3 * avg3)) / weightSum); - } -} diff --git a/lib/oscillators/Willr.cs b/lib/oscillators/Willr.cs deleted file mode 100644 index cb0beb84..00000000 --- a/lib/oscillators/Willr.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// WILLR: Williams %R -/// A momentum oscillator that measures the level of the close relative to the -/// highest high for a look-back period. Similar to Stochastic Oscillator but -/// with a reversed scale and no smoothing. -/// -/// -/// The Williams %R calculation process: -/// 1. Find highest high and lowest low over period -/// 2. Calculate where current close is within this range -/// 3. Scale result to -100 to 0 range -/// -/// Key characteristics: -/// - Oscillates between -100 and 0 -/// - Similar to Stochastic but no smoothing -/// - Traditional overbought level at -20 -/// - Traditional oversold level at -80 -/// - Leading indicator for market tops/bottoms -/// -/// Formula: -/// %R = -100 * (Highest High - Close) / (Highest High - Lowest Low) -/// -/// Sources: -/// Larry Williams - "How I Made One Million Dollars Last Year Trading Commodities" (1973) -/// https://www.investopedia.com/terms/w/williamsr.asp -/// -/// Note: Default period of 14 is commonly used -/// -[SkipLocalsInit] -public sealed class Willr : AbstractBase -{ - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private const int DefaultPeriod = 14; - private const double ScalingFactor = -100.0; - - /// The lookback period (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Willr(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _highs = new(period); - _lows = new(period); - WarmupPeriod = period; - Name = $"WILLR({period})"; - } - - /// The data source object that publishes updates. - /// The lookback period. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Willr(object source, int period = DefaultPeriod) - : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - double highest = _highs.Max(); - double lowest = _lows.Min(); - double range = highest - lowest; - - return range >= double.Epsilon ? ScalingFactor * ((highest - BarInput.Close) / range) : 0; - } -} diff --git a/lib/oscillators/_list.md b/lib/oscillators/_list.md deleted file mode 100644 index e0423145..00000000 --- a/lib/oscillators/_list.md +++ /dev/null @@ -1,32 +0,0 @@ -# Oscillators indicators -Done: 24, Todo: 5 - -✔️ AC - Acceleration Oscillator -✔️ AO - Awesome Oscillator -✔️ AROON - Aroon oscillator (Up, Down) -✔️ BOP - Balance of Power -✔️ CCI - Commodity Channel Index -✔️ CFO - Chande Forcast Oscillator -✔️ CHOP - Choppiness Index -✔️ CMO - Chande Momentum Oscillator -✔️ COG - Ehler's Center of Gravity -✔️ COPPOCK - Coppock Curve -✔️ CRSI - Connor RSI -✔️ CTI - Ehler's Correlation Trend Indicator -✔️ DOSC - Derivative Oscillator -✔️ FISHER - Fisher Transform -✔️ EFI - Elder Ray's Force Index -✔️ RSI - Relative Strength Index -✔️ RSX - Jurik Trend Strength Index -✔️ SMI - Stochastic Momentum Index -✔️ SRSI - Stochastic RSI (SRSI, Signal) -✔️ STC - Schaff Trend Cycle -✔️ STOCH - Stochastic Oscillator (%K, %D) -✔️ TSI - True Strength Index -✔️ UO - Ultimate Oscillator -✔️ WILLR - Larry Williams' %R -FOSC - Forecast Oscillator -GATOR - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth) -KDJ - KDJ Indicator (K, D, J lines) -KRI - Kairi Relative Index -RVGI - Relative Vigor Index (RVGI, Signal) diff --git a/lib/patterns/_list.md b/lib/patterns/_list.md deleted file mode 100644 index 3da4ea8a..00000000 --- a/lib/patterns/_list.md +++ /dev/null @@ -1,11 +0,0 @@ -# Pattern indicators -Done: 0, Todo: 8 - -DOJI - Doji Candlestick Pattern -ER - Elder Ray Pattern (Bull Power, Bear Power) -MARU - Marubozu Candlestick Pattern -PIV - Pivot Points (Support 1-3, Pivot, Resistance 1-3) -PP - Price Pivots (Support 1-3, Pivot, Resistance 1-3) -RPP - Rolling Pivot Points (Support 1-3, Pivot, Resistance 1-3) -WF - Williams Fractal -ZZ - Zig Zag Pattern diff --git a/lib/quantalib.csproj b/lib/quantalib.csproj index daa11ddc..20e55cf4 100644 --- a/lib/quantalib.csproj +++ b/lib/quantalib.csproj @@ -1,5 +1,6 @@ - + + net8.0;net10.0 QuanTAlib Library of TA Calculations, Charts and Strategies for Quantower Quantitative Technical Analysis Library in C# for Quantower @@ -28,6 +29,8 @@ $(GitVersion_AssemblySemVer) $(GitVersion_AssemblySemFileVer) $(GitVersion_InformationalVersion) + latest + 6afc11a7-4355-4f5e-9fdf-22431e5b03cb @@ -40,13 +43,4 @@ - - - ..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - diff --git a/lib/statistics/Beta.cs b/lib/statistics/Beta.cs deleted file mode 100644 index 97e065f2..00000000 --- a/lib/statistics/Beta.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// BETA: Beta Coefficient -/// A statistical measure that quantifies the volatility of an asset or portfolio -/// in relation to the overall market. Beta is used to assess the risk and return -/// characteristics of an investment. -/// -/// -/// The Beta calculation process: -/// 1. Calculates covariance between asset and market returns -/// 2. Computes variance of market returns -/// 3. Divides covariance by market variance -/// -/// Key characteristics: -/// - Measures relative volatility -/// - Beta > 1: More volatile than market -/// - Beta < 1: Less volatile than market -/// - Beta = 1: Same volatility as market -/// - Beta < 0: Inverse relationship with market -/// -/// Formula: -/// β = Cov(Ra, Rm) / Var(Rm) -/// where: -/// Ra = asset returns -/// Rm = market returns -/// -/// Market Applications: -/// - Risk assessment -/// - Portfolio management -/// - Asset allocation -/// - Performance analysis -/// - Hedging strategies -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Beta_(finance) -/// "Modern Portfolio Theory" - Harry Markowitz -/// -/// Note: Assumes linear relationship between asset and market returns -/// -[SkipLocalsInit] -public sealed class Beta : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _assetReturns; - private readonly CircularBuffer _marketReturns; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for beta calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Beta(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for beta calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _assetReturns = new CircularBuffer(period); - _marketReturns = new CircularBuffer(period); - Name = $"Beta(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for beta calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Beta(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _assetReturns.Clear(); - _marketReturns.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateCovariance(ReadOnlySpan assetReturns, ReadOnlySpan marketReturns, double assetMean, double marketMean) - { - double covariance = 0; - for (int i = 0; i < assetReturns.Length; i++) - { - covariance += (assetReturns[i] - assetMean) * (marketReturns[i] - marketMean); - } - return covariance / assetReturns.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateVariance(ReadOnlySpan values, double mean) - { - double variance = 0; - for (int i = 0; i < values.Length; i++) - { - double diff = values[i] - mean; - variance += diff * diff; - } - return variance / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _assetReturns.Add(Input.Value, Input.IsNew); - _marketReturns.Add(Input2.Value, Input.IsNew); - - double beta = 0; - if (_assetReturns.Count >= MinimumPoints && _marketReturns.Count >= MinimumPoints) - { - ReadOnlySpan assetValues = _assetReturns.GetSpan(); - ReadOnlySpan marketValues = _marketReturns.GetSpan(); - - double assetMean = CalculateMean(assetValues); - double marketMean = CalculateMean(marketValues); - - double covariance = CalculateCovariance(assetValues, marketValues, assetMean, marketMean); - double marketVariance = CalculateVariance(marketValues, marketMean); - - if (marketVariance > Epsilon) - { - beta = covariance / marketVariance; - } - } - - IsHot = _assetReturns.Count >= Period && _marketReturns.Count >= Period; - return beta; - } -} diff --git a/lib/statistics/Corr.cs b/lib/statistics/Corr.cs deleted file mode 100644 index 0eb18c50..00000000 --- a/lib/statistics/Corr.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CORR: Correlation Coefficient -/// A statistical measure that quantifies the strength and direction of the relationship -/// between two variables. The correlation coefficient ranges from -1 to 1, where 1 indicates -/// a perfect positive correlation, -1 indicates a perfect negative correlation, and 0 indicates -/// no correlation. -/// -/// -/// The Correlation calculation process: -/// 1. Calculates mean of both variables -/// 2. Computes covariance between variables -/// 3. Calculates standard deviation of both variables -/// 4. Divides covariance by product of standard deviations -/// -/// Key characteristics: -/// - Measures linear relationship strength -/// - Symmetric around zero -/// - Scale-independent measure -/// - Sensitive to outliers -/// - Useful for portfolio diversification -/// -/// Formula: -/// ρ = Cov(X, Y) / (σX * σY) -/// where: -/// X, Y = variables -/// Cov = covariance -/// σ = standard deviation -/// -/// Market Applications: -/// - Portfolio diversification -/// - Risk management -/// - Pairs trading -/// - Performance analysis -/// - Market sentiment analysis -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Correlation_coefficient -/// "Modern Portfolio Theory" - Harry Markowitz -/// -/// Note: Assumes linear relationship between variables -/// -[SkipLocalsInit] -public sealed class Corr : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _xValues; - private readonly CircularBuffer _yValues; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for correlation calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Corr(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for correlation calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _xValues = new CircularBuffer(period); - _yValues = new CircularBuffer(period); - Name = $"Corr(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for correlation calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Corr(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _xValues.Clear(); - _yValues.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateCovariance(ReadOnlySpan xValues, ReadOnlySpan yValues, double xMean, double yMean) - { - double covariance = 0; - for (int i = 0; i < xValues.Length; i++) - { - covariance += (xValues[i] - xMean) * (yValues[i] - yMean); - } - return covariance / xValues.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateStandardDeviation(ReadOnlySpan values, double mean) - { - double sumSquaredDeviations = 0; - for (int i = 0; i < values.Length; i++) - { - double deviation = values[i] - mean; - sumSquaredDeviations += deviation * deviation; - } - return Math.Sqrt(sumSquaredDeviations / values.Length); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _xValues.Add(Input.Value, Input.IsNew); - _yValues.Add(Input2.Value, Input.IsNew); - - double correlation = 0; - if (_xValues.Count >= MinimumPoints && _yValues.Count >= MinimumPoints) - { - ReadOnlySpan xValues = _xValues.GetSpan(); - ReadOnlySpan yValues = _yValues.GetSpan(); - - double xMean = CalculateMean(xValues); - double yMean = CalculateMean(yValues); - - double covariance = CalculateCovariance(xValues, yValues, xMean, yMean); - double xStdDev = CalculateStandardDeviation(xValues, xMean); - double yStdDev = CalculateStandardDeviation(yValues, yMean); - - if (xStdDev > Epsilon && yStdDev > Epsilon) - { - correlation = covariance / (xStdDev * yStdDev); - } - } - - IsHot = _xValues.Count >= Period && _yValues.Count >= Period; - return correlation; - } -} diff --git a/lib/statistics/Covar.cs b/lib/statistics/Covar.cs deleted file mode 100644 index 1622d2cd..00000000 --- a/lib/statistics/Covar.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// COVAR: Covariance -/// A statistical measure that quantifies how two variables change together. Unlike correlation, -/// covariance is not normalized and therefore is scale-dependent. A positive covariance indicates -/// that variables tend to move in the same direction, while a negative covariance indicates -/// opposite movement. -/// -/// -/// The Covariance calculation process: -/// 1. Calculates mean of both variables -/// 2. For each pair of points, multiply their deviations from their respective means -/// 3. Sum these products and divide by the number of observations -/// -/// Key characteristics: -/// - Measures linear relationship -/// - Scale-dependent measure -/// - Sign indicates direction of relationship -/// - Magnitude depends on scale of variables -/// - Basis for correlation coefficient -/// -/// Formula: -/// Cov(X,Y) = Σ((x - μx)(y - μy)) / n -/// where: -/// X, Y = variables -/// μx, μy = means of X and Y -/// n = number of observations -/// -/// Market Applications: -/// - Portfolio risk analysis -/// - Pairs trading strategy development -/// - Asset relationship analysis -/// - Risk factor sensitivity analysis -/// - Multi-asset portfolio optimization -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Covariance -/// "Modern Portfolio Theory" - Harry Markowitz -/// -/// Note: Scale-dependent nature means values should be interpreted in context of the data scales -/// -[SkipLocalsInit] -public sealed class Covar : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _xValues; - private readonly CircularBuffer _yValues; - private const int MinimumPoints = 2; - - /// The number of points to consider for covariance calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Covar(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for covariance calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _xValues = new CircularBuffer(period); - _yValues = new CircularBuffer(period); - Name = $"Covar(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for covariance calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Covar(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _xValues.Clear(); - _yValues.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateCovariance(ReadOnlySpan xValues, ReadOnlySpan yValues, double xMean, double yMean) - { - double covariance = 0; - for (int i = 0; i < xValues.Length; i++) - { - covariance += (xValues[i] - xMean) * (yValues[i] - yMean); - } - return covariance / xValues.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _xValues.Add(Input.Value, Input.IsNew); - _yValues.Add(Input2.Value, Input.IsNew); - - double covariance = 0; - if (_xValues.Count >= MinimumPoints && _yValues.Count >= MinimumPoints) - { - ReadOnlySpan xValues = _xValues.GetSpan(); - ReadOnlySpan yValues = _yValues.GetSpan(); - - double xMean = CalculateMean(xValues); - double yMean = CalculateMean(yValues); - - covariance = CalculateCovariance(xValues, yValues, xMean, yMean); - } - - IsHot = _xValues.Count >= Period && _yValues.Count >= Period; - return covariance; - } -} diff --git a/lib/statistics/Curvature.cs b/lib/statistics/Curvature.cs deleted file mode 100644 index fbab28d8..00000000 --- a/lib/statistics/Curvature.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Curvature: Second Derivative Rate of Change -/// A statistical measure that calculates the rate of change of the slope over time. -/// Curvature provides insights into trend acceleration or deceleration by measuring -/// how quickly the slope (first derivative) is changing. -/// -/// -/// The Curvature calculation process: -/// 1. Calculates slope values over the specified period -/// 2. Applies least squares regression to slope values -/// 3. Provides slope of slopes (curvature) -/// 4. Includes additional statistical measures (R², StdDev) -/// -/// Key characteristics: -/// - Measures trend acceleration/deceleration -/// - Positive values indicate accelerating uptrends or decelerating downtrends -/// - Negative values indicate decelerating uptrends or accelerating downtrends -/// - Helps identify potential trend reversals -/// - Provides trend momentum information -/// -/// Formula: -/// Curvature = Σ((x - x̄)(y - ȳ)) / Σ((x - x̄)²) -/// where: -/// x = time points -/// y = slope values -/// x̄, ȳ = respective means -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Curvature -/// https://www.sciencedirect.com/topics/mathematics/curve-fitting -/// -/// Note: Second-order derivative providing acceleration insights -/// -[SkipLocalsInit] -public sealed class Curvature : AbstractBase -{ - private readonly int _period; - private readonly Slope _slopeCalculator; - private readonly CircularBuffer _slopeBuffer; - private const double Epsilon = 1e-10; - - /// - /// Gets the y-intercept of the curvature line. - /// - public double? Intercept { get; private set; } - - /// - /// Gets the standard deviation of the slope values used in the curvature calculation. - /// - public double? StdDev { get; private set; } - - /// - /// Gets the R-squared value, indicating the goodness of fit of the curvature line. - /// - public double? RSquared { get; private set; } - - /// - /// Gets the last calculated point on the curvature line. - /// - public double? Line { get; private set; } - - /// The number of points to consider for calculation. - /// Thrown when period is 2 or less. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Curvature(int period) - { - if (period <= 2) - { - throw new ArgumentOutOfRangeException(nameof(period), period, - "Period must be greater than 2 for Curvature calculation."); - } - _period = period; - WarmupPeriod = (period * 2) - 1; // Number of points needed for period number of slopes - _slopeCalculator = new Slope(period); - _slopeBuffer = new CircularBuffer(period); - Name = $"Curvature(period={period})"; - - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Curvature(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _slopeBuffer.Clear(); - Intercept = null; - StdDev = null; - RSquared = null; - Line = null; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double sumX, double sumY) CalculateSums(ReadOnlySpan slopes, int count) - { - double sumX = 0, sumY = 0; - for (int i = 0; i < count; i++) - { - sumX += i + 1; - sumY += slopes[i]; - } - return (sumX, sumY); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double sumSqX, double sumSqY, double sumSqXY) CalculateSquaredSums( - ReadOnlySpan slopes, int count, double avgX, double avgY) - { - double sumSqX = 0, sumSqY = 0, sumSqXY = 0; - for (int i = 0; i < count; i++) - { - double devX = (i + 1) - avgX; - double devY = slopes[i] - avgY; - sumSqX += devX * devX; - sumSqY += devY * devY; - sumSqXY += devX * devY; - } - return (sumSqX, sumSqY, sumSqXY); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - var slopeResult = _slopeCalculator.Calc(Input); - _slopeBuffer.Add(slopeResult.Value, Input.IsNew); - - double curvature = 0; - - if (_slopeBuffer.Count < 2) - { - return curvature; // Not enough points for calculation - } - - int count = Math.Min(_slopeBuffer.Count, _period); - ReadOnlySpan slopes = _slopeBuffer.GetSpan(); - - // Calculate averages - var (sumX, sumY) = CalculateSums(slopes, count); - double avgX = sumX / count; - double avgY = sumY / count; - - // Least squares method - var (sumSqX, sumSqY, sumSqXY) = CalculateSquaredSums(slopes, count, avgX, avgY); - - if (sumSqX > Epsilon) - { - curvature = sumSqXY / sumSqX; - Intercept = avgY - (curvature * avgX); - - // Calculate Standard Deviation and R-Squared - double stdDevX = Math.Sqrt(sumSqX / count); - double stdDevY = Math.Sqrt(sumSqY / count); - StdDev = stdDevY; - - double stdDevProduct = stdDevX * stdDevY; - if (stdDevProduct > Epsilon) - { - double r = sumSqXY / (stdDevProduct) / count; - RSquared = r * r; - } - - // Calculate last Line value (y = mx + b) - Line = (curvature * count) + Intercept; - } - else - { - Intercept = null; - StdDev = null; - RSquared = null; - Line = null; - } - - IsHot = _slopeBuffer.Count == _period; - return curvature; - } -} diff --git a/lib/statistics/Entropy.cs b/lib/statistics/Entropy.cs deleted file mode 100644 index 9d2d9b7b..00000000 --- a/lib/statistics/Entropy.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Entropy: Information Content Measure -/// A statistical measure that quantifies the unpredictability or randomness in -/// a time series using Shannon's Entropy. Higher entropy indicates more randomness -/// and uncertainty in the data. -/// -/// -/// The Entropy calculation process: -/// 1. Groups values to calculate probabilities -/// 2. Applies Shannon's entropy formula -/// 3. Normalizes result to 0-1 range -/// 4. Adjusts for number of unique values -/// -/// Key characteristics: -/// - Range from 0 (predictable) to 1 (random) -/// - Measures information content -/// - Detects regime changes -/// - Identifies market uncertainty -/// - Scale-independent measure -/// -/// Formula: -/// H = -Σ(p(x) * log₂(p(x))) / log₂(n) -/// where: -/// p(x) = probability of value x -/// n = number of unique values -/// -/// Applications: -/// - Detect market regime changes -/// - Assess price movement predictability -/// - Identify periods of high uncertainty -/// - Measure information flow in markets -/// -/// Sources: -/// Claude Shannon - "A Mathematical Theory of Communication" (1948) -/// https://en.wikipedia.org/wiki/Entropy_(information_theory) -/// -/// Note: Normalized to [0,1] for easier interpretation -/// -[SkipLocalsInit] -public sealed class Entropy : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private readonly Dictionary _valueCounts; - private const double Epsilon = 1e-10; - private const double DefaultEntropy = 1.0; - private const int MinimumPoints = 2; - - /// The number of points to consider for entropy calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Entropy(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for entropy calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; // Minimum number of points needed for entropy calculation - _buffer = new CircularBuffer(period); - _valueCounts = new Dictionary(); - Name = $"Entropy(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for entropy calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Entropy(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _valueCounts.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static void CountValues(ReadOnlySpan values, Dictionary counts) - { - counts.Clear(); - for (int i = 0; i < values.Length; i++) - { - counts[values[i]] = counts.TryGetValue(values[i], out int count) ? count + 1 : 1; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateShannonsEntropy(Dictionary counts, int totalCount) - { - double entropy = 0; - foreach (var count in counts.Values) - { - double probability = (double)count / totalCount; - entropy -= probability * Math.Log2(probability); - } - return entropy; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer.Add(Input.Value, Input.IsNew); - - if (_index <= 1) // Need at least two data points for entropy calculation - { - return DefaultEntropy; - } - - ReadOnlySpan values = _buffer.GetSpan(); - CountValues(values, _valueCounts); - - // Calculate Shannon's entropy - double entropy = CalculateShannonsEntropy(_valueCounts, values.Length); - - // Normalize by maximum possible entropy for current unique values - double maxEntropy = Math.Log2(_valueCounts.Count); - entropy = maxEntropy < Epsilon ? DefaultEntropy : entropy / maxEntropy; - - IsHot = _buffer.Count >= Period; - return entropy; - } -} diff --git a/lib/statistics/Granger.cs b/lib/statistics/Granger.cs deleted file mode 100644 index 1473e27e..00000000 --- a/lib/statistics/Granger.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// GRANGER: Granger Causality Test -/// A statistical test to determine whether one time series is useful in forecasting another. -/// Tests if past values of X help predict future values of Y beyond Y's own past values. -/// Returns a value between 0 and 1 representing the probability that X does not Granger-cause Y. -/// -/// -/// The Granger Causality calculation process: -/// 1. Fits two regression models: -/// - Restricted model: Y(t) = α₀ + Σ(β₁ᵢY(t-i)) + ε(t) -/// - Unrestricted model: Y(t) = α₀ + Σ(β₁ᵢY(t-i)) + Σ(β₂ᵢX(t-i)) + ε(t) -/// 2. Calculates F-statistic comparing the models -/// 3. Computes p-value from F-distribution -/// -/// Key characteristics: -/// - Tests predictive causality, not true causation -/// - Sensitive to lag selection -/// - Assumes stationarity of time series -/// - Useful for lead/lag relationship analysis -/// -/// Formula: -/// F = ((RSS₁ - RSS₂)/p) / (RSS₂/(n-2p-1)) -/// where: -/// RSS₁ = residual sum of squares from restricted model -/// RSS₂ = residual sum of squares from unrestricted model -/// p = number of lags -/// n = number of observations -/// -/// Market Applications: -/// - Lead/lag analysis between markets -/// - Price discovery analysis -/// - Market efficiency testing -/// - Intermarket analysis -/// - Risk spillover detection -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Granger_causality -/// "Investigating Causal Relations by Econometric Models and Cross-spectral Methods" - C.W.J. Granger -/// -/// Note: Assumes linear relationships and stationarity -/// -[SkipLocalsInit] -public sealed class Granger : AbstractBase -{ - private readonly int Lags; - private readonly CircularBuffer _xValues; - private readonly CircularBuffer _yValues; - private const double Epsilon = 1e-10; - private const int MinimumLags = 1; - - /// The number of lags to use in the Granger causality test. - /// Thrown when lags is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Granger(int lags) - { - if (lags < MinimumLags) - { - throw new ArgumentOutOfRangeException(nameof(lags), - "Number of lags must be at least 1 for Granger causality test."); - } - Lags = lags; - WarmupPeriod = lags + 1; - _xValues = new CircularBuffer(lags * 2); // Need extra space for lagged values - _yValues = new CircularBuffer(lags * 2); - Name = $"Granger(lags={lags})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of lags to use in the Granger causality test. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Granger(object source, int lags) : this(lags) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _xValues.Clear(); - _yValues.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateRSS(ReadOnlySpan y, ReadOnlySpan yhat) - { - double rss = 0; - for (int i = 0; i < y.Length; i++) - { - double residual = y[i] - yhat[i]; - rss += residual * residual; - } - return rss; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static void FitOLS(ReadOnlySpan y, ReadOnlySpan x, Span beta) - { - // Simple OLS implementation for y = Xβ + ε - int n = y.Length; - int k = beta.Length; - - // Create X matrix (including constant term) - var X = new double[n, k]; - for (int i = 0; i < n; i++) - { - X[i, 0] = 1.0; // Constant term - for (int j = 1; j < k; j++) - { - X[i, j] = x[(i * (k - 1)) + (j - 1)]; - } - } - - // Calculate β = (X'X)⁻¹X'y - var XtX = new double[k, k]; - var Xty = new double[k]; - - // Calculate X'X and X'y - for (int i = 0; i < k; i++) - { - for (int j = 0; j < k; j++) - { - double sum = 0; - for (int l = 0; l < n; l++) - { - sum += X[l, i] * X[l, j]; - } - XtX[i, j] = sum; - } - - double sum2 = 0; - for (int l = 0; l < n; l++) - { - sum2 += X[l, i] * y[l]; - } - Xty[i] = sum2; - } - - // Solve system of equations - for (int i = 0; i < k; i++) - { - double pivot = XtX[i, i]; - if (Math.Abs(pivot) > Epsilon) - { - for (int j = 0; j < k; j++) - { - XtX[i, j] /= pivot; - } - Xty[i] /= pivot; - - for (int j = 0; j < k; j++) - { - if (i != j) - { - double factor = XtX[j, i]; - for (int l = 0; l < k; l++) - { - XtX[j, l] -= factor * XtX[i, l]; - } - Xty[j] -= factor * Xty[i]; - } - } - } - } - - // Copy results to beta - for (int i = 0; i < k; i++) - { - beta[i] = Xty[i]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateFStatistic(double rss1, double rss2, int n, int p) - { - // Calculate F-statistic - double numerator = (rss1 - rss2) / p; - double denominator = rss2 / (n - (2 * p) - 1); - return numerator / denominator; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double FDistributionPValue(double f, int df1, int df2) - { - // Approximate p-value from F-distribution - // Using a simplified approximation for performance - double v = df2 / (df2 + (df1 * f)); - return Math.Pow(v, df2 / 2.0); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _xValues.Add(Input.Value, Input.IsNew); - _yValues.Add(Input2.Value, Input.IsNew); - - double pValue = 1.0; // Null hypothesis: X does not Granger-cause Y - - if (_xValues.Count >= WarmupPeriod && _yValues.Count >= WarmupPeriod) - { - int n = _xValues.Count - Lags; - if (n > (2 * Lags) + 1) - { - ReadOnlySpan x = _xValues.GetSpan(); - ReadOnlySpan y = _yValues.GetSpan(); - - // Prepare data for regression - var yData = y.Slice(Lags, n).ToArray(); - var restricted = new double[Lags + 1]; - var unrestricted = new double[(2 * Lags) + 1]; - - // Fit restricted model (only Y lags) - FitOLS(yData, y.Slice(0, n), restricted); - - // Calculate RSS for restricted model - var yhatRestricted = new double[n]; - for (int i = 0; i < n; i++) - { - yhatRestricted[i] = restricted[0]; - for (int j = 0; j < Lags; j++) - { - yhatRestricted[i] += restricted[j + 1] * y[i + Lags - j - 1]; - } - } - double rss1 = CalculateRSS(yData, yhatRestricted); - - // Fit unrestricted model (Y and X lags) - FitOLS(yData, x.Slice(0, n), unrestricted); - - // Calculate RSS for unrestricted model - var yhatUnrestricted = new double[n]; - for (int i = 0; i < n; i++) - { - yhatUnrestricted[i] = unrestricted[0]; - for (int j = 0; j < Lags; j++) - { - yhatUnrestricted[i] += unrestricted[j + 1] * y[i + Lags - j - 1]; - yhatUnrestricted[i] += unrestricted[j + Lags + 1] * x[i + Lags - j - 1]; - } - } - double rss2 = CalculateRSS(yData, yhatUnrestricted); - - // Calculate F-statistic and p-value - if (rss2 > Epsilon) - { - double f = CalculateFStatistic(rss1, rss2, n, Lags); - pValue = FDistributionPValue(f, Lags, n - (2 * Lags) - 1); - } - } - } - - IsHot = _xValues.Count >= WarmupPeriod && _yValues.Count >= WarmupPeriod; - return pValue; - } -} diff --git a/lib/statistics/Hurst.cs b/lib/statistics/Hurst.cs deleted file mode 100644 index 4c2c9e2d..00000000 --- a/lib/statistics/Hurst.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// HURST: Hurst Exponent -/// A measure of long-term memory of time series that relates to the -/// autocorrelations of the time series, and the rate at which these -/// decrease as the lag between pairs of values increases. -/// -/// -/// The Hurst Exponent calculation process: -/// 1. Calculate log returns of the series -/// 2. Create subsequences of different lengths -/// 3. For each length: -/// - Calculate range (max-min) of cumulative deviations -/// - Calculate standard deviation -/// - Calculate R/S ratio -/// 4. Fit log(R/S) vs log(length) to find H -/// -/// Key characteristics: -/// - H = 0.5: Random walk (Brownian motion) -/// - 0.5 < H ≤ 1.0: Trending (persistent) series -/// - 0 ≤ H < 0.5: Mean-reverting (anti-persistent) series -/// - Default minimum length is 10 -/// - Default maximum length is period/2 -/// -/// Formula: -/// R(n)/S(n) = c * n^H -/// where: -/// R(n) = range of cumulative deviations -/// S(n) = standard deviation -/// n = subsequence length -/// H = Hurst exponent -/// -/// Market Applications: -/// - Market efficiency analysis -/// - Trend strength measurement -/// - Trading strategy development -/// - Risk assessment -/// - Market regime identification -/// -/// Sources: -/// H.E. Hurst (1951) -/// "Long-term Storage Capacity of Reservoirs" -/// Transactions of the American Society of Civil Engineers, 116, 770-799 -/// -/// Note: Returns a value between 0 and 1 -/// -[SkipLocalsInit] -public sealed class Hurst : AbstractBase -{ - private readonly int _period; - private readonly int _minLength; - private readonly CircularBuffer _prices; - private readonly CircularBuffer _logReturns; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hurst(int period = 100, int minLength = 10) - { - if (minLength < 10) - { - throw new ArgumentOutOfRangeException(nameof(minLength), "Minimum length must be at least 10."); - } - if (period <= minLength * 2) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be at least twice the minimum length."); - } - - _period = period; - _minLength = minLength; - WarmupPeriod = period + 1; // Need one extra period for returns - Name = $"HURST({_period})"; - _prices = new CircularBuffer(period); - _logReturns = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hurst(object source, int period = 100, int minLength = 10) : this(period, minLength) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prices.Clear(); - _logReturns.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double range, double stdDev) CalculateRangeAndStdDev(ReadOnlySpan data) - { - int n = data.Length; - if (n == 0) return (0, 0); - - // Calculate mean - double mean = 0; - for (int i = 0; i < n; i++) - { - mean += data[i]; - } - mean /= n; - - // Calculate cumulative deviations and std dev - double max = double.MinValue; - double min = double.MaxValue; - double sumSquaredDev = 0; - double cumDev = 0; - - for (int i = 0; i < n; i++) - { - double dev = data[i] - mean; - cumDev += dev; - max = Math.Max(max, cumDev); - min = Math.Min(min, cumDev); - sumSquaredDev += dev * dev; - } - - double range = max - min; - double stdDev = Math.Sqrt(sumSquaredDev / n); - - return (range, stdDev); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Add price and calculate log return - _prices.Add(BarInput.Close); - if (_index > 1) - { - double logReturn = Math.Log(BarInput.Close / _prices[1]); - _logReturns.Add(logReturn); - } - - // Need enough values for calculation - if (_index <= _period) - { - return 0.5; // Return random walk value until we have enough data - } - - // Calculate R/S values for different lengths - int maxLength = _period / 2; - int numPoints = 0; - double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0; - - for (int length = _minLength; length <= maxLength; length *= 2) - { - var (range, stdDev) = CalculateRangeAndStdDev(_logReturns.GetSpan()[..length]); - if (stdDev > 0) - { - double rs = range / stdDev; - if (rs > 0) - { - double x = Math.Log(length); - double y = Math.Log(rs); - sumX += x; - sumY += y; - sumXY += x * y; - sumX2 += x * x; - numPoints++; - } - } - } - - // Calculate Hurst exponent using linear regression - double hurst = 0.5; // Default to random walk - if (numPoints > 1) - { - double slope = ((numPoints * sumXY) - (sumX * sumY)) / ((numPoints * sumX2) - (sumX * sumX)); - hurst = Math.Max(0, Math.Min(1, slope)); // Clamp between 0 and 1 - } - - IsHot = _index >= WarmupPeriod; - return hurst; - } -} diff --git a/lib/statistics/Kendall.cs b/lib/statistics/Kendall.cs deleted file mode 100644 index cf6a73e4..00000000 --- a/lib/statistics/Kendall.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// KENDALL: Kendall's Rank Correlation Coefficient (Tau) -/// A nonparametric measure that evaluates the degree of similarity between two sets -/// of rankings by analyzing concordant and discordant pairs. Unlike Spearman correlation, -/// Kendall's tau measures the ordinal association between two variables. -/// -/// -/// The Kendall calculation process: -/// 1. Compares each pair of observations -/// 2. Counts concordant and discordant pairs -/// 3. Handles ties in both variables -/// -/// Key characteristics: -/// - Measures ordinal association -/// - Range: -1 to +1 -/// - Robust to outliers -/// - More intuitive probabilistic interpretation -/// - Less sensitive to error than Spearman -/// -/// Formula: -/// τ = (nc - nd) / sqrt((n0 - n1)(n0 - n2)) -/// where: -/// nc = number of concordant pairs -/// nd = number of discordant pairs -/// n0 = n(n-1)/2 -/// n1 = sum(u(u-1)/2) for ties in x -/// n2 = sum(v(v-1)/2) for ties in y -/// -/// Market Applications: -/// - Rank correlation analysis -/// - Portfolio diversification -/// - Risk assessment -/// - Market trend analysis -/// - Pattern recognition -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Kendall_rank_correlation_coefficient -/// "Rank Correlation Methods" - Maurice G. Kendall -/// -/// Note: More robust to outliers and errors than other correlation measures -/// -[SkipLocalsInit] -public sealed class Kendall : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _xValues; - private readonly CircularBuffer _yValues; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for Kendall correlation calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Kendall(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for Kendall correlation calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _xValues = new CircularBuffer(period); - _yValues = new CircularBuffer(period); - Name = $"Kendall(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for Kendall correlation calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Kendall(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _xValues.Clear(); - _yValues.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (int concordant, int discordant, int tiesX, int tiesY) CountPairs(ReadOnlySpan x, ReadOnlySpan y) - { - int n = x.Length; - int concordant = 0; - int discordant = 0; - int tiesX = 0; - int tiesY = 0; - - for (int i = 0; i < n - 1; i++) - { - if (double.IsNaN(x[i]) || double.IsNaN(y[i])) continue; - - for (int j = i + 1; j < n; j++) - { - if (double.IsNaN(x[j]) || double.IsNaN(y[j])) continue; - - double xDiff = x[i] - x[j]; - double yDiff = y[i] - y[j]; - - if (Math.Abs(xDiff) < Epsilon && Math.Abs(yDiff) < Epsilon) - { - tiesX++; - tiesY++; - } - else if (Math.Abs(xDiff) < Epsilon) - { - tiesX++; - } - else if (Math.Abs(yDiff) < Epsilon) - { - tiesY++; - } - else - { - int xSign = xDiff > 0 ? 1 : -1; - int ySign = yDiff > 0 ? 1 : -1; - if (xSign == ySign) - { - concordant++; - } - else - { - discordant++; - } - } - } - } - - return (concordant, discordant, tiesX, tiesY); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _xValues.Add(Input.Value, Input.IsNew); - _yValues.Add(Input2.Value, Input.IsNew); - - double correlation = 0; - if (_xValues.Count >= MinimumPoints && _yValues.Count >= MinimumPoints) - { - ReadOnlySpan xValues = _xValues.GetSpan(); - ReadOnlySpan yValues = _yValues.GetSpan(); - - var (concordant, discordant, tiesX, tiesY) = CountPairs(xValues, yValues); - - int n = xValues.Length; - int n0 = (n * (n - 1)) / 2; - - // Calculate denominator considering ties - double denominator = Math.Sqrt((n0 - tiesX) * (n0 - tiesY)); - - if (denominator > Epsilon) - { - correlation = (concordant - discordant) / denominator; - } - } - - IsHot = _xValues.Count >= Period && _yValues.Count >= Period; - return correlation; - } -} diff --git a/lib/statistics/Kurtosis.cs b/lib/statistics/Kurtosis.cs deleted file mode 100644 index 03f8c216..00000000 --- a/lib/statistics/Kurtosis.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Kurtosis: Distribution Tail Weight Measure -/// A statistical measure that quantifies the "tailedness" of a distribution using -/// the Sheskin Algorithm. Kurtosis indicates whether data has heavy tails (more -/// outliers) or light tails (fewer outliers) compared to a normal distribution. -/// -/// -/// The Kurtosis calculation process: -/// 1. Calculates mean of the data -/// 2. Computes squared and fourth power deviations -/// 3. Applies Sheskin Algorithm for excess kurtosis -/// 4. Adjusts for sample size bias -/// -/// Key characteristics: -/// - Measures tail weight relative to normal distribution -/// - Positive values indicate heavy tails -/// - Negative values indicate light tails -/// - Zero indicates normal distribution -/// - Sensitive to extreme values -/// -/// Formula: -/// K = [n(n+1)Σ(x-μ)⁴] / [s⁴(n-1)(n-2)(n-3)] - [3(n-1)²]/[(n-2)(n-3)] -/// where: -/// n = sample size -/// μ = mean -/// s = standard deviation -/// -/// Market Applications: -/// - Identify potential for extreme moves -/// - Assess risk of "black swan" events -/// - Compare return distributions -/// - Risk management tool -/// -/// Sources: -/// David J. Sheskin - "Handbook of Parametric and Nonparametric Statistical Procedures" -/// https://en.wikipedia.org/wiki/Kurtosis -/// -/// Note: Returns excess kurtosis (normal distribution = 0) -/// -[SkipLocalsInit] -public sealed class Kurtosis : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 4; - - /// The number of points to consider for kurtosis calculation. - /// Thrown when period is less than 4. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Kurtosis(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 4 for kurtosis calculation."); - } - Period = period; - WarmupPeriod = Period - 1; - _buffer = new CircularBuffer(period); - Name = $"Kurtosis(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for kurtosis calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Kurtosis(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double s2, double s4) CalculateDeviations(ReadOnlySpan values, double mean) - { - double s2 = 0; // Sum of squared deviations - double s4 = 0; // Sum of fourth power deviations - - for (int i = 0; i < values.Length; i++) - { - double diff = values[i] - mean; - double diff2 = diff * diff; - s2 += diff2; - s4 += diff2 * diff2; - } - - return (s2, s4); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSheskinKurtosis(double s2, double s4, int n) - { - double variance = s2 / (n - 1); - double variance2 = variance * variance; - - if (variance2 < Epsilon) - return 0; - - return ((n * (n + 1) * s4) / (variance2 * (n - 3) * (n - 1) * (n - 2))) - - (3 * (n - 1) * (n - 1) / ((n - 2) * (n - 3))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer.Add(Input.Value, Input.IsNew); - - double kurtosis = 0; - if (_buffer.Count > MinimumPoints - 1) // Need at least 4 points for valid calculation - { - ReadOnlySpan values = _buffer.GetSpan(); - double mean = CalculateMean(values); - var (s2, s4) = CalculateDeviations(values, mean); - kurtosis = CalculateSheskinKurtosis(s2, s4, values.Length); - } - - IsHot = _buffer.Count >= Period; - return kurtosis; - } -} diff --git a/lib/statistics/Max.cs b/lib/statistics/Max.cs deleted file mode 100644 index 15a52d8a..00000000 --- a/lib/statistics/Max.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MAX: Maximum Value with Decay -/// A statistical measure that tracks the highest value over a specified period, -/// with an optional decay factor to gradually reduce the influence of older peaks. -/// This adaptive approach allows the indicator to respond to changing market conditions. -/// -/// -/// The MAX calculation process: -/// 1. Tracks highest value in current period -/// 2. Applies exponential decay to old peaks -/// 3. Adjusts decay based on time since last peak -/// 4. Caps result at current period's maximum -/// -/// Key characteristics: -/// - Tracks absolute highest values -/// - Optional decay for adaptivity -/// - Maintains historical context -/// - Smooth transitions with decay -/// - Period-based windowing -/// -/// Formula: -/// decay = 1 - e^(-halfLife * timeSinceMax / period) -/// max = max - decay * (max - periodAverage) -/// max = min(max, periodMaximum) -/// -/// Market Applications: -/// - Identify resistance levels -/// - Track price peaks -/// - Implement trailing stops -/// - Monitor price extremes -/// - Adaptive trend following -/// -/// Sources: -/// Technical Analysis of Financial Markets -/// https://www.investopedia.com/terms/r/resistance.asp -/// -/// Note: Decay factor allows for adaptive peak tracking -/// -[SkipLocalsInit] -public sealed class Max : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private readonly double _halfLife; - private double _currentMax; - private double _p_currentMax; - private int _timeSinceNewMax; - private int _p_timeSinceNewMax; - private const double DefaultDecay = 0.0; - private const double DecayScaleFactor = 0.1; - private const double Epsilon = 1e-10; - - /// The number of points to consider for maximum calculation. - /// Half-life decay factor (0 for no decay, higher for faster forgetting). - /// Thrown when period is less than 1 or decay is negative. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Max(int period, double decay = DefaultDecay) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 1."); - } - if (decay < 0) - { - throw new ArgumentOutOfRangeException(nameof(decay), - "Half-life must be non-negative."); - } - Period = period; - WarmupPeriod = 0; - _buffer = new CircularBuffer(period); - _halfLife = decay * DecayScaleFactor; - Name = $"Max(period={period}, halfLife={decay:F2})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for maximum calculation. - /// Half-life decay factor (default 0). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Max(object source, int period, double decay = DefaultDecay) : this(period, decay) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _currentMax = double.MinValue; - _timeSinceNewMax = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_currentMax = _currentMax; - _lastValidValue = Input.Value; - _index++; - _timeSinceNewMax++; - _p_timeSinceNewMax = _timeSinceNewMax; - } - else - { - _currentMax = _p_currentMax; - _timeSinceNewMax = _p_timeSinceNewMax; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateDecayRate() - { - return 1 - Math.Exp(-_halfLife * _timeSinceNewMax / Period); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double FindMaxValue(ReadOnlySpan values) - { - double max = double.MinValue; - for (int i = 0; i < values.Length; i++) - { - if (values[i] > max) - { - max = values[i]; - } - } - return max; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - // Update maximum if new value is higher - if (Input.Value >= _currentMax) - { - _currentMax = Input.Value; - _timeSinceNewMax = 0; - } - - // Apply decay based on time since last maximum - double decayRate = CalculateDecayRate(); - _currentMax -= decayRate * (_currentMax - _buffer.Average()); - - // Ensure maximum doesn't exceed current period's highest value - ReadOnlySpan values = _buffer.GetSpan(); - _currentMax = Math.Min(_currentMax, FindMaxValue(values)); - - IsHot = true; - return _currentMax; - } -} diff --git a/lib/statistics/Median.cs b/lib/statistics/Median.cs deleted file mode 100644 index b6fc0801..00000000 --- a/lib/statistics/Median.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Median: Central Tendency Measure -/// A robust statistical measure that finds the middle value in a sorted dataset. -/// The median is less sensitive to outliers than the mean, making it particularly -/// useful for analyzing price data with extreme values. -/// -/// -/// The Median calculation process: -/// 1. Collects values over specified period -/// 2. Sorts values in ascending order -/// 3. Finds middle value(s) -/// 4. Averages two middle values if even count -/// -/// Key characteristics: -/// - Robust to outliers -/// - Always represents actual data point -/// - Splits dataset in half -/// - More stable than mean -/// - Maintains data scale -/// -/// Formula: -/// For odd n: median = value at position (n+1)/2 -/// For even n: median = (value at n/2 + value at (n/2)+1) / 2 -/// -/// Market Applications: -/// - Price distribution analysis -/// - Trend identification -/// - Outlier detection -/// - Support/resistance levels -/// - Filter extreme movements -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Median -/// "Statistics for Trading" - Technical Analysis of Financial Markets -/// -/// Note: More robust than mean for non-normal distributions -/// -[SkipLocalsInit] -public sealed class Median : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - - /// The number of points to consider for median calculation. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Median(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 1."); - } - Period = period; - WarmupPeriod = period; - _buffer = new CircularBuffer(period); - Name = $"Median(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for median calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Median(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static void QuickSort(Span arr, int left, int right) - { - if (left < right) - { - int pivotIndex = Partition(arr, left, right); - QuickSort(arr, left, pivotIndex - 1); - QuickSort(arr, pivotIndex + 1, right); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static int Partition(Span arr, int left, int right) - { - double pivot = arr[right]; - int i = left - 1; - - for (int j = left; j < right; j++) - { - if (arr[j] <= pivot) - { - i++; - (arr[i], arr[j]) = (arr[j], arr[i]); - } - } - - (arr[i + 1], arr[right]) = (arr[right], arr[i + 1]); - return i + 1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMedian(Span sortedValues) - { - int middleIndex = sortedValues.Length / 2; - return (sortedValues.Length % 2 == 0) - ? (sortedValues[middleIndex - 1] + sortedValues[middleIndex]) / 2.0 - : sortedValues[middleIndex]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double median; - if (_index >= Period) - { - // Create a temporary buffer on the stack - Span values = stackalloc double[Period]; - _buffer.GetSpan().CopyTo(values); - - // Sort values in-place - QuickSort(values, 0, values.Length - 1); - - // Calculate median based on odd/even count - median = CalculateMedian(values); - } - else - { - // Not enough data, use average as temporary measure - median = _buffer.Average(); - } - - IsHot = _index >= WarmupPeriod; - return median; - } -} diff --git a/lib/statistics/Min.cs b/lib/statistics/Min.cs deleted file mode 100644 index 0949a11b..00000000 --- a/lib/statistics/Min.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MIN: Minimum Value with Decay -/// A statistical measure that tracks the lowest value over a specified period, -/// with an optional decay factor to gradually reduce the influence of older lows. -/// This adaptive approach allows the indicator to respond to changing market conditions. -/// -/// -/// The MIN calculation process: -/// 1. Tracks lowest value in current period -/// 2. Applies exponential decay to old lows -/// 3. Adjusts decay based on time since last low -/// 4. Caps result at current period's minimum -/// -/// Key characteristics: -/// - Tracks absolute lowest values -/// - Optional decay for adaptivity -/// - Maintains historical context -/// - Smooth transitions with decay -/// - Period-based windowing -/// -/// Formula: -/// decay = 1 - e^(-halfLife * timeSinceMin / period) -/// min = min + decay * (periodAverage - min) -/// min = max(min, periodMinimum) -/// -/// Market Applications: -/// - Identify support levels -/// - Track price troughs -/// - Implement trailing stops -/// - Monitor price extremes -/// - Adaptive trend following -/// -/// Sources: -/// Technical Analysis of Financial Markets -/// https://www.investopedia.com/terms/s/support.asp -/// -/// Note: Decay factor allows for adaptive low tracking -/// -[SkipLocalsInit] -public sealed class Min : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private readonly double _halfLife; - private double _currentMin; - private double _p_currentMin; - private int _timeSinceNewMin; - private int _p_timeSinceNewMin; - private const double DefaultDecay = 0.0; - private const double DecayScaleFactor = 0.1; - private const double Epsilon = 1e-10; - - /// The number of points to consider for minimum calculation. - /// Half-life decay factor (0 for no decay, higher for faster forgetting). - /// Thrown when period is less than 1 or decay is negative. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Min(int period, double decay = DefaultDecay) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - if (decay < 0) - { - throw new ArgumentOutOfRangeException(nameof(decay), "Half-life must be non-negative."); - } - Period = period; - WarmupPeriod = 0; - _buffer = new CircularBuffer(period); - _halfLife = decay * DecayScaleFactor; - Name = $"Min(period={period}, halfLife={decay:F2})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for minimum calculation. - /// Half-life decay factor (default 0). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Min(object source, int period, double decay = DefaultDecay) : this(period, decay) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _currentMin = double.MaxValue; - _timeSinceNewMin = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _p_currentMin = _currentMin; - _lastValidValue = Input.Value; - _index++; - _timeSinceNewMin++; - _p_timeSinceNewMin = _timeSinceNewMin; - } - else - { - _currentMin = _p_currentMin; - _timeSinceNewMin = _p_timeSinceNewMin; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateDecayRate() - { - return 1 - Math.Exp(-_halfLife * _timeSinceNewMin / Period); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double FindMinValue(ReadOnlySpan values) - { - double min = double.MaxValue; - for (int i = 0; i < values.Length; i++) - { - if (values[i] < min) - { - min = values[i]; - } - } - return min; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - // Update minimum if new value is lower - if (Input.Value <= _currentMin) - { - _currentMin = Input.Value; - _timeSinceNewMin = 0; - } - - // Apply decay based on time since last minimum - double decayRate = CalculateDecayRate(); - _currentMin += decayRate * (_buffer.Average() - _currentMin); - - // Ensure minimum doesn't fall below current period's lowest value - ReadOnlySpan values = _buffer.GetSpan(); - _currentMin = Math.Max(_currentMin, FindMinValue(values)); - - IsHot = true; - return _currentMin; - } -} diff --git a/lib/statistics/Mode.cs b/lib/statistics/Mode.cs deleted file mode 100644 index b64282b5..00000000 --- a/lib/statistics/Mode.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MODE: Most Frequent Value Measure -/// A statistical measure that identifies the most frequently occurring value(s) -/// in a dataset. When multiple values share the highest frequency, it returns -/// their average to provide a representative central value. -/// -/// -/// The Mode calculation process: -/// 1. Groups values by frequency -/// 2. Identifies highest frequency group(s) -/// 3. Averages multiple modes if present -/// 4. Uses mean until period filled -/// -/// Key characteristics: -/// - Identifies most common values -/// - Handles multiple modes -/// - Robust to distribution shape -/// - Useful for discrete data -/// - Returns actual data points -/// -/// Formula: -/// mode = value with highest frequency count -/// if multiple modes: average of mode values -/// -/// Market Applications: -/// - Identify common price levels -/// - Detect support/resistance zones -/// - Analyze volume clusters -/// - Find price congestion areas -/// - Pattern recognition -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Mode_(statistics) -/// "Statistical Analysis in Financial Markets" -/// -/// Note: Particularly useful for price level analysis -/// -[SkipLocalsInit] -public sealed class Mode : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private readonly Dictionary _frequencies; - private readonly List _modes; - private const double Epsilon = 1e-10; - - /// The number of points to consider for mode calculation. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mode(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - Period = period; - WarmupPeriod = period; - _buffer = new CircularBuffer(period); - _frequencies = new Dictionary(); - _modes = new List(); - Name = $"Mode(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for mode calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mode(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _frequencies.Clear(); - _modes.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private void CountFrequencies(ReadOnlySpan values) - { - _frequencies.Clear(); - for (int i = 0; i < values.Length; i++) - { - _frequencies[values[i]] = _frequencies.TryGetValue(values[i], out int count) ? count + 1 : 1; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private void FindModes() - { - _modes.Clear(); - int maxCount = 0; - - foreach (var kvp in _frequencies) - { - if (kvp.Value > maxCount) - { - maxCount = kvp.Value; - _modes.Clear(); - _modes.Add(kvp.Key); - } - else if (kvp.Value == maxCount) - { - _modes.Add(kvp.Key); - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateAverageMode() - { - double sum = 0; - for (int i = 0; i < _modes.Count; i++) - { - sum += _modes[i]; - } - return sum / _modes.Count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double mode; - if (_index >= Period) - { - ReadOnlySpan values = _buffer.GetSpan(); - CountFrequencies(values); - FindModes(); - mode = CalculateAverageMode(); - } - else - { - // Use average until we have enough data points - mode = _buffer.Average(); - } - - IsHot = _index >= WarmupPeriod; - return mode; - } -} diff --git a/lib/statistics/Percentile.cs b/lib/statistics/Percentile.cs deleted file mode 100644 index c8ef7be9..00000000 --- a/lib/statistics/Percentile.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// Percentile: Distribution Position Measure -/// A statistical measure that indicates the value below which a given percentage -/// of observations falls. Percentiles provide insights into data distribution -/// and are particularly useful for risk assessment and outlier detection. -/// -/// -/// The Percentile calculation process: -/// 1. Sorts values in ascending order -/// 2. Calculates position based on percentile -/// 3. Interpolates between adjacent values -/// 4. Uses mean until period filled -/// -/// Key characteristics: -/// - Range specific value identification -/// - Linear interpolation for precision -/// - Distribution independent -/// - Robust to outliers -/// - Useful for risk metrics -/// -/// Formula: -/// position = (percentile/100) * (n-1) -/// value = v[floor(pos)] + (v[ceil(pos)] - v[floor(pos)]) * (pos - floor(pos)) -/// where n = number of observations, v = sorted values -/// -/// Market Applications: -/// - Value at Risk (VaR) calculation -/// - Risk management metrics -/// - Performance analysis -/// - Volatility assessment -/// - Outlier detection -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Percentile -/// "Risk Management in Trading" - Davis Edwards -/// -/// Note: Particularly useful for risk metrics like VaR -/// -[SkipLocalsInit] -public sealed class Percentile : AbstractBase -{ - private readonly int Period; - private readonly double Percent; - private readonly CircularBuffer _buffer; - private const int MinimumPoints = 2; - - /// The number of points to consider for percentile calculation. - /// The percentile to calculate (0-100). - /// - /// Thrown when period is less than 2 or percent is not between 0 and 100. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Percentile(int period, double percent) - { - ArgumentOutOfRangeException.ThrowIfLessThan(period, MinimumPoints); - ArgumentOutOfRangeException.ThrowIfLessThan(percent, 0); - ArgumentOutOfRangeException.ThrowIfGreaterThan(percent, 100); - - Period = period; - Percent = percent; - WarmupPeriod = MinimumPoints; // Minimum number of points needed for percentile calculation - _buffer = new CircularBuffer(period); - Name = $"Percentile(period={period}, percent={percent})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for percentile calculation. - /// The percentile to calculate (0-100). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Percentile(object source, int period, double percent) : this(period, percent) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static void QuickSort(Span arr, int left, int right) - { - if (left < right) - { - int pivotIndex = Partition(arr, left, right); - QuickSort(arr, left, pivotIndex - 1); - QuickSort(arr, pivotIndex + 1, right); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static int Partition(Span arr, int left, int right) - { - double pivot = arr[right]; - int i = left - 1; - - for (int j = left; j < right; j++) - { - if (arr[j] <= pivot) - { - i++; - (arr[i], arr[j]) = (arr[j], arr[i]); - } - } - - (arr[i + 1], arr[right]) = (arr[right], arr[i + 1]); - return i + 1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculatePercentile(Span sortedValues) - { - double position = (Percent / 100.0) * (sortedValues.Length - 1); - int lowerIndex = (int)Math.Floor(position); - int upperIndex = (int)Math.Ceiling(position); - - if (lowerIndex == upperIndex) - { - return sortedValues[lowerIndex]; - } - - // Linear interpolation between adjacent values - double lowerValue = sortedValues[lowerIndex]; - double upperValue = sortedValues[upperIndex]; - double fraction = position - lowerIndex; - return lowerValue + ((upperValue - lowerValue) * fraction); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double result; - if (_buffer.Count >= Period) - { - // Create a temporary buffer on the stack and sort values - Span values = stackalloc double[Period]; - _buffer.GetSpan().CopyTo(values); - QuickSort(values, 0, values.Length - 1); - - result = CalculatePercentile(values); - } - else - { - // Use average until we have enough data points - result = _buffer.Average(); - } - - IsHot = _buffer.Count >= Period; - return result; - } -} diff --git a/lib/statistics/Skew.cs b/lib/statistics/Skew.cs deleted file mode 100644 index eccc5f04..00000000 --- a/lib/statistics/Skew.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SKEW: Distribution Asymmetry Measure -/// A statistical measure that quantifies the asymmetry of a probability distribution -/// around its mean. Skewness indicates whether deviations from the mean are more -/// likely in one direction than the other. -/// -/// -/// The Skew calculation process: -/// 1. Calculates mean of the data -/// 2. Computes deviations from mean -/// 3. Calculates third moment (cubed deviations) -/// 4. Normalizes by standard deviation cubed -/// -/// Key characteristics: -/// - Measures distribution asymmetry -/// - Positive values indicate right skew -/// - Negative values indicate left skew -/// - Zero indicates symmetry -/// - Scale-independent measure -/// -/// Formula: -/// skew = [√(n(n-1))/(n-2)] * [m₃/s³] -/// where: -/// m₃ = third moment about the mean -/// s = standard deviation -/// n = sample size -/// -/// Market Applications: -/// - Risk assessment in returns -/// - Options pricing models -/// - Trading strategy development -/// - Portfolio risk management -/// - Market sentiment analysis -/// -/// Sources: -/// Fisher-Pearson standardized moment coefficient -/// https://en.wikipedia.org/wiki/Skewness -/// "The Analysis of Financial Time Series" - Ruey S. Tsay -/// -/// Note: Requires minimum of 3 data points for calculation -/// -[SkipLocalsInit] -public sealed class Skew : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 3; - - /// The number of points to consider for skewness calculation. - /// Thrown when period is less than 3. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Skew(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 3 for skewness calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _buffer = new CircularBuffer(period); - Name = $"Skew(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for skewness calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Skew(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double m3, double m2) CalculateMoments(ReadOnlySpan values, double mean) - { - double sumCubedDeviations = 0; - double sumSquaredDeviations = 0; - - for (int i = 0; i < values.Length; i++) - { - double deviation = values[i] - mean; - double squared = deviation * deviation; - sumSquaredDeviations += squared; - sumCubedDeviations += squared * deviation; - } - - double n = values.Length; - return (sumCubedDeviations / n, sumSquaredDeviations / n); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSkewness(double m3, double m2, int n) - { - double s3 = Math.Pow(m2, 1.5); - if (s3 < Epsilon) - return 0; - - return (Math.Sqrt(n * (n - 1)) / (n - 2)) * (m3 / s3); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double skew = 0; - if (_buffer.Count >= MinimumPoints) // Need at least 3 points for skewness - { - ReadOnlySpan values = _buffer.GetSpan(); - double mean = CalculateMean(values); - var (m3, m2) = CalculateMoments(values, mean); - skew = CalculateSkewness(m3, m2, values.Length); - } - - IsHot = _buffer.Count >= Period; - return skew; - } -} diff --git a/lib/statistics/Slope.cs b/lib/statistics/Slope.cs deleted file mode 100644 index cd1dab68..00000000 --- a/lib/statistics/Slope.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SLOPE: Linear Regression Trend Measure -/// A statistical measure that calculates the rate of change using linear regression. -/// Slope indicates the direction and steepness of a trend, providing insights into -/// momentum and potential trend changes. -/// -/// -/// The Slope calculation process: -/// 1. Calculates means of x and y values -/// 2. Computes deviations from means -/// 3. Applies least squares method -/// 4. Provides additional regression statistics -/// -/// Key characteristics: -/// - Measures trend direction and strength -/// - Provides rate of change -/// - Scale-dependent measure -/// - Includes regression statistics -/// - Time-weighted calculation -/// -/// Formula: -/// slope = Σ((x - x̄)(y - ȳ)) / Σ((x - x̄)²) -/// where: -/// x = time points -/// y = price values -/// x̄, ȳ = respective means -/// -/// Market Applications: -/// - Trend identification -/// - Momentum measurement -/// - Support/resistance angles -/// - Price target projection -/// - Trend strength analysis -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Simple_linear_regression -/// "Technical Analysis of Financial Markets" - John J. Murphy -/// -/// Note: Provides additional regression statistics (R², intercept) -/// -[SkipLocalsInit] -public sealed class Slope : AbstractBase -{ - private readonly int _period; - private readonly CircularBuffer _buffer; - private readonly CircularBuffer _timeBuffer; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// Gets the y-intercept of the regression line. - public double? Intercept { get; private set; } - - /// Gets the standard deviation of the y-values. - public double? StdDev { get; private set; } - - /// Gets the R-squared value, indicating regression fit quality. - public double? RSquared { get; private set; } - - /// Gets the last point on the regression line. - public double? Line { get; private set; } - - /// The number of points to consider for slope calculation. - /// Thrown when period is less than or equal to 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Slope(int period) - { - if (period <= 1) - { - throw new ArgumentOutOfRangeException(nameof(period), period, - "Period must be greater than 1 for Slope/Linear Regression."); - } - _period = period; - WarmupPeriod = period; - _buffer = new CircularBuffer(period); - _timeBuffer = new CircularBuffer(period); - Name = $"Slope(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for slope calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Slope(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _timeBuffer.Clear(); - Intercept = null; - StdDev = null; - RSquared = null; - Line = null; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double sumX, double sumY) CalculateSums(ReadOnlySpan values, int count) - { - double sumX = 0, sumY = 0; - for (int i = 0; i < count; i++) - { - sumX += i + 1; - sumY += values[i]; - } - return (sumX, sumY); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double sumSqX, double sumSqY, double sumSqXY) CalculateSquaredSums( - ReadOnlySpan values, int count, double avgX, double avgY) - { - double sumSqX = 0, sumSqY = 0, sumSqXY = 0; - for (int i = 0; i < count; i++) - { - double devX = (i + 1) - avgX; - double devY = values[i] - avgY; - sumSqX += devX * devX; - sumSqY += devY * devY; - sumSqXY += devX * devY; - } - return (sumSqX, sumSqY, sumSqXY); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer.Add(Input.Value, Input.IsNew); - _timeBuffer.Add(Input.Time.Ticks, Input.IsNew); - - double slope = 0; - if (_buffer.Count < MinimumPoints) - { - return slope; // Need at least 2 points - } - - int count = Math.Min(_buffer.Count, _period); - ReadOnlySpan values = _buffer.GetSpan(); - - // Calculate averages - var (sumX, sumY) = CalculateSums(values, count); - double avgX = sumX / count; - double avgY = sumY / count; - - // Least squares regression - var (sumSqX, sumSqY, sumSqXY) = CalculateSquaredSums(values, count, avgX, avgY); - - if (sumSqX > Epsilon) - { - // Calculate slope and related statistics - slope = sumSqXY / sumSqX; - Intercept = avgY - (slope * avgX); - - // Calculate Standard Deviation and R-Squared - double stdDevX = Math.Sqrt(sumSqX / count); - double stdDevY = Math.Sqrt(sumSqY / count); - StdDev = stdDevY; - - double stdDevProduct = stdDevX * stdDevY; - if (stdDevProduct > Epsilon) - { - double r = sumSqXY / stdDevProduct / count; - RSquared = r * r; - } - - // Calculate regression line endpoint - Line = (slope * count) + Intercept; - } - else - { - Intercept = null; - StdDev = null; - RSquared = null; - Line = null; - } - - IsHot = _buffer.Count == _period; - return slope; - } -} diff --git a/lib/statistics/Spearman.cs b/lib/statistics/Spearman.cs deleted file mode 100644 index b3b525ad..00000000 --- a/lib/statistics/Spearman.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SPEARMAN: Spearman's Rank Correlation Coefficient -/// A nonparametric measure of rank correlation that assesses the monotonic relationship -/// between two variables. Unlike Pearson correlation, Spearman correlation evaluates -/// the relationship based on ranked values rather than raw data. -/// -/// -/// The Spearman calculation process: -/// 1. Ranks both sets of values -/// 2. Calculates correlation between ranks -/// 3. Handles ties by averaging ranks -/// -/// Key characteristics: -/// - Resistant to outliers -/// - Detects monotonic relationships -/// - Range: -1 to +1 -/// - Distribution-free measure -/// - Handles non-linear relationships -/// -/// Formula: -/// ρ = Cov(rank(X), rank(Y)) / (σrank(X) * σrank(Y)) -/// where: -/// X, Y = variables -/// rank() = ranking function -/// Cov = covariance -/// σ = standard deviation -/// -/// Market Applications: -/// - Technical analysis -/// - Risk assessment -/// - Market correlation studies -/// - Trend analysis -/// - Pattern recognition -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient -/// "Nonparametric Statistics for Non-Statisticians" - Gregory W. Corder -/// -/// Note: More robust to outliers than Pearson correlation -/// -[SkipLocalsInit] -public sealed class Spearman : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _xValues; - private readonly CircularBuffer _yValues; - private readonly CircularBuffer _xRanks; - private readonly CircularBuffer _yRanks; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for Spearman correlation calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Spearman(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for Spearman correlation calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _xValues = new CircularBuffer(period); - _yValues = new CircularBuffer(period); - _xRanks = new CircularBuffer(period); - _yRanks = new CircularBuffer(period); - Name = $"Spearman(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for Spearman correlation calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Spearman(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _xValues.Clear(); - _yValues.Clear(); - _xRanks.Clear(); - _yRanks.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double[] CalculateRanks(ReadOnlySpan values) - { - int n = values.Length; - var pairs = new (double value, int index)[n]; - for (int i = 0; i < n; i++) - { - pairs[i] = double.IsNaN(values[i]) ? (double.NaN, i) : (values[i], i); - } - - // Sort non-NaN values - var validPairs = pairs.Where(p => !double.IsNaN(p.value)).OrderBy(p => p.value).ToArray(); - var ranks = new double[n]; - Array.Fill(ranks, double.NaN); - - for (int i = 0; i < validPairs.Length;) - { - int j = i; - // Find ties - while (j < validPairs.Length - 1 && Math.Abs(validPairs[j].value - validPairs[j + 1].value) < Epsilon) - { - j++; - } - - // Average rank for ties - double rank = ((i + j) / 2.0) + 1; - for (int k = i; k <= j; k++) - { - ranks[validPairs[k].index] = rank; - } - i = j + 1; - } - - return ranks; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateCovariance(CircularBuffer xBuffer, CircularBuffer yBuffer, double xMean, double yMean) - { - var xSpan = xBuffer.GetSpan(); - var ySpan = yBuffer.GetSpan(); - double covariance = 0; - int count = 0; - - for (int i = 0; i < xSpan.Length; i++) - { - if (!double.IsNaN(xSpan[i]) && !double.IsNaN(ySpan[i])) - { - covariance += (xSpan[i] - xMean) * (ySpan[i] - yMean); - count++; - } - } - - return count > 0 ? covariance / count : double.NaN; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateStandardDeviation(CircularBuffer buffer, double mean) - { - var span = buffer.GetSpan(); - double sumSquaredDeviations = 0; - int count = 0; - - for (int i = 0; i < span.Length; i++) - { - if (!double.IsNaN(span[i])) - { - double deviation = span[i] - mean; - sumSquaredDeviations += deviation * deviation; - count++; - } - } - - return count > 0 ? Math.Sqrt(sumSquaredDeviations / count) : double.NaN; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _xValues.Add(Input.Value, Input.IsNew); - _yValues.Add(Input2.Value, Input.IsNew); - - double correlation = 0; - if (_xValues.Count >= MinimumPoints && _yValues.Count >= MinimumPoints) - { - // Convert values to ranks - var xRanks = CalculateRanks(_xValues.GetSpan()); - var yRanks = CalculateRanks(_yValues.GetSpan()); - - // Store ranks in buffers for statistical calculations - _xRanks.Clear(); - _yRanks.Clear(); - for (int i = 0; i < xRanks.Length; i++) - { - _xRanks.Add(xRanks[i], true); - _yRanks.Add(yRanks[i], true); - } - - // Use CircularBuffer's optimized Average() method - double xMean = _xRanks.Average(); - double yMean = _yRanks.Average(); - - if (!double.IsNaN(xMean) && !double.IsNaN(yMean)) - { - double covariance = CalculateCovariance(_xRanks, _yRanks, xMean, yMean); - double xStdDev = CalculateStandardDeviation(_xRanks, xMean); - double yStdDev = CalculateStandardDeviation(_yRanks, yMean); - - if (!double.IsNaN(covariance) && xStdDev > Epsilon && yStdDev > Epsilon) - { - correlation = covariance / (xStdDev * yStdDev); - } - } - } - - IsHot = _xValues.Count >= Period && _yValues.Count >= Period; - return correlation; - } -} diff --git a/lib/statistics/Stddev.cs b/lib/statistics/Stddev.cs deleted file mode 100644 index a1639804..00000000 --- a/lib/statistics/Stddev.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// STDDEV: Standard Deviation Volatility Measure -/// A statistical measure that quantifies the amount of variation or dispersion -/// in a dataset. Standard deviation is widely used in finance as a measure of -/// volatility and risk assessment. -/// -/// -/// The StdDev calculation process: -/// 1. Calculates mean of the data -/// 2. Computes squared deviations from mean -/// 3. Averages squared deviations -/// 4. Takes square root of average -/// -/// Key characteristics: -/// - Measures data dispersion -/// - Same units as input data -/// - Sensitive to outliers -/// - Population or sample versions -/// - Key volatility indicator -/// -/// Formula: -/// Population: σ = √(Σ(x - μ)² / N) -/// Sample: s = √(Σ(x - x̄)² / (n-1)) -/// where: -/// x = values -/// μ, x̄ = mean -/// N, n = count -/// -/// Market Applications: -/// - Volatility measurement -/// - Risk assessment -/// - Bollinger Bands -/// - Option pricing -/// - Portfolio management -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Standard_deviation -/// "Options, Futures, and Other Derivatives" - John C. Hull -/// -/// Note: Foundation for many volatility-based indicators -/// -[SkipLocalsInit] -public sealed class Stddev : AbstractBase -{ - private readonly bool IsPopulation; - private readonly CircularBuffer _buffer; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for standard deviation calculation. - /// True for population stddev, false for sample stddev (default). - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Stddev(int period, bool isPopulation = false) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2."); - } - IsPopulation = isPopulation; - WarmupPeriod = 0; - _buffer = new CircularBuffer(period); - Name = $"Stddev(period={period}, population={isPopulation})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for standard deviation calculation. - /// True for population stddev, false for sample stddev (default). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Stddev(object source, int period, bool isPopulation = false) : this(period, isPopulation) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSumSquaredDeviations(ReadOnlySpan values, double mean) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - double diff = values[i] - mean; - sum += diff * diff; - } - return sum; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double stddev = 0; - if (_buffer.Count > 1) - { - ReadOnlySpan values = _buffer.GetSpan(); - double mean = CalculateMean(values); - double sumOfSquaredDifferences = CalculateSumSquaredDeviations(values, mean); - - // Use appropriate divisor based on population/sample calculation - double divisor = IsPopulation ? _buffer.Count : _buffer.Count - 1; - double variance = sumOfSquaredDifferences / divisor; - stddev = Math.Sqrt(variance); - } - - IsHot = true; // StdDev calc is valid from bar 1 - return stddev; - } -} diff --git a/lib/statistics/Theil.cs b/lib/statistics/Theil.cs deleted file mode 100644 index 3ebcb7b5..00000000 --- a/lib/statistics/Theil.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// THEIL: Theil's U Statistics (U1, U2) -/// A statistical measure that quantifies the accuracy of forecasts compared to actual values -/// and naive forecasts. -/// -/// -/// The Theil's U calculation process: -/// 1. Calculate U1 statistic (relative accuracy) -/// 2. Calculate U2 statistic (comparison with naive forecast) -/// -/// Key characteristics: -/// - U1 ranges from 0 to 1, with 0 indicating perfect forecast -/// - U2 < 1: forecast better than naive forecast -/// - U2 = 1: forecast equal to naive forecast -/// - U2 > 1: forecast worse than naive forecast -/// -/// Formula: -/// U1 = √[Σ(Ft - At)² / Σ(At)²] -/// U2 = √[Σ(Ft - At)² / Σ(At - At-1)²] -/// where: -/// Ft = forecasted value -/// At = actual value -/// At-1 = previous actual value -/// -/// Market Applications: -/// - Evaluating forecast accuracy -/// - Comparing forecasting models -/// - Assessing forecasting methods -/// - Model selection -/// - Performance analysis -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Theil%27s_U -/// "Forecasting: Principles and Practice" - Rob J Hyndman -/// -/// Note: Should be used alongside other accuracy measures -/// -[SkipLocalsInit] -public sealed class Theil : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _actual; - private readonly CircularBuffer _forecast; - private const int MinimumPoints = 2; - - /// - /// Gets the U2 statistic comparing forecast with naive forecast - /// - public double U2 { get; private set; } - - /// The number of points to consider for Theil's U calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Theil(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for Theil's U calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _actual = new CircularBuffer(period); - _forecast = new CircularBuffer(period); - Name = $"Theil(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for Theil's U calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Theil(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _actual.Clear(); - _forecast.Clear(); - U2 = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSquaredSum(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i] * values[i]; - } - return sum; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSquaredErrorSum(ReadOnlySpan forecast, ReadOnlySpan actual) - { - double sum = 0; - for (int i = 0; i < forecast.Length; i++) - { - double error = forecast[i] - actual[i]; - sum += error * error; - } - return sum; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateNaiveSquaredErrorSum(ReadOnlySpan actual) - { - double sum = 0; - for (int i = 1; i < actual.Length; i++) - { - double error = actual[i] - actual[i - 1]; - sum += error * error; - } - return sum; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _actual.Add(Input.Value, Input.IsNew); - _forecast.Add(Input2.Value, Input.IsNew); - - double u1 = 0; - if (_actual.Count >= MinimumPoints && _forecast.Count >= MinimumPoints) - { - ReadOnlySpan actualValues = _actual.GetSpan(); - ReadOnlySpan forecastValues = _forecast.GetSpan(); - - double squaredErrorSum = CalculateSquaredErrorSum(forecastValues, actualValues); - double squaredActualSum = CalculateSquaredSum(actualValues); - double naiveSquaredErrorSum = CalculateNaiveSquaredErrorSum(actualValues); - - if (squaredActualSum > double.Epsilon) - { - u1 = Math.Sqrt(squaredErrorSum / squaredActualSum); - } - - if (naiveSquaredErrorSum > double.Epsilon) - { - U2 = Math.Sqrt(squaredErrorSum / naiveSquaredErrorSum); - } - } - - IsHot = _actual.Count >= Period && _forecast.Count >= Period; - return u1; - } -} diff --git a/lib/statistics/Tsf.cs b/lib/statistics/Tsf.cs deleted file mode 100644 index 6aa9b798..00000000 --- a/lib/statistics/Tsf.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TSF: Time Series Forecast -/// A statistical indicator that provides a linear regression forecast of future values -/// based on historical data. It includes both the forecast value and a confidence interval. -/// -/// -/// The Time Series Forecast calculation process: -/// 1. Calculates linear regression on the input data -/// 2. Extrapolates the regression line to forecast future values -/// 3. Computes confidence intervals based on the standard error of the forecast -/// -/// Key characteristics: -/// - Provides point forecast and confidence interval -/// - Based on linear regression principles -/// - Assumes trend continuity -/// - Sensitive to recent data changes -/// - Useful for short-term predictions -/// -/// Formula: -/// Forecast = a + b * (n + 1) -/// where: -/// a = y-intercept -/// b = slope -/// n = number of periods -/// -/// Confidence Interval = Forecast ± (t * SE) -/// where: -/// t = t-value for desired confidence level -/// SE = Standard Error of the forecast -/// -/// Market Applications: -/// - Price target estimation -/// - Trend analysis -/// - Risk assessment -/// - Trading strategy development -/// - Market behavior prediction -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Time_series -/// "Forecasting: Principles and Practice" - Rob J Hyndman and George Athanasopoulos -/// -/// Note: Assumes linear trend in the data and may not capture non-linear patterns -/// -[SkipLocalsInit] -public sealed class Tsf : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _values; - private const int MinimumPoints = 2; - - /// - /// The forecasted value for the next period. - /// - public double Forecast { get; private set; } - - /// - /// The lower bound of the confidence interval. - /// - public double LowerBound { get; private set; } - - /// - /// The upper bound of the confidence interval. - /// - public double UpperBound { get; private set; } - - /// The number of historical data points to consider for forecasting. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tsf(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for time series forecasting."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _values = new CircularBuffer(period); - Name = $"TSF(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of historical data points to consider for forecasting. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tsf(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _values.Clear(); - Forecast = 0; - LowerBound = 0; - UpperBound = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double slope, double intercept) CalculateLinearRegression(ReadOnlySpan values) - { - int n = values.Length; - double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0; - - for (int i = 0; i < n; i++) - { - double x = i + 1; - double y = values[i]; - sumX += x; - sumY += y; - sumXY += x * y; - sumX2 += x * x; - } - - double slope = ((n * sumXY) - (sumX * sumY)) / ((n * sumX2) - (sumX * sumX)); - double intercept = (sumY - (slope * sumX)) / n; - - return (slope, intercept); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateStandardError(ReadOnlySpan values, double slope, double intercept) - { - int n = values.Length; - double sumSquaredResiduals = 0; - - for (int i = 0; i < n; i++) - { - double x = i + 1; - double y = values[i]; - double predicted = (slope * x) + intercept; - double residual = y - predicted; - sumSquaredResiduals += residual * residual; - } - - return Math.Sqrt(sumSquaredResiduals / (n - 2)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - _values.Add(Input.Value, Input.IsNew); - - if (_values.Count >= MinimumPoints) - { - ReadOnlySpan values = _values.GetSpan(); - - var (slope, intercept) = CalculateLinearRegression(values); - - // Calculate forecast for the next period - Forecast = (slope * (Period + 1)) + intercept; - - // Calculate standard error - double standardError = CalculateStandardError(values, slope, intercept); - - // Calculate confidence interval (using t-distribution with n-2 degrees of freedom) - double tValue = 1.96; // Approximation for 95% confidence interval - double marginOfError = tValue * standardError * Math.Sqrt(1 + (1.0 / Period)); - - LowerBound = Forecast - marginOfError; - UpperBound = Forecast + marginOfError; - } - - IsHot = _values.Count >= Period; - return Forecast; - } -} diff --git a/lib/statistics/Variance.cs b/lib/statistics/Variance.cs deleted file mode 100644 index ee4e043b..00000000 --- a/lib/statistics/Variance.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VARIANCE: Squared Deviation Risk Measure -/// A statistical measure that quantifies the spread of data points around their -/// mean value. Variance is fundamental to risk assessment and portfolio theory, -/// providing the basis for many financial models. -/// -/// -/// The Variance calculation process: -/// 1. Calculates mean of the data -/// 2. Computes squared deviations from mean -/// 3. Sums squared deviations -/// 4. Divides by n or (n-1) -/// -/// Key characteristics: -/// - Measures data dispersion -/// - Squared units of input data -/// - Always non-negative -/// - Population or sample versions -/// - Foundation for risk metrics -/// -/// Formula: -/// Population: σ² = Σ(x - μ)² / N -/// Sample: s² = Σ(x - x̄)² / (n-1) -/// where: -/// x = values -/// μ, x̄ = mean -/// N, n = count -/// -/// Market Applications: -/// - Portfolio optimization -/// - Risk measurement -/// - Modern Portfolio Theory -/// - Asset allocation -/// - Volatility analysis -/// -/// Sources: -/// Harry Markowitz - "Portfolio Selection" (1952) -/// https://en.wikipedia.org/wiki/Variance -/// -/// Note: Basis for Modern Portfolio Theory and risk models -/// -[SkipLocalsInit] -public sealed class Variance : AbstractBase -{ - private readonly bool IsPopulation; - private readonly CircularBuffer _buffer; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for variance calculation. - /// True for population variance, false for sample variance (default). - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Variance(int period, bool isPopulation = false) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2."); - } - IsPopulation = isPopulation; - WarmupPeriod = 0; - _buffer = new CircularBuffer(period); - Name = $"Variance(period={period}, population={isPopulation})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for variance calculation. - /// True for population variance, false for sample variance (default). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Variance(object source, int period, bool isPopulation = false) : this(period, isPopulation) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateSumSquaredDeviations(ReadOnlySpan values, double mean) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - double diff = values[i] - mean; - sum += diff * diff; - } - return sum; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double variance = 0; - if (_buffer.Count > 1) - { - ReadOnlySpan values = _buffer.GetSpan(); - double mean = CalculateMean(values); - double sumOfSquaredDifferences = CalculateSumSquaredDeviations(values, mean); - - // Use appropriate divisor based on population/sample calculation - double divisor = IsPopulation ? _buffer.Count : _buffer.Count - 1; - variance = sumOfSquaredDifferences / divisor; - } - - IsHot = true; - return variance; - } -} diff --git a/lib/statistics/Zscore.cs b/lib/statistics/Zscore.cs deleted file mode 100644 index 6af78b57..00000000 --- a/lib/statistics/Zscore.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ZSCORE: Standardized Distance Measure -/// A statistical measure that indicates how many standard deviations an observation -/// is from the mean. Z-scores normalize data to a standard scale, making it useful -/// for comparing values across different distributions. -/// -/// -/// The Zscore calculation process: -/// 1. Calculates mean of the period -/// 2. Computes standard deviation -/// 3. Measures distance from mean -/// 4. Normalizes by standard deviation -/// -/// Key characteristics: -/// - Scale-independent measure -/// - Symmetric around zero -/// - Normal distribution context -/// - Outlier identification -/// - Comparative analysis tool -/// -/// Formula: -/// Z = (x - μ) / σ -/// where: -/// x = current value -/// μ = mean -/// σ = standard deviation -/// -/// Market Applications: -/// - Mean reversion strategies -/// - Overbought/oversold signals -/// - Volatility breakouts -/// - Cross-asset comparison -/// - Statistical arbitrage -/// -/// Sources: -/// https://en.wikipedia.org/wiki/Standard_score -/// "Statistical Analysis in Trading" - Technical Analysis -/// -/// Note: Assumes approximately normal distribution -/// -[SkipLocalsInit] -public sealed class Zscore : AbstractBase -{ - private readonly int Period; - private readonly CircularBuffer _buffer; - private const double Epsilon = 1e-10; - private const int MinimumPoints = 2; - - /// The number of points to consider for Z-score calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Zscore(int period) - { - if (period < MinimumPoints) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2 for Z-score calculation."); - } - Period = period; - WarmupPeriod = MinimumPoints; - _buffer = new CircularBuffer(period); - Name = $"ZScore(period={period})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of points to consider for Z-score calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Zscore(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateStandardDeviation(ReadOnlySpan values, double mean) - { - double sumSquaredDeviations = 0; - for (int i = 0; i < values.Length; i++) - { - double deviation = values[i] - mean; - sumSquaredDeviations += deviation * deviation; - } - return Math.Sqrt(sumSquaredDeviations / (values.Length - 1)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double zScore = 0; - if (_buffer.Count >= MinimumPoints) // Need at least 2 points for standard deviation - { - ReadOnlySpan values = _buffer.GetSpan(); - double mean = CalculateMean(values); - double standardDeviation = CalculateStandardDeviation(values, mean); - - if (standardDeviation > Epsilon) // Avoid division by zero - { - zScore = (Input.Value - mean) / standardDeviation; - } - } - - IsHot = _buffer.Count >= Period; - return zScore; - } -} diff --git a/lib/statistics/_list.md b/lib/statistics/_list.md deleted file mode 100644 index 2c7ec039..00000000 --- a/lib/statistics/_list.md +++ /dev/null @@ -1,26 +0,0 @@ -# Statistics indicators -Done: 22, Todo: 1 - -✔️ BETA - Beta coefficient measuring volatility relative to market -✔️ CORR - Correlation coefficient between two series -✔️ COVAR - Covariance between two series -✔️ CURVATURE - Curvature of a time series -✔️ ENTROPY - Information entropy of a series -✔️ GRANGER - Granger causality test -✔️ HURST - Hurst exponent for trend strength -✔️ KENDALL - Kendall rank correlation -✔️ KURTOSIS - Kurtosis measuring tail extremity -✔️ MAX - Maximum value over period -✔️ MEDIAN - Median value over period -✔️ MIN - Minimum value over period -✔️ MODE - Mode (most frequent value) -✔️ PERCENTILE - Percentile rank calculation -✔️ SKEW - Skewness measuring distribution asymmetry -✔️ SLOPE - Linear regression slope -✔️ SPEARMAN - Spearman rank correlation -✔️ STDDEV - Standard deviation -✔️ THEIL - Theil's U statistics for forecast accuracy -✔️ TSF - Time series forecast -✔️ VARIANCE - Statistical variance -✔️ ZSCORE - Z-score standardization -COINTEGRATION - Test for cointegrated series diff --git a/lib/volatility/Adr.cs b/lib/volatility/Adr.cs deleted file mode 100644 index 7137746e..00000000 --- a/lib/volatility/Adr.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ADR: Average Daily Range -/// A volatility indicator that measures the average range of price movement over -/// a specified period. It helps identify normal trading ranges and potential -/// breakout levels. -/// -/// -/// The ADR calculation process: -/// 1. Calculate daily range (High - Low) -/// 2. Apply SMA to daily ranges -/// 3. Updates with each new price bar -/// -/// Key characteristics: -/// - Simple volatility measure -/// - Period-based average -/// - Trend independent -/// - Absolute price measure -/// - Support/resistance aid -/// -/// Formula: -/// Daily Range = High - Low -/// ADR = SMA(Daily Range, period) -/// -/// Market Applications: -/// - Position sizing -/// - Volatility analysis -/// - Support/resistance levels -/// - Breakout identification -/// - Risk assessment -/// -/// Note: Simpler alternative to ATR, doesn't consider gaps -/// -[SkipLocalsInit] -public sealed class Adr : AbstractBase -{ - private readonly Sma _ma; - private const int DefaultPeriod = 14; - - /// The number of periods for ADR calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adr(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _ma = new(period); - WarmupPeriod = period; - Name = $"ADR({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for ADR calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adr(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate daily range - double range = BarInput.High - BarInput.Low; - - // Apply SMA smoothing - return _ma.Calc(range, BarInput.IsNew); - } -} diff --git a/lib/volatility/Ap.cs b/lib/volatility/Ap.cs deleted file mode 100644 index 48d57213..00000000 --- a/lib/volatility/Ap.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// AP: Andrew's Pitchfork -/// A trend channel tool that uses three points to create a channel with a median -/// line and two parallel lines. It helps identify potential support and resistance -/// levels based on market pivots. -/// -/// -/// The AP calculation process: -/// 1. Use three pivot points (P0, P1, P2) -/// 2. Calculate median line from P0 to midpoint of P1-P2 -/// 3. Draw parallel lines at P1 and P2 -/// 4. Project all lines forward -/// -/// Key characteristics: -/// - Trend channel tool -/// - Support/resistance levels -/// - Price projection -/// - Market geometry -/// - Pivot-based analysis -/// -/// Formula: -/// Median Line = Line from P0 to (P1 + P2)/2 -/// Upper Line = Parallel to median at P1 -/// Lower Line = Parallel to median at P2 -/// -/// Market Applications: -/// - Trend analysis -/// - Support/resistance -/// - Price targets -/// - Channel trading -/// - Market structure -/// -/// Sources: -/// Dr. Alan Andrews -/// https://www.investopedia.com/terms/a/andrewspitchfork.asp -/// -/// Note: Returns median line value for current price level -/// -[SkipLocalsInit] -public sealed class Ap : AbstractBase -{ - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private readonly CircularBuffer _closes; - private const int DefaultPeriod = 20; - - /// The lookback period for pivot points (default 20). - /// Thrown when period is less than 3. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ap(int period = DefaultPeriod) - { - if (period < 3) - throw new ArgumentOutOfRangeException(nameof(period)); - - _highs = new(period); - _lows = new(period); - _closes = new(period); - WarmupPeriod = period; - Name = $"AP({period})"; - } - - /// The data source object that publishes updates. - /// The lookback period for pivot points. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ap(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double x, double y) FindPivot(CircularBuffer highs, CircularBuffer lows, CircularBuffer closes, int offset) - { - double high = highs[offset]; - double low = lows[offset]; - double close = closes[offset]; - return (offset, (high + low + close) / 3.0); // Simple pivot point calculation - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Store price data - _highs.Add(BarInput.High, BarInput.IsNew); - _lows.Add(BarInput.Low, BarInput.IsNew); - _closes.Add(BarInput.Close, BarInput.IsNew); - - if (_index < WarmupPeriod) - return BarInput.Close; - - // Find three pivot points - var p0 = FindPivot(_highs, _lows, _closes, 2); - var p1 = FindPivot(_highs, _lows, _closes, 1); - var p2 = FindPivot(_highs, _lows, _closes, 0); - - // Calculate midpoint of P1-P2 - double midX = (p1.x + p2.x) / 2.0; - double midY = (p1.y + p2.y) / 2.0; - - // Calculate slope of median line - double slope = (midY - p0.y) / (midX - p0.x); - - // Project median line to current bar - double currentX = _index - p0.x; - return p0.y + (slope * currentX); - } -} diff --git a/lib/volatility/Atr.cs b/lib/volatility/Atr.cs deleted file mode 100644 index 2810f5a1..00000000 --- a/lib/volatility/Atr.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ATR: Average True Range -/// A technical indicator that measures market volatility by decomposing the entire -/// range of an asset's price for a period. ATR accounts for gaps between periods -/// and provides a comprehensive view of price volatility. -/// -/// -/// The ATR calculation process: -/// 1. Calculates True Range (TR) as maximum of: -/// - Current High - Current Low -/// - |Current High - Previous Close| -/// - |Current Low - Previous Close| -/// 2. Applies RMA smoothing to TR values -/// 3. Updates with each new price bar -/// 4. Adapts to changing volatility -/// -/// Key characteristics: -/// - Absolute price measure -/// - Gap-inclusive calculation -/// - Trend independent -/// - Volatility focused -/// - Smoothed output -/// -/// Formula: -/// TR = max(high-low, |high-prevClose|, |low-prevClose|) -/// ATR = RMA(TR, period) -/// -/// Market Applications: -/// - Position sizing -/// - Stop loss placement -/// - Volatility breakouts -/// - Risk assessment -/// - Entry/exit timing -/// -/// Sources: -/// J. Welles Wilder - "New Concepts in Technical Trading Systems" -/// https://www.investopedia.com/terms/a/atr.asp -/// -/// Note: Higher ATR indicates higher volatility -/// -[SkipLocalsInit] -public sealed class Atr : AbstractBase -{ - public double Tr { get; private set; } - private readonly Rma _ma; - private double _prevClose, _p_prevClose; - - /// The number of periods for ATR calculation. - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Atr(int period) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 1."); - } - _ma = new(period, useSma: true); - WarmupPeriod = _ma.WarmupPeriod; - Name = $"ATR({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for ATR calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Atr(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _ma.Init(); - _prevClose = double.NaN; - Tr = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevClose = _prevClose; - } - else - { - _prevClose = _p_prevClose; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateTrueRange(double high, double low, double prevClose) - { - double highLowRange = high - low; - double highPrevCloseRange = Math.Abs(high - prevClose); - double lowPrevCloseRange = Math.Abs(low - prevClose); - - return Math.Max(highLowRange, Math.Max(highPrevCloseRange, lowPrevCloseRange)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - if (_index == 1) - { - // First bar uses simple high-low range - Tr = BarInput.High - BarInput.Low; - _prevClose = BarInput.Close; - } - else - { - // Calculate True Range as maximum of three measures - Tr = CalculateTrueRange(BarInput.High, BarInput.Low, _prevClose); - } - - // Apply RMA smoothing to True Range - _ma.Calc(new TValue(Input.Time, Tr, BarInput.IsNew)); - - IsHot = _ma.IsHot; - _prevClose = BarInput.Close; - return _ma.Value; - } -} diff --git a/lib/volatility/Atrp.cs b/lib/volatility/Atrp.cs deleted file mode 100644 index 193c2909..00000000 --- a/lib/volatility/Atrp.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ATRP: Average True Range Percent -/// A volatility indicator that expresses ATR as a percentage of current price. -/// This normalization allows for comparison across different price levels and -/// instruments. -/// -/// -/// The ATRP calculation process: -/// 1. Calculate ATR normally -/// 2. Divide by current price -/// 3. Multiply by 100 for percentage -/// -/// Key characteristics: -/// - Normalized volatility measure -/// - Price-independent comparison -/// - Percentage output -/// - Cross-market analysis -/// - Relative volatility measure -/// -/// Formula: -/// ATRP = (ATR / Close) * 100 -/// -/// Market Applications: -/// - Cross-market comparison -/// - Position sizing -/// - Volatility analysis -/// - Risk assessment -/// - Market comparison -/// -/// Note: More suitable for comparing different instruments than raw ATR -/// -[SkipLocalsInit] -public sealed class Atrp : AbstractBase -{ - private readonly Atr _atr; - private const int DefaultPeriod = 14; - private const double ScalingFactor = 100.0; - - /// The number of periods for ATR calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Atrp(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _atr = new(period); - WarmupPeriod = period; - Name = $"ATRP({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for ATR calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Atrp(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate ATR - double atr = _atr.Calc(BarInput); - - // Convert to percentage of price - return Math.Abs(BarInput.Close) > double.Epsilon - ? (atr / BarInput.Close) * ScalingFactor - : 0.0; - } -} diff --git a/lib/volatility/Atrs.cs b/lib/volatility/Atrs.cs deleted file mode 100644 index 352a2291..00000000 --- a/lib/volatility/Atrs.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ATRS: ATR Trailing Stop -/// A volatility-based trailing stop indicator that uses ATR to dynamically adjust -/// stop levels. It helps maintain position while allowing for normal market -/// fluctuations. -/// -/// -/// The ATRS calculation process: -/// 1. Calculate ATR -/// 2. Multiply ATR by factor -/// 3. Apply trailing logic based on trend -/// 4. Update stop levels -/// -/// Key characteristics: -/// - Dynamic stop levels -/// - Trend-following -/// - Volatility-based -/// - Position protection -/// - Risk management -/// -/// Formula: -/// Long Stop = High - (ATR * Factor) -/// Short Stop = Low + (ATR * Factor) -/// where Factor is multiplier for ATR (default 2.0) -/// -/// Market Applications: -/// - Stop loss placement -/// - Position management -/// - Trend following -/// - Risk control -/// - Exit strategy -/// -/// Note: Returns stop level based on current trend -/// -[SkipLocalsInit] -public sealed class Atrs : AbstractBase -{ - private readonly Atr _atr; - private double _prevStop; - private double _p_prevStop; - private bool _isLong; - private bool _p_isLong; - private const int DefaultPeriod = 14; - private const double DefaultFactor = 2.0; - - /// - /// Gets the current trend direction (true for long, false for short) - /// - public bool IsLong => _isLong; - - /// The number of periods for ATR calculation (default 14). - /// The multiplier for ATR (default 2.0). - /// Thrown when period is less than 1 or factor is less than or equal to 0. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Atrs(int period = DefaultPeriod, double factor = DefaultFactor) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - if (factor <= 0) - throw new ArgumentOutOfRangeException(nameof(factor)); - - _atr = new(period); - Factor = factor; - WarmupPeriod = period; - Name = $"ATRS({period},{factor:F1})"; - } - - /// The data source object that publishes updates. - /// The number of periods for ATR calculation. - /// The multiplier for ATR. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Atrs(object source, int period = DefaultPeriod, double factor = DefaultFactor) : this(period, factor) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - /// - /// Gets or sets the ATR multiplier factor - /// - public double Factor { get; set; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _atr.Init(); - _prevStop = double.NaN; - _isLong = true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevStop = _prevStop; - _p_isLong = _isLong; - } - else - { - _prevStop = _p_prevStop; - _isLong = _p_isLong; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate ATR - double atr = _atr.Calc(BarInput); - double atrBand = atr * Factor; - - if (_index == 1 || double.IsNaN(_prevStop)) - { - // Initialize stop level - _isLong = BarInput.Close > BarInput.Open; - _prevStop = _isLong ? BarInput.Low - atrBand : BarInput.High + atrBand; - return _prevStop; - } - - // Update stop level based on trend - if (_isLong) - { - double newStop = BarInput.High - atrBand; - if (BarInput.Close < _prevStop) - { - _isLong = false; - _prevStop = BarInput.High + atrBand; - } - else if (newStop > _prevStop) - { - _prevStop = newStop; - } - } - else - { - double newStop = BarInput.Low + atrBand; - if (BarInput.Close > _prevStop) - { - _isLong = true; - _prevStop = BarInput.Low - atrBand; - } - else if (newStop < _prevStop) - { - _prevStop = newStop; - } - } - - return _prevStop; - } -} diff --git a/lib/volatility/Bband.cs b/lib/volatility/Bband.cs deleted file mode 100644 index 19226928..00000000 --- a/lib/volatility/Bband.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// BBAND: Bollinger Bands® -/// A technical analysis tool that creates a band of three lines: -/// - Middle Band: n-period simple moving average (SMA) -/// - Upper Band: Middle Band + (standard deviation * multiplier) -/// - Lower Band: Middle Band - (standard deviation * multiplier) -/// -/// -/// The Bollinger Bands calculation process: -/// 1. Calculate the middle band (SMA of closing prices) -/// 2. Calculate the standard deviation of prices -/// 3. Upper and lower bands are the middle band +/- standard deviation * multiplier -/// -/// Key characteristics: -/// - Adapts to volatility -/// - Default period is 20 days -/// - Default multiplier is 2.0 -/// - Returns three bands (upper, middle, lower) -/// - Wider bands indicate higher volatility -/// - Narrower bands indicate lower volatility -/// -/// Formula: -/// Middle Band = SMA(Close, period) -/// Standard Deviation = SQRT(SUM((Close - Middle Band)^2) / period) -/// Upper Band = Middle Band + (multiplier * Standard Deviation) -/// Lower Band = Middle Band - (multiplier * Standard Deviation) -/// -/// Market Applications: -/// - Volatility measurement -/// - Overbought/oversold identification -/// - Price breakout detection -/// - Trend strength analysis -/// - Dynamic support/resistance levels -/// -/// Sources: -/// John Bollinger (1980s) -/// https://www.bollingerbands.com -/// -/// Note: Returns three values: upper, middle, and lower bands -/// -[SkipLocalsInit] -public sealed class Bband : AbstractBase -{ - private readonly int _period; - private readonly double _multiplier; - private readonly CircularBuffer _prices; - private double _middleBand; - private double _upperBand; - private double _lowerBand; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Bband(int period = 20, double multiplier = 2.0) - { - _period = period; - _multiplier = multiplier; - WarmupPeriod = period; - Name = $"BBAND({_period},{_multiplier})"; - _prices = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Bband(object source, int period = 20, double multiplier = 2.0) : this(period, multiplier) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _middleBand = 0; - _upperBand = 0; - _lowerBand = 0; - _prices.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Add current price to buffer - _prices.Add(BarInput.Close); - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate middle band (SMA) - _middleBand = _prices.Average(); - - // Calculate standard deviation - double sumSquaredDeviations = 0; - for (int i = 0; i < _period; i++) - { - double deviation = _prices[i] - _middleBand; - sumSquaredDeviations += deviation * deviation; - } - double standardDeviation = Math.Sqrt(sumSquaredDeviations / _period); - - // Calculate bands - double bandWidth = _multiplier * standardDeviation; - _upperBand = _middleBand + bandWidth; - _lowerBand = _middleBand - bandWidth; - - IsHot = _index >= WarmupPeriod; - return _middleBand; // Return middle band as primary value - } - - /// - /// Gets the upper band value - /// - public double UpperBand => _upperBand; - - /// - /// Gets the middle band value (SMA) - /// - public double MiddleBand => _middleBand; - - /// - /// Gets the lower band value - /// - public double LowerBand => _lowerBand; -} diff --git a/lib/volatility/Ccv.cs b/lib/volatility/Ccv.cs deleted file mode 100644 index 6514b7a4..00000000 --- a/lib/volatility/Ccv.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CCV: Close-to-Close Volatility -/// A measure of price volatility that uses only closing prices, -/// calculated as the standard deviation of logarithmic returns. -/// -/// -/// The CCV calculation process: -/// 1. Calculate logarithmic returns: ln(Close[t]/Close[t-1]) -/// 2. Calculate standard deviation of returns over the period -/// 3. Annualize by multiplying by sqrt(trading days per year) -/// -/// Key characteristics: -/// - Uses only closing prices -/// - Based on logarithmic returns -/// - Default period is 20 days -/// - Annualized by default (multiply by sqrt(252)) -/// - Expressed as a percentage -/// -/// Formula: -/// Returns = ln(Close[t]/Close[t-1]) -/// CCV = StdDev(Returns, period) * sqrt(252) * 100 -/// -/// Market Applications: -/// - Volatility measurement -/// - Risk assessment -/// - Option pricing -/// - Trading strategy development -/// - Portfolio management -/// -/// Sources: -/// Close-to-Close Volatility concept -/// https://www.investopedia.com/terms/v/volatility.asp -/// -/// Note: Returns annualized volatility as a percentage -/// -[SkipLocalsInit] -public sealed class Ccv : AbstractBase -{ - private readonly int _period; - private readonly bool _annualize; - private readonly CircularBuffer _returns; - private double _prevClose; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ccv(int period = 20, bool annualize = true) - { - _period = period; - _annualize = annualize; - WarmupPeriod = period + 1; // Need one extra period for returns calculation - Name = $"CCV({_period})"; - _returns = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ccv(object source, int period = 20, bool annualize = true) : this(period, annualize) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _returns.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate logarithmic return - double logReturn = Math.Log(BarInput.Close / _prevClose); - _returns.Add(logReturn); - _prevClose = BarInput.Close; - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate standard deviation - double mean = _returns.Average(); - double sumSquaredDeviations = 0; - for (int i = 0; i < _period; i++) - { - double deviation = _returns[i] - mean; - sumSquaredDeviations += deviation * deviation; - } - double stdDev = Math.Sqrt(sumSquaredDeviations / _period); - - // Annualize if requested (sqrt(252) for trading days in a year) - if (_annualize) - { - stdDev *= Math.Sqrt(252); - } - - // Convert to percentage - double volatility = stdDev * 100; - - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Ce.cs b/lib/volatility/Ce.cs deleted file mode 100644 index cdab9695..00000000 --- a/lib/volatility/Ce.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CE: Chandelier Exit -/// A volatility-based stop-loss indicator that adapts to market conditions, -/// using ATR to set stop levels above/below recent price extremes. -/// -/// -/// The CE calculation process: -/// 1. Calculate highest high and lowest low over the period -/// 2. Calculate ATR over the period -/// 3. Long Exit = Highest High - (ATR * multiplier) -/// 4. Short Exit = Lowest Low + (ATR * multiplier) -/// -/// Key characteristics: -/// - Adapts to market volatility -/// - Default period is 22 days -/// - Default multiplier is 3.0 -/// - Returns both long and short exit levels -/// - Based on ATR and price extremes -/// -/// Formula: -/// ATR = Average(TR, period) -/// Long Exit = Highest High[period] - (multiplier * ATR) -/// Short Exit = Lowest Low[period] + (multiplier * ATR) -/// -/// Market Applications: -/// - Stop loss placement -/// - Position management -/// - Trend following -/// - Risk control -/// - Exit strategy -/// -/// Sources: -/// Chuck LeBeau -/// https://www.investopedia.com/terms/c/chandelier-exit.asp -/// -/// Note: Returns two values: long exit and short exit levels -/// -[SkipLocalsInit] -public sealed class Ce : AbstractBase -{ - private readonly int _period; - private readonly double _multiplier; - private readonly CircularBuffer _tr; - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private double _prevClose; - private double _longExit; - private double _shortExit; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ce(int period = 22, double multiplier = 3.0) - { - _period = period; - _multiplier = multiplier; - WarmupPeriod = period + 1; // Need one extra period for TR - Name = $"CE({_period},{_multiplier})"; - _tr = new CircularBuffer(period); - _highs = new CircularBuffer(period); - _lows = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ce(object source, int period = 22, double multiplier = 3.0) : this(period, multiplier) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _longExit = 0; - _shortExit = 0; - _tr.Clear(); - _highs.Clear(); - _lows.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate True Range - double tr = Math.Max(BarInput.High - BarInput.Low, - Math.Max(Math.Abs(BarInput.High - _prevClose), - Math.Abs(BarInput.Low - _prevClose))); - - // Add values to buffers - _tr.Add(tr); - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate ATR - double atr = _tr.Average(); - - // Find highest high and lowest low - double highestHigh = double.MinValue; - double lowestLow = double.MaxValue; - for (int i = 0; i < _period; i++) - { - highestHigh = Math.Max(highestHigh, _highs[i]); - lowestLow = Math.Min(lowestLow, _lows[i]); - } - - // Calculate exit levels - _longExit = highestHigh - (_multiplier * atr); - _shortExit = lowestLow + (_multiplier * atr); - - IsHot = _index >= WarmupPeriod; - return _longExit; // Return long exit as primary value - } - - /// - /// Gets the long exit level - /// - public double LongExit => _longExit; - - /// - /// Gets the short exit level - /// - public double ShortExit => _shortExit; -} diff --git a/lib/volatility/Cv.cs b/lib/volatility/Cv.cs deleted file mode 100644 index bc77b20b..00000000 --- a/lib/volatility/Cv.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CV: Conditional Volatility (GARCH) -/// Implements the GARCH(1,1) model for estimating conditional volatility, -/// which captures volatility clustering and mean reversion in financial markets. -/// -/// -/// The CV (GARCH) calculation process: -/// 1. Calculate returns: (Close[t] - Close[t-1])/Close[t-1] -/// 2. Update variance estimate using GARCH(1,1) formula: -/// σ²[t] = ω + α*r²[t-1] + β*σ²[t-1] -/// 3. Take square root to get volatility -/// -/// Key characteristics: -/// - Captures volatility clustering -/// - Mean-reverting behavior -/// - Responds to market shocks -/// - Default period is 20 days -/// - Returns annualized volatility -/// -/// Formula: -/// Returns[t] = (Close[t] - Close[t-1])/Close[t-1] -/// σ²[t] = ω + α*Returns²[t-1] + β*σ²[t-1] -/// CV[t] = sqrt(σ²[t]) * sqrt(252) * 100 -/// -/// Where: -/// ω (omega) = long-term variance * (1 - α - β) -/// α (alpha) = weight of recent squared return -/// β (beta) = weight of previous variance -/// -/// Market Applications: -/// - Risk measurement -/// - Option pricing -/// - Value at Risk (VaR) -/// - Portfolio optimization -/// - Volatility forecasting -/// -/// Sources: -/// Bollerslev (1986) -/// https://en.wikipedia.org/wiki/GARCH -/// -/// Note: Returns annualized volatility as a percentage -/// -[SkipLocalsInit] -public sealed class Cv : AbstractBase -{ - private readonly int _period; - private readonly double _alpha; - private readonly double _beta; - private readonly double _omega; - private double _prevClose; - private double _prevVariance; - private bool _isInitialized; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cv(int period = 20, double alpha = 0.1, double beta = 0.8) - { - _period = period; - _alpha = alpha; - _beta = beta; - _omega = 0.001 * (1 - alpha - beta); // Initial estimate, will be updated with actual data - WarmupPeriod = period + 1; // Need one extra period for returns - Name = $"CV({_period})"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cv(object source, int period = 20, double alpha = 0.1, double beta = 0.8) : this(period, alpha, beta) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevVariance = 0; - _isInitialized = false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate return - double return_ = (BarInput.Close - _prevClose) / _prevClose; - double squaredReturn = return_ * return_; - _prevClose = BarInput.Close; - - // Initialize with first available data if not done - if (!_isInitialized && _index > _period) - { - double _longTermVariance = squaredReturn; // Use current squared return as initial estimate - _prevVariance = _longTermVariance; - _isInitialized = true; - } - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Update variance estimate using GARCH(1,1) - double variance = _omega + (_alpha * squaredReturn) + (_beta * _prevVariance); - _prevVariance = variance; - - // Calculate annualized volatility as percentage - double volatility = Math.Sqrt(variance) * Math.Sqrt(252) * 100; - - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Cvi.cs b/lib/volatility/Cvi.cs deleted file mode 100644 index 25c3912d..00000000 --- a/lib/volatility/Cvi.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CVI: Chaikin's Volatility Index -/// Measures the rate of change of a moving average of the difference -/// between high and low prices, indicating volatility expansion/contraction. -/// -/// -/// The CVI calculation process: -/// 1. Calculate High-Low difference -/// 2. Take EMA of High-Low difference -/// 3. Calculate ROC of the EMA over specified period -/// -/// Key characteristics: -/// - Measures volatility expansion/contraction -/// - Default period is 10 days -/// - Default smoothing period is 10 days -/// - Positive values indicate expanding volatility -/// - Negative values indicate contracting volatility -/// -/// Formula: -/// HL = High - Low -/// Smoothed = EMA(HL, smoothPeriod) -/// CVI = ((Smoothed - Smoothed[period]) / Smoothed[period]) * 100 -/// -/// Market Applications: -/// - Volatility measurement -/// - Trend strength analysis -/// - Market regime identification -/// - Trading range analysis -/// - Breakout confirmation -/// -/// Sources: -/// Marc Chaikin -/// https://www.investopedia.com/terms/c/chaikinvolatility.asp -/// -/// Note: Returns percentage change in volatility -/// -[SkipLocalsInit] -public sealed class Cvi : AbstractBase -{ - private readonly int _period; - private readonly CircularBuffer _smoothed; - private readonly double _alpha; - private double _ema; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cvi(int period = 10, int smoothPeriod = 10) - { - _period = period; - _alpha = 2.0 / (smoothPeriod + 1); - WarmupPeriod = _period + smoothPeriod; - Name = $"CVI({_period},{smoothPeriod})"; - _smoothed = new CircularBuffer(_period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cvi(object source, int period = 10, int smoothPeriod = 10) : this(period, smoothPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _ema = 0; - _smoothed.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate High-Low difference - double hl = BarInput.High - BarInput.Low; - - // Calculate EMA of High-Low difference - if (_index == 1) - { - _ema = hl; - } - else - { - _ema = (_alpha * hl) + ((1 - _alpha) * _ema); - } - - // Add smoothed value to buffer - _smoothed.Add(_ema); - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate rate of change - double roc = ((_ema - _smoothed[_period - 1]) / _smoothed[_period - 1]) * 100; - - IsHot = _index >= WarmupPeriod; - return roc; - } -} diff --git a/lib/volatility/Dchn.cs b/lib/volatility/Dchn.cs deleted file mode 100644 index 2a5d5782..00000000 --- a/lib/volatility/Dchn.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// DCHN: Donchian Channels -/// A volatility indicator that identifies the highest high and lowest low -/// over a specified period, creating a channel that contains price movement. -/// -/// -/// The DCHN calculation process: -/// 1. Track highest high over period -/// 2. Track lowest low over period -/// 3. Calculate midline as average of high and low -/// 4. Updates with each new price bar -/// -/// Key characteristics: -/// - Trend following indicator -/// - Support/resistance identification -/// - Breakout detection -/// - Volatility measurement -/// - Range-based analysis -/// -/// Formula: -/// Upper = Highest High over period -/// Lower = Lowest Low over period -/// Middle = (Upper + Lower) / 2 -/// -/// Market Applications: -/// - Trend identification -/// - Support/resistance levels -/// - Breakout trading -/// - Volatility analysis -/// - Range-bound trading -/// -[SkipLocalsInit] -public sealed class Dchn : AbstractBase -{ - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private const int DefaultPeriod = 20; - - /// The number of periods for DCHN calculation (default 20). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dchn(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _highs = new(period); - _lows = new(period); - WarmupPeriod = period; - Name = $"DCHN({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for DCHN calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dchn(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate channel boundaries - double upper = _highs.Max(); - double lower = _lows.Min(); - - // Return midline - return (upper + lower) / 2.0; - } - - /// - /// Gets the upper channel value (highest high) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Upper() => _highs.Max(); - - /// - /// Gets the lower channel value (lowest low) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Lower() => _lows.Min(); -} diff --git a/lib/volatility/Ewma.cs b/lib/volatility/Ewma.cs deleted file mode 100644 index 672ebfb1..00000000 --- a/lib/volatility/Ewma.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// EWMA: Exponential Weighted Moving Average Volatility -/// A volatility measure that gives more weight to recent observations, -/// calculated using squared returns and exponential weighting. -/// -/// -/// The EWMA calculation process: -/// 1. Calculate returns: (Close[t] - Close[t-1])/Close[t-1] -/// 2. Square returns -/// 3. Apply exponential weighting to squared returns -/// 4. Take square root and annualize -/// -/// Key characteristics: -/// - More responsive to recent volatility changes -/// - Default decay factor (lambda) is 0.94 -/// - Default period is 20 days -/// - Annualized by default (multiply by sqrt(252)) -/// - Expressed as a percentage -/// -/// Formula: -/// Returns[t] = (Close[t] - Close[t-1])/Close[t-1] -/// EWMA[t] = λ * EWMA[t-1] + (1-λ) * Returns[t]² -/// Volatility = sqrt(EWMA) * sqrt(252) * 100 -/// -/// Where: -/// λ (lambda) = decay factor (typically 0.94) -/// -/// Market Applications: -/// - Risk measurement -/// - Option pricing -/// - Value at Risk (VaR) -/// - Portfolio optimization -/// - Volatility forecasting -/// -/// Sources: -/// RiskMetrics™ Technical Document (1996) -/// https://www.msci.com/documents/10199/5915b101-4206-4ba0-aee2-3449d5c7e95a -/// -/// Note: Returns annualized volatility as a percentage -/// -[SkipLocalsInit] -public sealed class Ewma : AbstractBase -{ - private readonly int _period; - private readonly double _lambda; - private readonly bool _annualize; - private double _prevClose; - private double _ewma; - private bool _isInitialized; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ewma(int period = 20, double lambda = 0.94, bool annualize = true) - { - _period = period; - _lambda = lambda; - _annualize = annualize; - WarmupPeriod = period + 1; // Need one extra period for returns - Name = $"EWMA({_period},{_lambda})"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ewma(object source, int period = 20, double lambda = 0.94, bool annualize = true) : this(period, lambda, annualize) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _ewma = 0; - _isInitialized = false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate return - double return_ = (BarInput.Close - _prevClose) / _prevClose; - double squaredReturn = return_ * return_; - _prevClose = BarInput.Close; - - // Initialize EWMA if not done - if (!_isInitialized && _index > _period) - { - _ewma = squaredReturn; - _isInitialized = true; - } - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Update EWMA - _ewma = (_lambda * _ewma) + ((1 - _lambda) * squaredReturn); - - // Calculate volatility - double volatility = Math.Sqrt(_ewma); - - // Annualize if requested - if (_annualize) - { - volatility *= Math.Sqrt(252); - } - - // Convert to percentage - volatility *= 100; - - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Fcb.cs b/lib/volatility/Fcb.cs deleted file mode 100644 index 60c926e1..00000000 --- a/lib/volatility/Fcb.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// FCB: Fractal Chaos Bands -/// Adaptive price bands based on fractal geometry concepts, -/// identifying potential support and resistance levels. -/// -/// -/// The FCB calculation process: -/// 1. Identify fractal highs and lows over the period -/// 2. Calculate high and low bands using fractal points -/// 3. Smooth bands using exponential moving average -/// -/// Key characteristics: -/// - Adapts to market structure -/// - Default period is 20 days -/// - Default smoothing factor is 0.5 -/// - Returns upper and lower bands -/// - Based on fractal geometry concepts -/// -/// Formula: -/// Fractal High = High[t] where High[t] > High[t±1,2] -/// Fractal Low = Low[t] where Low[t] < Low[t±1,2] -/// Upper Band = EMA(Fractal Highs, smoothing) -/// Lower Band = EMA(Fractal Lows, smoothing) -/// -/// Market Applications: -/// - Support/resistance identification -/// - Trend analysis -/// - Volatility measurement -/// - Breakout detection -/// - Trading range analysis -/// -/// Sources: -/// Bill Williams' Chaos Theory -/// Trading Chaos (2nd Edition) by Bill Williams -/// -/// Note: Returns three values: upper, middle, and lower bands -/// -[SkipLocalsInit] -public sealed class Fcb : AbstractBase -{ - private readonly double _smoothing; - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private double _upperBand; - private double _middleBand; - private double _lowerBand; - private double _upperEma; - private double _lowerEma; - private readonly double _alpha; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Fcb(int period = 20, double smoothing = 0.5) - { - _smoothing = smoothing; - _alpha = 2.0 / (period + 1); - WarmupPeriod = period + 4; // Need extra periods for fractal identification - Name = $"FCB({period},{_smoothing})"; - _highs = new CircularBuffer(period); - _lows = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Fcb(object source, int period = 20, double smoothing = 0.5) : this(period, smoothing) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _upperBand = 0; - _middleBand = 0; - _lowerBand = 0; - _upperEma = 0; - _lowerEma = 0; - _highs.Clear(); - _lows.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Add current high/low to buffers - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - - // Need enough values for calculation - if (_index <= 4) - { - return 0; - } - - // Check for fractal patterns - bool isFractalHigh = false; - bool isFractalLow = false; - - // Fractal high: current high is higher than 2 bars before and after - isFractalHigh = _highs[2] > _highs[0] && _highs[2] > _highs[1] && - _highs[2] > _highs[3] && _highs[2] > _highs[4]; - - // Fractal low: current low is lower than 2 bars before and after - isFractalLow = _lows[2] < _lows[0] && _lows[2] < _lows[1] && - _lows[2] < _lows[3] && _lows[2] < _lows[4]; - - - // Update EMAs with fractal points - if (isFractalHigh) - { - _upperEma = (_alpha * _highs[2]) + ((1 - _alpha) * _upperEma); - } - if (isFractalLow) - { - _lowerEma = (_alpha * _lows[2]) + ((1 - _alpha) * _lowerEma); - } - - // Apply smoothing to bands - _upperBand = (_smoothing * _upperEma) + ((1 - _smoothing) * BarInput.High); - _lowerBand = (_smoothing * _lowerEma) + ((1 - _smoothing) * BarInput.Low); - _middleBand = (_upperBand + _lowerBand) / 2; - - IsHot = _index >= WarmupPeriod; - return _middleBand; // Return middle band as primary value - } - - /// - /// Gets the upper band value - /// - public double UpperBand => _upperBand; - - /// - /// Gets the middle band value - /// - public double MiddleBand => _middleBand; - - /// - /// Gets the lower band value - /// - public double LowerBand => _lowerBand; -} diff --git a/lib/volatility/Gkv.cs b/lib/volatility/Gkv.cs deleted file mode 100644 index fd197d48..00000000 --- a/lib/volatility/Gkv.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// GKV: Garman-Klass Volatility -/// An efficient estimator of volatility that uses open, high, low, -/// and close prices to capture intraday price movements. -/// -/// -/// The GKV calculation process: -/// 1. Calculate components using OHLC prices -/// 2. Combine components using optimal weights -/// 3. Take rolling average over period -/// 4. Annualize and convert to percentage -/// -/// Key characteristics: -/// - More efficient than close-to-close volatility -/// - Uses full OHLC price information -/// - Default period is 20 days -/// - Annualized by default -/// - Expressed as a percentage -/// -/// Formula: -/// u = ln(High/Low)²/2 -/// c = ln(Close/Open)² -/// GKV = sqrt(sum((0.5*u - (2*ln(2)-1)*c) / period) * 252) * 100 -/// -/// Market Applications: -/// - Volatility estimation -/// - Risk measurement -/// - Option pricing -/// - Trading strategy development -/// - Market analysis -/// -/// Sources: -/// Garman and Klass (1980) -/// Journal of Business 53(1): 67-78 -/// -/// Note: Returns annualized volatility as a percentage -/// -[SkipLocalsInit] -public sealed class Gkv : AbstractBase -{ - private readonly int _period; - private readonly bool _annualize; - private readonly CircularBuffer _components; - private readonly double _ln2; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Gkv(int period = 20, bool annualize = true) - { - _period = period; - _annualize = annualize; - WarmupPeriod = period; - Name = $"GKV({_period})"; - _components = new CircularBuffer(period); - _ln2 = Math.Log(2); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Gkv(object source, int period = 20, bool annualize = true) : this(period, annualize) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _components.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate components - double u = Math.Log(BarInput.High / BarInput.Low); - u = u * u / 2; - - double c = Math.Log(BarInput.Close / BarInput.Open); - c = c * c; - - // Combine components with optimal weights - double component = (0.5 * u) - (((2 * _ln2) - 1) * c); - _components.Add(component); - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate average component - double avgComponent = _components.Average(); - - // Calculate volatility - double volatility = Math.Sqrt(avgComponent); - - // Annualize if requested - if (_annualize) - { - volatility *= Math.Sqrt(252); - } - - // Convert to percentage - volatility *= 100; - - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Hlv.cs b/lib/volatility/Hlv.cs deleted file mode 100644 index b1d60e36..00000000 --- a/lib/volatility/Hlv.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// HLV: High-Low Volatility -/// A volatility measure based on the high-low range relative -/// to the previous close, capturing intraday price movements. -/// -/// -/// The HLV calculation process: -/// 1. Calculate normalized high-low range -/// 2. Take rolling average over period -/// 3. Convert to annualized volatility -/// -/// Key characteristics: -/// - Captures intraday price movements -/// - Uses high, low, and previous close -/// - Default period is 20 days -/// - Annualized by default -/// - Expressed as a percentage -/// -/// Formula: -/// Range = (High - Low) / PrevClose -/// HLV = sqrt(sum(Range² / period) * 252) * 100 -/// -/// Market Applications: -/// - Volatility measurement -/// - Risk assessment -/// - Trading range analysis -/// - Market regime identification -/// - Position sizing -/// -/// Sources: -/// Parkinson (1980) modified -/// The Extreme Value Method for Estimating the Variance of the Rate of Return -/// Journal of Business 53(1): 61-65 -/// -/// Note: Returns annualized volatility as a percentage -/// -[SkipLocalsInit] -public sealed class Hlv : AbstractBase -{ - private readonly int _period; - private readonly bool _annualize; - private readonly CircularBuffer _ranges; - private double _prevClose; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hlv(int period = 20, bool annualize = true) - { - _period = period; - _annualize = annualize; - WarmupPeriod = period + 1; // Need one extra period for previous close - Name = $"HLV({_period})"; - _ranges = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hlv(object source, int period = 20, bool annualize = true) : this(period, annualize) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _ranges.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate normalized range - double range = (BarInput.High - BarInput.Low) / _prevClose; - double squaredRange = range * range; - _ranges.Add(squaredRange); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - // Need enough values for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate average squared range - double avgSquaredRange = _ranges.Average(); - - // Calculate volatility - double volatility = Math.Sqrt(avgSquaredRange); - - // Annualize if requested - if (_annualize) - { - volatility *= Math.Sqrt(252); - } - - // Convert to percentage - volatility *= 100; - - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Hv.cs b/lib/volatility/Hv.cs deleted file mode 100644 index 0bf17c1d..00000000 --- a/lib/volatility/Hv.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// HV: Historical Volatility -/// A statistical measure that calculates the dispersion of returns over time, -/// providing insights into past price variability. Historical volatility is -/// fundamental to options pricing and risk assessment. -/// -/// -/// The HV calculation process: -/// 1. Computes daily log returns -/// 2. Calculates standard deviation -/// 3. Annualizes if specified -/// 4. Uses sample variance formula -/// -/// Key characteristics: -/// - Backward-looking measure -/// - Log-return based -/// - Optional annualization -/// - Sample-based calculation -/// - Trading-day adjusted -/// -/// Formula: -/// HV = √[(Σ(ln(P[t]/P[t-1]) - μ)²)/(n-1)] * √252 -/// where: -/// P = price -/// μ = mean of log returns -/// n = number of observations -/// 252 = trading days per year -/// -/// Market Applications: -/// - Options pricing -/// - Risk assessment -/// - Trading ranges -/// - Portfolio management -/// - Volatility trading -/// -/// Sources: -/// Black-Scholes Option Pricing Model -/// https://en.wikipedia.org/wiki/Volatility_(finance) -/// -/// Note: Assumes 252 trading days for annualization -/// -[SkipLocalsInit] -public sealed class Hv : AbstractBase -{ - private readonly int Period; - private readonly bool IsAnnualized; - private readonly CircularBuffer _buffer; - private readonly CircularBuffer _logReturns; - private double _previousClose; - private const int TradingDaysPerYear = 252; - private const double Epsilon = 1e-10; - - /// The number of periods for volatility calculation. - /// Whether to annualize the result (default true). - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hv(int period, bool isAnnualized = true) - { - if (period < 2) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2."); - } - Period = period; - IsAnnualized = isAnnualized; - WarmupPeriod = period + 1; // Need extra point for first return - _buffer = new CircularBuffer(period + 1); - _logReturns = new CircularBuffer(period); - Name = $"Historical(period={period}, annualized={isAnnualized})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods for volatility calculation. - /// Whether to annualize the result (default true). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hv(object source, int period, bool isAnnualized = true) : this(period, isAnnualized) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _buffer.Clear(); - _logReturns.Clear(); - _previousClose = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateLogReturn(double currentPrice, double previousPrice) - { - return previousPrice > Epsilon ? Math.Log(currentPrice / previousPrice) : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMean(ReadOnlySpan values) - { - double sum = 0; - for (int i = 0; i < values.Length; i++) - { - sum += values[i]; - } - return sum / values.Length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateVariance(ReadOnlySpan values, double mean, int degreesOfFreedom) - { - double sumSquaredDiff = 0; - for (int i = 0; i < values.Length; i++) - { - double diff = values[i] - mean; - sumSquaredDiff += diff * diff; - } - return sumSquaredDiff / degreesOfFreedom; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - double volatility = 0; - if (_buffer.Count > 1) - { - // Calculate log return if we have previous close - if (_previousClose > Epsilon) - { - double logReturn = CalculateLogReturn(Input.Value, _previousClose); - _logReturns.Add(logReturn, Input.IsNew); - } - - // Calculate volatility when we have enough returns - if (_logReturns.Count == Period) - { - ReadOnlySpan returns = _logReturns.GetSpan(); - double mean = CalculateMean(returns); - double variance = CalculateVariance(returns, mean, Period - 1); - volatility = Math.Sqrt(variance); - - if (IsAnnualized) - { - volatility *= Math.Sqrt(TradingDaysPerYear); - } - } - } - - _previousClose = Input.Value; - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Jvolty.cs b/lib/volatility/Jvolty.cs deleted file mode 100644 index 24dddcf3..00000000 --- a/lib/volatility/Jvolty.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// JVOLTY: Jurik Volatility -/// An advanced volatility measure developed by Mark Jurik that combines adaptive -/// bands with JMA smoothing. JVOLTY provides a sophisticated approach to measuring -/// market volatility with reduced noise and better responsiveness. -/// -/// -/// The JVOLTY calculation process: -/// 1. Calculates adaptive price bands -/// 2. Measures volatility from band distances -/// 3. Applies volatility normalization -/// 4. Uses JMA-style smoothing -/// 5. Provides multiple outputs -/// -/// Key characteristics: -/// - Adaptive measurement -/// - Noise reduction -/// - Multiple timeframe analysis -/// - Price band integration -/// - Volatility normalization -/// -/// Formula: -/// volty = max(|price - upperBand|, |price - lowerBand|) -/// bands = adaptive calculation using Jurik's methods -/// final = JMA smoothing of normalized volatility -/// -/// Market Applications: -/// - Dynamic position sizing -/// - Adaptive stop placement -/// - Volatility breakout systems -/// - Risk management -/// - Market regime detection -/// -/// Sources: -/// Mark Jurik Research -/// https://www.jurikresearch.com/ -/// -/// Note: Proprietary enhancement of volatility measurement -/// -[SkipLocalsInit] -public sealed class Jvolty : AbstractBase -{ - private readonly int _period; - private readonly double _phase; - private readonly CircularBuffer _vsumBuff; - private readonly CircularBuffer _avoltyBuff; - private readonly double _beta; - private const double Epsilon = 1e-10; - private const int DefaultPhase = 0; - private const int VsumBufferSize = 10; - private const int AvoltyBufferSize = 65; - - private double _len1; - private double _pow1; - private double _upperBand, _lowerBand, _p_upperBand, _p_lowerBand; - private double _prevMa1, _prevDet0, _prevDet1, _prevJma, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma; - private double _vSum, _p_vSum; - - public double UpperBand { get; private set; } - public double LowerBand { get; private set; } - public double Volty { get; private set; } - public double VSum { get; private set; } - public double Jma { get; private set; } - public double AvgVolty { get; private set; } - - /// The number of periods for volatility calculation. - /// Phase parameter for JMA smoothing (default 0). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Jvolty(int period, int phase = DefaultPhase) - { - if (period < 1) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 1."); - } - _period = period; - _phase = Math.Clamp((phase * 0.01) + 1.5, 0.5, 2.5); - - _vsumBuff = new CircularBuffer(VsumBufferSize); - _avoltyBuff = new CircularBuffer(AvoltyBufferSize); - _beta = 0.45 * (period - 1) / ((0.45 * (period - 1)) + 2); - - WarmupPeriod = period * 2; - Name = $"JVOLTY({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for volatility calculation. - /// Phase parameter for JMA smoothing (default 0). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Jvolty(object source, int period, int phase = DefaultPhase) : this(period, phase) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _upperBand = _lowerBand = 0.0; - _p_upperBand = _p_lowerBand = 0.0; - _len1 = Math.Max((Math.Log(Math.Sqrt(_period - 1)) / Math.Log(2.0)) + 2.0, 0); - _pow1 = Math.Max(_len1 - 2.0, 0.5); - _avoltyBuff.Clear(); - _vsumBuff.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_upperBand = _upperBand; - _p_lowerBand = _lowerBand; - _p_vSum = _vSum; - _p_prevMa1 = _prevMa1; - _p_prevDet0 = _prevDet0; - _p_prevDet1 = _prevDet1; - _p_prevJma = _prevJma; - } - else - { - _upperBand = _p_upperBand; - _lowerBand = _p_lowerBand; - _vSum = _p_vSum; - _prevMa1 = _p_prevMa1; - _prevDet0 = _p_prevDet0; - _prevDet1 = _p_prevDet1; - _prevJma = _p_prevJma; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateVolatility(double price, double upperBand, double lowerBand) - { - double del1 = price - upperBand; - double del2 = price - lowerBand; - return Math.Max(Math.Abs(del1), Math.Abs(del2)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateNormalizedVolatility(double volty, double avgVolty) - { - double rvolty = (avgVolty > Epsilon) ? volty / avgVolty : 1; - return Math.Min(Math.Max(rvolty, 1.0), Math.Pow(_len1, 1.0 / _pow1)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateJma(double price, double alpha, double ma1) - { - double det0 = ((price - ma1) * (1 - _beta)) + (_beta * _prevDet0); - _prevDet0 = det0; - double ma2 = ma1 + (_phase * det0); - - double det1 = ((ma2 - _prevJma) * (1 - alpha) * (1 - alpha)) + (alpha * alpha * _prevDet1); - _prevDet1 = det1; - double jma = _prevJma + det1; - _prevJma = jma; - - return jma; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double price = Input.Value; - if (_index == 1) - { - _upperBand = _lowerBand = price; - } - - // Calculate volatility from band distances - double volty = CalculateVolatility(price, _upperBand, _lowerBand); - - // Calculate moving averages of volatility - _vsumBuff.Add(volty, Input.IsNew); - _vSum += (_vsumBuff[^1] - _vsumBuff[0]) / VsumBufferSize; - _avoltyBuff.Add(_vSum, Input.IsNew); - double avgvolty = _avoltyBuff.Average(); - - // Normalize and adjust volatility - double rvolty = CalculateNormalizedVolatility(volty, avgvolty); - double pow2 = Math.Pow(rvolty, _pow1); - double Kv = Math.Pow(_beta, Math.Sqrt(pow2)); - - // Update adaptive bands - double del1 = price - _upperBand; - double del2 = price - _lowerBand; - _upperBand = (del1 >= 0) ? price : price - (Kv * del1); - _lowerBand = (del2 <= 0) ? price : price - (Kv * del2); - - // Apply JMA smoothing - double alpha = Math.Pow(_beta, pow2); - double ma1 = ((1 - alpha) * price) + (alpha * _prevMa1); - _prevMa1 = ma1; - - double jma = CalculateJma(price, alpha, ma1); - - // Update public properties - UpperBand = _upperBand; - LowerBand = _lowerBand; - Volty = volty; - VSum = _vSum; - AvgVolty = avgvolty; - Jma = jma; - - IsHot = _index >= WarmupPeriod; - return volty; - } -} diff --git a/lib/volatility/Natr.cs b/lib/volatility/Natr.cs deleted file mode 100644 index d4a37d21..00000000 --- a/lib/volatility/Natr.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// NATR: Normalized Average True Range -/// A volatility indicator that expresses ATR as a percentage of closing price, -/// making it more comparable across different price levels. -/// -/// -/// The NATR calculation process: -/// 1. Calculate True Range (TR): -/// TR = max(high-low, abs(high-prevClose), abs(low-prevClose)) -/// 2. Calculate ATR using SMA of TR -/// 3. Normalize by dividing ATR by close price and multiply by 100 -/// 4. Updates with each new price bar -/// -/// Key characteristics: -/// - Normalized volatility measure -/// - Period-based average -/// - Trend independent -/// - Percentage-based measure -/// - Comparable across instruments -/// -/// Formula: -/// TR = max(high-low, abs(high-prevClose), abs(low-prevClose)) -/// ATR = SMA(TR, period) -/// NATR = (ATR / Close) * 100 -/// -/// Market Applications: -/// - Cross-market comparison -/// - Position sizing -/// - Volatility analysis -/// - Risk assessment -/// - Market regime identification -/// -/// Note: More suitable for comparing volatility across different instruments than ATR -/// -[SkipLocalsInit] -public sealed class Natr : AbstractBase -{ - private readonly Sma _ma; - private double _prevClose; - private const int DefaultPeriod = 14; - - /// The number of periods for NATR calculation (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Natr(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _ma = new(period); - WarmupPeriod = period; - Name = $"NATR({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for NATR calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Natr(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _prevClose = BarInput.Close; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate True Range - double hl = BarInput.High - BarInput.Low; - double hc = Math.Abs(BarInput.High - _prevClose); - double lc = Math.Abs(BarInput.Low - _prevClose); - double tr = Math.Max(hl, Math.Max(hc, lc)); - - // Calculate ATR - double atr = _ma.Calc(tr, BarInput.IsNew); - - // Normalize ATR - return (atr / BarInput.Close) * 100.0; - } -} diff --git a/lib/volatility/Pch.cs b/lib/volatility/Pch.cs deleted file mode 100644 index 476d3b15..00000000 --- a/lib/volatility/Pch.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PCH: Price Channel -/// A volatility indicator that identifies the highest high and lowest low -/// over a specified period, creating a channel that contains price movement. -/// -/// -/// The PCH calculation process: -/// 1. Track highest high over period -/// 2. Track lowest low over period -/// 3. Calculate midline as average of high and low -/// 4. Updates with each new price bar -/// -/// Key characteristics: -/// - Trend following indicator -/// - Support/resistance identification -/// - Breakout detection -/// - Volatility measurement -/// - Range-based analysis -/// -/// Formula: -/// Upper = Highest High over period -/// Lower = Lowest Low over period -/// Middle = (Upper + Lower) / 2 -/// -/// Market Applications: -/// - Trend identification -/// - Support/resistance levels -/// - Breakout trading -/// - Volatility analysis -/// - Range-bound trading -/// -/// Note: Also known as Donchian Channels -/// -[SkipLocalsInit] -public sealed class Pch : AbstractBase -{ - private readonly CircularBuffer _highs; - private readonly CircularBuffer _lows; - private const int DefaultPeriod = 20; - - /// The number of periods for PCH calculation (default 20). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pch(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _highs = new(period); - _lows = new(period); - WarmupPeriod = period; - Name = $"PCH({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for PCH calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pch(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _highs.Add(BarInput.High); - _lows.Add(BarInput.Low); - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate channel boundaries - double upper = _highs.Max(); - double lower = _lows.Min(); - - // Return midline - return (upper + lower) / 2.0; - } - - /// - /// Gets the upper channel value (highest high) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Upper() => _highs.Max(); - - /// - /// Gets the lower channel value (lowest low) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Lower() => _lows.Min(); -} diff --git a/lib/volatility/Pv.cs b/lib/volatility/Pv.cs deleted file mode 100644 index 97d5817b..00000000 --- a/lib/volatility/Pv.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PV: Parkinson Volatility -/// A volatility measure that uses the high and low prices to estimate -/// volatility, assuming continuous trading and log-normal price distribution. -/// -/// -/// The PV calculation process: -/// 1. Calculate squared log range for each period -/// 2. Apply scaling factor (1/4ln2) -/// 3. Average over specified period -/// 4. Take square root for final volatility -/// -/// Key characteristics: -/// - Range-based volatility -/// - More efficient than close-to-close -/// - Assumes continuous trading -/// - No gap consideration -/// - Log-normal distribution -/// -/// Formula: -/// PV = sqrt(1/(4*ln(2)*n) * Σ(ln(High/Low))²) -/// where n is the number of periods -/// -/// Market Applications: -/// - Volatility estimation -/// - Risk assessment -/// - Option pricing -/// - Trading system development -/// - Market regime identification -/// -/// Note: More efficient than traditional volatility measures but sensitive to gaps -/// -[SkipLocalsInit] -public sealed class Pv : AbstractBase -{ - private readonly Sma _ma; - private readonly double _scaleFactor; - private const int DefaultPeriod = 10; - private double _prevValue; - - /// The number of periods for PV calculation (default 10). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pv(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _ma = new(period); - _scaleFactor = 1.0 / (4.0 * Math.Log(2.0)); - WarmupPeriod = period; - Name = $"PV({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for PV calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pv(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - if (!BarInput.IsNew) - return _prevValue; - - ManageState(true); - - // Calculate log range squared - double logRange = Math.Log(BarInput.High / BarInput.Low); - double logRangeSquared = logRange * logRange; - - // Apply moving average and scaling - double meanLogRangeSquared = _ma.Calc(logRangeSquared, true); - - // Calculate final volatility - _prevValue = Math.Sqrt(_scaleFactor * meanLogRangeSquared); - return _prevValue; - } -} diff --git a/lib/volatility/Rsv.cs b/lib/volatility/Rsv.cs deleted file mode 100644 index af0a1b2b..00000000 --- a/lib/volatility/Rsv.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RSV: Rogers-Satchell Volatility -/// A volatility measure that accounts for drift in the price process and -/// is independent of the mean return level. -/// -/// -/// The RSV calculation process: -/// 1. Calculate log differences between prices -/// 2. Combine log differences in specific way -/// 3. Average over specified period -/// 4. Take square root for final volatility -/// -/// Key characteristics: -/// - Drift-independent -/// - Uses all price data (HLOC) -/// - More efficient estimator -/// - Handles trending markets -/// - Non-zero mean returns -/// -/// Formula: -/// RSV = sqrt(mean(ln(H/C) * ln(H/O) + ln(L/C) * ln(L/O))) -/// where H=High, L=Low, O=Open, C=Close -/// -/// Market Applications: -/// - Volatility estimation -/// - Risk measurement -/// - Option pricing -/// - Trading system development -/// - Market regime identification -/// -/// Note: More robust than simple volatility measures in trending markets -/// -[SkipLocalsInit] -public sealed class Rsv : AbstractBase -{ - private readonly Sma _ma; - private const int DefaultPeriod = 10; - private double _prevValue; - - /// The number of periods for RSV calculation (default 10). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsv(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _ma = new(period); - WarmupPeriod = period; - Name = $"RSV({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for RSV calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rsv(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - if (!BarInput.IsNew) - return _prevValue; - - ManageState(true); - - // Calculate log ratios - double lnHC = Math.Log(BarInput.High / BarInput.Close); - double lnHO = Math.Log(BarInput.High / BarInput.Open); - double lnLC = Math.Log(BarInput.Low / BarInput.Close); - double lnLO = Math.Log(BarInput.Low / BarInput.Open); - - // Calculate Rogers-Satchell term - double rs = (lnHC * lnHO) + (lnLC * lnLO); - - // Apply moving average and take square root - _prevValue = Math.Sqrt(_ma.Calc(rs, true)); - return _prevValue; - } -} diff --git a/lib/volatility/Rv.cs b/lib/volatility/Rv.cs deleted file mode 100644 index 9ba91021..00000000 --- a/lib/volatility/Rv.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RV: Realized Volatility -/// A precise volatility measure that captures actual observed price fluctuations -/// using high-frequency returns. RV provides a more accurate assessment of true -/// market volatility compared to traditional estimators. -/// -/// -/// The RV calculation process: -/// 1. Computes log returns -/// 2. Squares each return -/// 3. Maintains rolling sum -/// 4. Takes square root of average -/// 5. Optionally annualizes -/// -/// Key characteristics: -/// - Model-free measurement -/// - High-frequency capable -/// - Rolling calculation -/// - Memory efficient -/// - Optional annualization -/// -/// Formula: -/// RV = √(Σ(ln(P[t]/P[t-1]))²/n) * √252 -/// where: -/// P = price -/// n = number of observations -/// 252 = trading days per year -/// -/// Market Applications: -/// - High-frequency trading -/// - Options pricing -/// - Risk forecasting -/// - Market microstructure -/// - Volatility trading -/// -/// Sources: -/// Andersen, Bollerslev - "Answering the Skeptics" -/// https://en.wikipedia.org/wiki/Realized_volatility -/// -/// Note: Efficient implementation using rolling sums -/// -[SkipLocalsInit] -public sealed class Rv : AbstractBase -{ - private readonly int Period; - private readonly bool IsAnnualized; - private readonly CircularBuffer _returns; - private double _previousClose; - private double _sumSquaredReturns; - private const int TradingDaysPerYear = 252; - private const double Epsilon = 1e-10; - private const bool DefaultIsAnnualized = true; - - /// The number of periods for volatility calculation. - /// Whether to annualize the result (default true). - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rv(int period, bool isAnnualized = DefaultIsAnnualized) - { - if (period < 2) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2."); - } - Period = period; - IsAnnualized = isAnnualized; - WarmupPeriod = period + 1; // Need extra point for first return - _returns = new CircularBuffer(period); - Name = $"Realized(period={period}, annualized={isAnnualized})"; - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods for volatility calculation. - /// Whether to annualize the result (default true). - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rv(object source, int period, bool isAnnualized = DefaultIsAnnualized) : this(period, isAnnualized) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _returns.Clear(); - _previousClose = 0; - _sumSquaredReturns = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateLogReturn(double currentPrice, double previousPrice) - { - return previousPrice > Epsilon ? Math.Log(currentPrice / previousPrice) : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateVolatility(double sumSquaredReturns, int period, bool isAnnualized) - { - double variance = sumSquaredReturns / period; - double volatility = Math.Sqrt(variance); - return isAnnualized ? volatility * Math.Sqrt(TradingDaysPerYear) : volatility; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double volatility = 0; - if (_previousClose > Epsilon) - { - // Calculate log return - double logReturn = CalculateLogReturn(Input.Value, _previousClose); - - if (_returns.Count == Period) - { - // Maintain rolling sum by removing oldest squared return - double oldReturn = _returns[0]; - _sumSquaredReturns -= oldReturn * oldReturn; - } - - // Add new return and update sum - _returns.Add(logReturn, Input.IsNew); - _sumSquaredReturns += logReturn * logReturn; - - if (_returns.Count == Period) - { - // Calculate realized volatility - volatility = CalculateVolatility(_sumSquaredReturns, Period, IsAnnualized); - } - } - - _previousClose = Input.Value; - IsHot = _index >= WarmupPeriod; - return volatility; - } -} diff --git a/lib/volatility/Rvi.cs b/lib/volatility/Rvi.cs deleted file mode 100644 index 44a9067d..00000000 --- a/lib/volatility/Rvi.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// RVI: Relative Volatility Index -/// A technical indicator developed by Donald Dorsey that measures the direction -/// of volatility by comparing upward and downward price movements. RVI helps -/// identify whether volatility is increasing more in up or down moves. -/// -/// -/// The RVI calculation process: -/// 1. Separates price changes into up/down moves -/// 2. Calculates standard deviation for each -/// 3. Applies moving average smoothing -/// 4. Computes relative strength ratio -/// 5. Scales to percentage (0-100) -/// -/// Key characteristics: -/// - Oscillator (0-100 range) -/// - Directional volatility measure -/// - Combines volatility and momentum -/// - Uses standard deviation -/// - Smoothed output -/// -/// Formula: -/// RVI = 100 * SMA(StdDev(upMoves)) / (SMA(StdDev(upMoves)) + SMA(StdDev(downMoves))) -/// where: -/// upMove = max(close - prevClose, 0) -/// downMove = max(prevClose - close, 0) -/// -/// Market Applications: -/// - Trend confirmation -/// - Divergence analysis -/// - Volatility breakouts -/// - Market reversals -/// - Overbought/oversold levels -/// -/// Sources: -/// Donald Dorsey - "Technical Analysis of Stocks & Commodities" (1993) -/// https://www.investopedia.com/terms/r/relative_volatility_index.asp -/// -/// Note: Similar concept to RSI but using volatility -/// -[SkipLocalsInit] -public sealed class Rvi : AbstractBase -{ - private readonly Stddev _upStdDev, _downStdDev; - private readonly Sma _upSma, _downSma; - private double _previousClose; - private const double ScalingFactor = 100.0; - private const double Epsilon = 1e-10; - - /// The number of periods for RVI calculation. - /// Thrown when period is less than 2. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rvi(int period) - { - if (period < 2) - { - throw new ArgumentOutOfRangeException(nameof(period), - "Period must be greater than or equal to 2."); - } - WarmupPeriod = period; - Name = $"RVI(period={period})"; - _upStdDev = new Stddev(period); - _downStdDev = new Stddev(period); - _upSma = new(period); - _downSma = new(period); - Init(); - } - - /// The data source object that publishes updates. - /// The number of periods for RVI calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rvi(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _previousClose = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static (double upMove, double downMove) CalculateMoves(double change) - { - return (Math.Max(change, 0), Math.Max(-change, 0)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateRvi(double upSma, double downSma) - { - double totalSma = upSma + downSma; - return totalSma > Epsilon ? ScalingFactor * upSma / totalSma : 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(Input.IsNew); - - double close = Input.Value; - double change = close - _previousClose; - - // Separate into up and down moves - var (upMove, downMove) = CalculateMoves(change); - - // Calculate standard deviations and apply smoothing - _upSma.Calc(_upStdDev.Calc(new TValue(Input.Time, upMove, Input.IsNew))); - _downSma.Calc(_downStdDev.Calc(new TValue(Input.Time, downMove, Input.IsNew))); - - // Calculate RVI ratio - double rvi = CalculateRvi(_upSma.Value, _downSma.Value); - - _previousClose = close; - IsHot = _index >= WarmupPeriod; - return rvi; - } -} diff --git a/lib/volatility/Sv.cs b/lib/volatility/Sv.cs deleted file mode 100644 index 28ddd7df..00000000 --- a/lib/volatility/Sv.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// SV: Stochastic Volatility -/// A volatility measure that models price volatility as a random process, -/// capturing both the magnitude and the rate of change in price movements. -/// -/// -/// The SV calculation process: -/// 1. Calculate log returns -/// 2. Compute exponentially weighted variance -/// 3. Apply smoothing to variance estimate -/// 4. Take square root for volatility -/// -/// Key characteristics: -/// - Time-varying volatility -/// - Mean-reverting process -/// - Captures volatility clustering -/// - Handles leverage effects -/// - Accounts for fat tails -/// -/// Formula: -/// Returns = ln(Close/PrevClose) -/// Variance = λ * PrevVariance + (1-λ) * Returns² -/// SV = sqrt(Variance) -/// where λ is the decay factor -/// -/// Market Applications: -/// - Option pricing -/// - Risk management -/// - Trading strategies -/// - Portfolio optimization -/// - Market regime detection -/// -/// Note: More sophisticated than simple volatility measures, better captures market dynamics -/// -[SkipLocalsInit] -public sealed class Sv : AbstractBase -{ - private readonly double _lambda; - private readonly Sma _ma; - private double _prevClose; - private double _prevVariance; - private double _prevValue; - private const int DefaultPeriod = 20; - private const double DefaultLambda = 0.94; - - /// The number of periods for smoothing (default 20). - /// The decay factor for variance calculation (default 0.94). - /// Thrown when period is less than 1 or lambda is not between 0 and 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Sv(int period = DefaultPeriod, double lambda = DefaultLambda) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - if (lambda <= 0 || lambda >= 1) - throw new ArgumentOutOfRangeException(nameof(lambda)); - - _lambda = lambda; - _ma = new(period); - WarmupPeriod = period; - Name = $"SV({period},{lambda:F2})"; - } - - /// The data source object that publishes updates. - /// The number of periods for smoothing. - /// The decay factor for variance calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Sv(object source, int period = DefaultPeriod, double lambda = DefaultLambda) : this(period, lambda) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _prevClose = BarInput.Close; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - if (!BarInput.IsNew) - return _prevValue; - - ManageState(true); - - // Calculate log return - double logReturn = Math.Log(BarInput.Close / _prevClose); - double squaredReturn = logReturn * logReturn; - - // Update variance estimate - _prevVariance = (_lambda * _prevVariance) + ((1.0 - _lambda) * squaredReturn); - - // Apply smoothing and take square root - _prevValue = Math.Sqrt(_ma.Calc(_prevVariance, true)); - return _prevValue; - } -} diff --git a/lib/volatility/Tr.cs b/lib/volatility/Tr.cs deleted file mode 100644 index e95016c7..00000000 --- a/lib/volatility/Tr.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TR: True Range -/// A basic volatility measure that represents the greatest of three price ranges: -/// current high-low, current high-previous close, or current low-previous close. -/// -/// -/// The TR calculation process: -/// 1. Calculate three differences: -/// - Current High minus Current Low -/// - |Current High minus Previous Close| -/// - |Current Low minus Previous Close| -/// 2. TR is the maximum of these three values -/// -/// Key characteristics: -/// - Basic volatility measure -/// - Accounts for gaps between trading periods -/// - Foundation for other indicators (ATR, etc.) -/// - No upper bound -/// - Always positive -/// -/// Formula: -/// TR = max(High - Low, |High - Previous Close|, |Low - Previous Close|) -/// -/// Market Applications: -/// - Volatility measurement -/// - Stop loss placement -/// - Position sizing -/// - Market analysis -/// - Risk assessment -/// -/// Sources: -/// J. Welles Wilder Jr. - Original development -/// https://www.investopedia.com/terms/t/truerange.asp -/// -/// Note: True Range accounts for gaps between periods, making it more accurate than simple high-low range -/// -[SkipLocalsInit] -public sealed class Tr : AbstractBase -{ - private double _prevClose; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tr() - { - WarmupPeriod = 2; // Need previous close - Name = "TR"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tr(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return BarInput.High - BarInput.Low; - } - - // Calculate True Range - double tr = Math.Max(BarInput.High - BarInput.Low, - Math.Max(Math.Abs(BarInput.High - _prevClose), - Math.Abs(BarInput.Low - _prevClose))); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - IsHot = _index >= WarmupPeriod; - return tr; - } -} diff --git a/lib/volatility/Ui.cs b/lib/volatility/Ui.cs deleted file mode 100644 index 4af8baa8..00000000 --- a/lib/volatility/Ui.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// UI: Ulcer Index -/// A technical indicator that measures downside risk by incorporating both -/// the depth and duration of price declines over a given period. -/// -/// -/// The UI calculation process: -/// 1. Calculate percentage drawdown from recent high for each period -/// 2. Square the drawdowns to emphasize larger declines -/// 3. Calculate the average of squared drawdowns -/// 4. Take the square root of the average -/// -/// Key characteristics: -/// - Measures downside volatility -/// - Emphasizes larger drawdowns -/// - Default period is 14 days -/// - Always positive -/// - No upper bound -/// -/// Formula: -/// Drawdown = ((Close - 14-period High) / 14-period High) * 100 -/// UI = sqrt(sum(Drawdown^2) / period) -/// -/// Market Applications: -/// - Risk assessment -/// - Portfolio analysis -/// - Trading system evaluation -/// - Market timing -/// - Trend strength measurement -/// -/// Sources: -/// Peter Martin - Original development (1987) -/// https://www.investopedia.com/terms/u/ulcerindex.asp -/// -/// Note: Higher values indicate higher risk due to deeper or more frequent drawdowns -/// -[SkipLocalsInit] -public sealed class Ui : AbstractBase -{ - private readonly int _period; - private readonly CircularBuffer _prices; - private readonly CircularBuffer _drawdowns; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ui(int period = 14) - { - _period = period; - WarmupPeriod = period; - Name = $"UI({_period})"; - _prices = new CircularBuffer(period); - _drawdowns = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ui(object source, int period = 14) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prices.Clear(); - _drawdowns.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Add current price to buffer - _prices.Add(BarInput.Close); - - // Need enough prices for calculation - if (_index <= _period) - { - return 0; - } - - // Calculate maximum price in period - double maxPrice = _prices.Max(); - - // Calculate percentage drawdown - double drawdown = Math.Abs(maxPrice) > double.Epsilon ? ((BarInput.Close - maxPrice) / maxPrice) * 100 : 0; - - // Add squared drawdown to buffer - _drawdowns.Add(drawdown * drawdown); - - // Calculate Ulcer Index - double ui = Math.Sqrt(_drawdowns.Average()); - - IsHot = _index >= WarmupPeriod; - return ui; - } -} diff --git a/lib/volatility/Vc.cs b/lib/volatility/Vc.cs deleted file mode 100644 index 1b95a89a..00000000 --- a/lib/volatility/Vc.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VC: Volatility Cone -/// A technical indicator that analyzes volatility across different time periods -/// to identify normal ranges and extreme values. -/// -/// -/// The VC calculation process: -/// 1. Calculate volatility for the specified period -/// 2. Track mean and standard deviation of volatility -/// 3. Calculate upper and lower bounds: -/// Upper = Mean + (deviations * StdDev) -/// Lower = Mean - (deviations * StdDev) -/// -/// Key characteristics: -/// - Multi-period volatility analysis -/// - Statistical approach -/// - Default period is 20 days -/// - Returns mean and bounds -/// - Adaptive to market conditions -/// -/// Formula: -/// Volatility = StdDev(Returns) * sqrt(252) // Annualized -/// Upper = Mean(Volatility) + (deviations * StdDev(Volatility)) -/// Lower = Mean(Volatility) - (deviations * StdDev(Volatility)) -/// -/// Market Applications: -/// - Options trading -/// - Risk assessment -/// - Volatility forecasting -/// - Trading strategy development -/// - Market regime analysis -/// -/// Sources: -/// https://www.investopedia.com/terms/v/volatility-cone.asp -/// -/// Note: Returns three values: mean volatility and its upper/lower bounds -/// -[SkipLocalsInit] -public sealed class Vc : AbstractBase -{ - private readonly int _period; - private readonly double _deviations; - private readonly CircularBuffer _returns; - private readonly CircularBuffer _volatilities; - private double _prevClose; - private double _upperBound; - private double _lowerBound; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vc(int period = 20, double deviations = 2.0) - { - _period = period; - _deviations = deviations; - WarmupPeriod = period * 2; // Need enough data for stable statistics - Name = $"VC({_period},{_deviations})"; - _returns = new CircularBuffer(period); - _volatilities = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vc(object source, int period = 20, double deviations = 2.0) : this(period, deviations) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _upperBound = 0; - _lowerBound = 0; - _returns.Clear(); - _volatilities.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateVariance(CircularBuffer buffer) - { - if (buffer.Count == 0) return 0; - double mean = buffer.Average(); - double sumSquaredDiff = 0; - for (int i = 0; i < buffer.Count; i++) - { - double diff = buffer[i] - mean; - sumSquaredDiff += diff * diff; - } - return sumSquaredDiff / buffer.Count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate return - double ret = Math.Abs(_prevClose) > double.Epsilon ? Math.Log(BarInput.Close / _prevClose) : 0; - _returns.Add(ret); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - // Need enough returns for volatility calculation - if (_index <= _period) - { - return 0; - } - - // Calculate current volatility (annualized) - double vol = Math.Sqrt(CalculateVariance(_returns)) * Math.Sqrt(252); - _volatilities.Add(vol); - - // Need enough volatilities for cone calculation - if (_index <= WarmupPeriod) - { - return vol; - } - - // Calculate mean and standard deviation of volatilities - double meanVol = _volatilities.Average(); - double stdVol = Math.Sqrt(CalculateVariance(_volatilities)); - - // Calculate bounds - _upperBound = meanVol + (_deviations * stdVol); - _lowerBound = Math.Max(0, meanVol - (_deviations * stdVol)); - - IsHot = _index >= WarmupPeriod; - return meanVol; - } - - /// - /// Gets the upper bound of the volatility cone - /// - public double UpperBound => _upperBound; - - /// - /// Gets the lower bound of the volatility cone - /// - public double LowerBound => _lowerBound; -} diff --git a/lib/volatility/Vov.cs b/lib/volatility/Vov.cs deleted file mode 100644 index 6c92b7d8..00000000 --- a/lib/volatility/Vov.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VOV: Volatility of Volatility -/// A technical indicator that measures the volatility of volatility itself, -/// providing insight into the stability of market volatility. -/// -/// -/// The VOV calculation process: -/// 1. Calculate primary volatility (e.g., using True Range) -/// 2. Calculate standard deviation of primary volatility -/// 3. Normalize result for comparison -/// -/// Key characteristics: -/// - Second-order volatility measure -/// - Default period is 20 days -/// - Always positive -/// - No upper bound -/// - Measures volatility stability -/// -/// Formula: -/// Primary Volatility = TR (True Range) -/// VOV = StdDev(Primary Volatility, period) / Average(Primary Volatility, period) -/// -/// Market Applications: -/// - Risk of risk assessment -/// - Volatility regime changes -/// - Market stability analysis -/// - Trading strategy adaptation -/// - Risk management -/// -/// Note: Higher values indicate more unstable volatility conditions -/// -[SkipLocalsInit] -public sealed class Vov : AbstractBase -{ - private readonly int _period; - private readonly CircularBuffer _volatilities; - private double _prevClose; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vov(int period = 20) - { - _period = period; - WarmupPeriod = period + 1; // Need extra period for TR calculation - Name = $"VOV({_period})"; - _volatilities = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vov(object source, int period = 20) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _volatilities.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateVariance(CircularBuffer buffer) - { - if (buffer.Count == 0) return 0; - double mean = buffer.Average(); - double sumSquaredDiff = 0; - for (int i = 0; i < buffer.Count; i++) - { - double diff = buffer[i] - mean; - sumSquaredDiff += diff * diff; - } - return sumSquaredDiff / buffer.Count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate True Range as primary volatility measure - double tr = Math.Max(BarInput.High - BarInput.Low, - Math.Max(Math.Abs(BarInput.High - _prevClose), - Math.Abs(BarInput.Low - _prevClose))); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - // Add volatility to buffer - _volatilities.Add(tr); - - // Need enough volatilities for VOV calculation - if (_index <= _period) - { - return 0; - } - - // Calculate mean volatility - double meanVol = _volatilities.Average(); - - // Calculate VOV (normalized standard deviation) - double vov = meanVol > double.Epsilon ? Math.Sqrt(CalculateVariance(_volatilities)) / meanVol : 0; - - IsHot = _index >= WarmupPeriod; - return vov; - } -} diff --git a/lib/volatility/Vr.cs b/lib/volatility/Vr.cs deleted file mode 100644 index d32c113c..00000000 --- a/lib/volatility/Vr.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VR: Volatility Ratio -/// A technical indicator that compares volatility across different time periods -/// to identify changes in market conditions. -/// -/// -/// The VR calculation process: -/// 1. Calculate short-term volatility -/// 2. Calculate long-term volatility -/// 3. Calculate ratio between them -/// -/// Key characteristics: -/// - Relative volatility measure -/// - Default periods are 10 and 20 days -/// - Values above 1 indicate increasing volatility -/// - Values below 1 indicate decreasing volatility -/// - Normalized comparison -/// -/// Formula: -/// Short Volatility = StdDev(Returns, shortPeriod) -/// Long Volatility = StdDev(Returns, longPeriod) -/// VR = Short Volatility / Long Volatility -/// -/// Market Applications: -/// - Volatility regime changes -/// - Market condition analysis -/// - Risk assessment -/// - Trading strategy adaptation -/// - Trend confirmation -/// -/// Note: Values significantly different from 1 indicate changing market conditions -/// -[SkipLocalsInit] -public sealed class Vr : AbstractBase -{ - private readonly int _longPeriod; - private readonly CircularBuffer _shortReturns; - private readonly CircularBuffer _longReturns; - private double _prevClose; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vr(int shortPeriod = 10, int longPeriod = 20) - { - _longPeriod = longPeriod; - WarmupPeriod = longPeriod + 1; // Need one extra period for returns - Name = $"VR({shortPeriod},{_longPeriod})"; - _shortReturns = new CircularBuffer(shortPeriod); - _longReturns = new CircularBuffer(longPeriod); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vr(object source, int shortPeriod = 10, int longPeriod = 20) : this(shortPeriod, longPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _shortReturns.Clear(); - _longReturns.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private double CalculateVariance(CircularBuffer buffer) - { - if (buffer.Count == 0) return 0; - double mean = buffer.Average(); - double sumSquaredDiff = 0; - for (int i = 0; i < buffer.Count; i++) - { - double diff = buffer[i] - mean; - sumSquaredDiff += diff * diff; - } - return sumSquaredDiff / buffer.Count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate return - double ret = _prevClose > double.Epsilon ? Math.Log(BarInput.Close / _prevClose) : 0; - - // Add return to buffers - _shortReturns.Add(ret); - _longReturns.Add(ret); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - // Need enough returns for both periods - if (_index <= _longPeriod) - { - return 0; - } - - // Calculate volatilities - double shortVol = Math.Sqrt(CalculateVariance(_shortReturns)); - double longVol = Math.Sqrt(CalculateVariance(_longReturns)); - - // Calculate ratio - double vr = longVol > double.Epsilon ? shortVol / longVol : 1; - - IsHot = _index >= WarmupPeriod; - return vr; - } -} diff --git a/lib/volatility/Vs.cs b/lib/volatility/Vs.cs deleted file mode 100644 index 6755c505..00000000 --- a/lib/volatility/Vs.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VS: Volatility Stop -/// A technical indicator that uses volatility to determine stop levels, -/// adapting to market conditions for dynamic risk management. -/// -/// -/// The VS calculation process: -/// 1. Calculate Average True Range (ATR) -/// 2. Calculate stop levels: -/// Long Stop = Close - (multiplier * ATR) -/// Short Stop = Close + (multiplier * ATR) -/// 3. Trail stops based on price movement -/// -/// Key characteristics: -/// - Adaptive stop levels -/// - Based on ATR volatility -/// - Default period is 14 days -/// - Returns both long and short stops -/// - Trails with price movement -/// -/// Formula: -/// ATR = Average(TR, period) -/// Long Stop = Close - (multiplier * ATR) -/// Short Stop = Close + (multiplier * ATR) -/// -/// Market Applications: -/// - Stop loss placement -/// - Position management -/// - Risk control -/// - Trend following -/// - Exit strategy -/// -/// Sources: -/// Adaptation of Volatility-Based Stops concept -/// https://www.investopedia.com/terms/v/volatility-stop.asp -/// -/// Note: Returns two values: long stop and short stop levels -/// -[SkipLocalsInit] -public sealed class Vs : AbstractBase -{ - private readonly int _period; - private readonly double _multiplier; - private readonly CircularBuffer _tr; - private double _prevClose; - private double _longStop; - private double _shortStop; - private double _prevLongStop; - private double _prevShortStop; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vs(int period = 14, double multiplier = 2.0) - { - _period = period; - _multiplier = multiplier; - WarmupPeriod = period + 1; // Need one extra period for TR - Name = $"VS({_period},{_multiplier})"; - _tr = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vs(object source, int period = 14, double multiplier = 2.0) : this(period, multiplier) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _longStop = 0; - _shortStop = 0; - _prevLongStop = 0; - _prevShortStop = 0; - _tr.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - _longStop = BarInput.Close; - _shortStop = BarInput.Close; - return 0; - } - - // Calculate True Range - double tr = Math.Max(BarInput.High - BarInput.Low, - Math.Max(Math.Abs(BarInput.High - _prevClose), - Math.Abs(BarInput.Low - _prevClose))); - - // Add TR to buffer - _tr.Add(tr); - - // Store current close for next calculation - _prevClose = BarInput.Close; - - // Need enough values for ATR calculation - if (_index <= _period) - { - return 0; - } - - // Calculate ATR - double atr = _tr.Average(); - - // Calculate initial stop levels - double potentialLongStop = BarInput.Close - (_multiplier * atr); - double potentialShortStop = BarInput.Close + (_multiplier * atr); - - // Trail stops - _longStop = BarInput.Close > _prevShortStop ? potentialLongStop : Math.Max(potentialLongStop, _prevLongStop); - _shortStop = BarInput.Close < _prevLongStop ? potentialShortStop : Math.Min(potentialShortStop, _prevShortStop); - - // Store current stops for next calculation - _prevLongStop = _longStop; - _prevShortStop = _shortStop; - - IsHot = _index >= WarmupPeriod; - return _longStop; // Return long stop as primary value - } - - /// - /// Gets the long stop level - /// - public double LongStop => _longStop; - - /// - /// Gets the short stop level - /// - public double ShortStop => _shortStop; -} diff --git a/lib/volatility/Yzv.cs b/lib/volatility/Yzv.cs deleted file mode 100644 index 4331f982..00000000 --- a/lib/volatility/Yzv.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// YZV: Yang-Zhang Volatility -/// A volatility estimator that combines overnight and trading volatilities, -/// providing a more complete picture of price variation while being drift-independent. -/// -/// -/// The YZV calculation process: -/// 1. Calculate overnight (close-to-open) volatility -/// 2. Calculate open-to-close volatility -/// 3. Calculate Rogers-Satchell volatility -/// 4. Combine components with optimal weights -/// -/// Key characteristics: -/// - Drift independence -/// - Minimum variance -/// - Handles overnight gaps -/// - Uses all HLOC prices -/// - Optimal weighting -/// -/// Formula: -/// YZV = sqrt(Vo + k*Vc + (1-k)*Vrs) -/// where: -/// Vo = overnight volatility -/// Vc = open-to-close volatility -/// Vrs = Rogers-Satchell volatility -/// k ≈ 0.34 (optimal weight) -/// -/// Market Applications: -/// - Option pricing -/// - Risk measurement -/// - Trading systems -/// - Portfolio management -/// - Market analysis -/// -/// Note: Most efficient unbiased estimator among drift-independent estimators -/// -[SkipLocalsInit] -public sealed class Yzv : AbstractBase -{ - private readonly Sma _maCo; // Close-to-Open - private readonly Sma _maOc; // Open-to-Close - private readonly Sma _maRs; // Rogers-Satchell - private double _prevClose; - private double _prevValue; - private const double K = 0.34; // Optimal weight - private const int DefaultPeriod = 20; - - /// The number of periods for volatility calculation (default 20). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Yzv(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _maCo = new(period); - _maOc = new(period); - _maRs = new(period); - WarmupPeriod = period; - Name = $"YZV({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for volatility calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Yzv(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _prevClose = BarInput.Close; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - if (!BarInput.IsNew) - return _prevValue; - - ManageState(true); - - // Calculate overnight volatility (close-to-open) - double co = Math.Log(BarInput.Open / _prevClose); - double vo = _maCo.Calc(co * co, true); - - // Calculate open-to-close volatility - double oc = Math.Log(BarInput.Close / BarInput.Open); - double vc = _maOc.Calc(oc * oc, true); - - // Calculate Rogers-Satchell volatility component - double lnHC = Math.Log(BarInput.High / BarInput.Close); - double lnHO = Math.Log(BarInput.High / BarInput.Open); - double lnLC = Math.Log(BarInput.Low / BarInput.Close); - double lnLO = Math.Log(BarInput.Low / BarInput.Open); - double rs = (lnHC * lnHO) + (lnLC * lnLO); - double vrs = _maRs.Calc(rs, true); - - // Combine components with optimal weights - _prevValue = Math.Sqrt(vo + (K * vc) + ((1.0 - K) * vrs)); - return _prevValue; - } -} diff --git a/lib/volatility/_list.md b/lib/volatility/_list.md deleted file mode 100644 index bb1c8d0c..00000000 --- a/lib/volatility/_list.md +++ /dev/null @@ -1,38 +0,0 @@ -# Volatility indicators -Done: 31, Todo: 4 - -✔️ ADR - Average Daily Range -✔️ AP - Andrew's Pitchfork -✔️ ATR - Average True Range -✔️ ATRP - Average True Range Percent -✔️ ATRS - ATR Trailing Stop -✔️ BBAND - Bollinger Bands® (Upper, Middle, Lower) -✔️ CCV - Close-to-Close Volatility -✔️ CE - Chandelier Exit -✔️ CV - Conditional Volatility (ARCH/GARCH) -✔️ CVI - Chaikin's Volatility -✔️ DCHN - Donchian Channels (Upper, Middle, Lower) -✔️ EWMA - Exponential Weighted Moving Average Volatility -✔️ FCB - Fractal Chaos Bands -✔️ GKV - Garman-Klass Volatility -✔️ HLV - High-Low Volatility -✔️ HV - Historical Volatility -✔️ JVOLTY - Jurik Volatility (Jvolty, Upper band, Lower band) -✔️ NATR - Normalized Average True Range -✔️ PCH - Price Channel Indicator -✔️ PV - Parkinson Volatility -✔️ RSV - Rogers-Satchell Volatility -✔️ RV - Realized Volatility -✔️ RVI - Relative Volatility Index -✔️ SV - Stochastic Volatility -✔️ TR - True Range -✔️ UI - Ulcer Index -✔️ VC - Volatility Cone (Mean, Upper Bound, Lower Bound) -✔️ VOV - Volatility of Volatility -✔️ VR - Volatility Ratio -✔️ *VS - Volatility Stop (Long Stop, Short Stop) -✔️ YZV - Yang-Zhang Volatility -ICH - Ichimoku Cloud (Conversion, Base, Leading Span A, Leading Span B, Lagging Span) -KC - Keltner Channels (Upper, Middle, Lower) -PSAR - Parabolic Stop and Reverse (Value, Trend) -STARC - Starc Bands (Upper, Middle, Lower) diff --git a/lib/volume/Adl.cs b/lib/volume/Adl.cs deleted file mode 100644 index aae5dea1..00000000 --- a/lib/volume/Adl.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ADL: Accumulation Distribution Line (Chaikin) -/// A volume-based indicator that measures the cumulative flow of money into and out -/// of a security. It assesses the relationship between price and volume to determine -/// buying/selling pressure. -/// -/// -/// The ADL calculation process: -/// 1. Calculates Money Flow Multiplier (MFM): -/// MFM = ((Close - Low) - (High - Close)) / (High - Low) -/// 2. Calculates Money Flow Volume (MFV): -/// MFV = MFM × Volume -/// 3. ADL is cumulative sum of MFV values -/// -/// Key characteristics: -/// - Volume-weighted measure -/// - Cumulative indicator -/// - No upper/lower bounds -/// - Trend confirmation tool -/// - Divergence indicator -/// -/// Formula: -/// MFM = ((Close - Low) - (High - Close)) / (High - Low) -/// MFV = MFM × Volume -/// ADL = Previous ADL + MFV -/// -/// Market Applications: -/// - Trend confirmation -/// - Volume analysis -/// - Price/volume divergence -/// - Support/resistance levels -/// - Market participation -/// -/// Sources: -/// Marc Chaikin - Original development -/// https://www.investopedia.com/terms/a/accumulationdistribution.asp -/// -/// Note: Focuses on the relationship between price and volume -/// -[SkipLocalsInit] -public sealed class Adl : AbstractBase -{ - private double _cumulativeAdl; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adl() - { - WarmupPeriod = 1; - Name = "ADL"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adl(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _cumulativeAdl = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMoneyFlowMultiplier(double close, double high, double low) - { - double range = high - low; - if (range > 0) - { - return ((close - low) - (high - close)) / range; - } - return 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate Money Flow Multiplier - double mfm = CalculateMoneyFlowMultiplier(BarInput.Close, BarInput.High, BarInput.Low); - - // Calculate Money Flow Volume - double mfv = mfm * BarInput.Volume; - - // Update cumulative ADL only for new bars - if (BarInput.IsNew) - { - _cumulativeAdl += mfv; - } - - IsHot = _index >= WarmupPeriod; - return _cumulativeAdl; - } -} diff --git a/lib/volume/Adosc.cs b/lib/volume/Adosc.cs deleted file mode 100644 index 614244c1..00000000 --- a/lib/volume/Adosc.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// ADOSC: Chaikin Accumulation/Distribution Oscillator -/// A momentum indicator that measures the strength of accumulation/distribution by combining -/// price and volume with moving averages. It helps identify potential trend reversals and -/// buying/selling pressure. -/// -/// -/// The ADOSC calculation process: -/// 1. Calculate ADL (Accumulation/Distribution Line) -/// a. Money Flow Multiplier = ((Close - Low) - (High - Close)) / (High - Low) -/// b. Money Flow Volume = MFM × Volume -/// c. ADL = Previous ADL + MFV -/// 2. Calculate two EMAs of ADL values -/// 3. Subtract longer EMA from shorter EMA -/// -/// Key characteristics: -/// - Volume-weighted measure -/// - Oscillates around zero -/// - Uses two different time periods -/// - Default periods are 3 and 10 days -/// - Shows momentum of money flow -/// -/// Formula: -/// MFM = ((Close - Low) - (High - Close)) / (High - Low) -/// MFV = MFM × Volume -/// ADL = Previous ADL + MFV -/// ADOSC = EMA(ADL, shortPeriod) - EMA(ADL, longPeriod) -/// -/// Market Applications: -/// - Trend confirmation -/// - Divergence analysis -/// - Volume/price relationship -/// - Support/resistance levels -/// - Market reversals -/// -/// Sources: -/// Marc Chaikin - Original development -/// https://www.investopedia.com/terms/c/chaikinoscillator.asp -/// -/// Note: Positive values indicate buying pressure, while negative values indicate selling pressure -/// -[SkipLocalsInit] -public sealed class Adosc : AbstractBase -{ - private readonly int _longPeriod; - private double _cumulativeAdl; - private double _shortEma; - private double _longEma; - private readonly double _shortAlpha; - private readonly double _longAlpha; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adosc(int shortPeriod = 3, int longPeriod = 10) - { - _longPeriod = longPeriod; - WarmupPeriod = longPeriod; // Need longer period for EMA calculation - Name = $"ADOSC({shortPeriod},{_longPeriod})"; - _shortAlpha = 2.0 / (shortPeriod + 1); - _longAlpha = 2.0 / (longPeriod + 1); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Adosc(object source, int shortPeriod = 3, int longPeriod = 10) : this(shortPeriod, longPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _cumulativeAdl = 0; - _shortEma = 0; - _longEma = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMoneyFlowMultiplier(double close, double high, double low) - { - double range = high - low; - if (range > 0) - { - return ((close - low) - (high - close)) / range; - } - return 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate Money Flow Multiplier - double mfm = CalculateMoneyFlowMultiplier(BarInput.Close, BarInput.High, BarInput.Low); - - // Calculate Money Flow Volume - double mfv = mfm * BarInput.Volume; - - // Update cumulative ADL - _cumulativeAdl += mfv; - - // Calculate EMAs - if (_index <= _longPeriod) - { - // Initialize EMAs - _shortEma = _cumulativeAdl; - _longEma = _cumulativeAdl; - return 0; - } - - // Update EMAs - _shortEma = (_shortAlpha * _cumulativeAdl) + ((1 - _shortAlpha) * _shortEma); - _longEma = (_longAlpha * _cumulativeAdl) + ((1 - _longAlpha) * _longEma); - - // Calculate ADOSC - double adosc = _shortEma - _longEma; - - IsHot = _index >= WarmupPeriod; - return adosc; - } -} diff --git a/lib/volume/Aobv.cs b/lib/volume/Aobv.cs deleted file mode 100644 index 25ca5abc..00000000 --- a/lib/volume/Aobv.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// AOBV: Archer On-Balance Volume -/// A modified version of the traditional On-Balance Volume (OBV) indicator that uses a more -/// sophisticated method to determine buying and selling pressure. It considers both the -/// closing price and the price range to provide a more nuanced view of volume flow. -/// -/// -/// The AOBV calculation process: -/// 1. Determine price position within the day's range -/// 2. Apply volume based on price position: -/// - If close is in upper 1/3 of range: Add full volume -/// - If close is in middle 1/3 of range: Add/subtract half volume -/// - If close is in lower 1/3 of range: Subtract full volume -/// -/// Key characteristics: -/// - Volume-weighted measure -/// - Cumulative indicator -/// - No upper/lower bounds -/// - More nuanced than traditional OBV -/// - Considers price position in range -/// -/// Formula: -/// Range = High - Low -/// UpperThird = High - (Range / 3) -/// LowerThird = Low + (Range / 3) -/// If Close >= UpperThird: -/// AOBV = Previous AOBV + Volume -/// Else if Close <= LowerThird: -/// AOBV = Previous AOBV - Volume -/// Else: -/// If Close > Previous Close: -/// AOBV = Previous AOBV + (Volume / 2) -/// Else: -/// AOBV = Previous AOBV - (Volume / 2) -/// -/// Market Applications: -/// - Trend confirmation -/// - Volume analysis -/// - Price/volume divergence -/// - Support/resistance levels -/// - Market participation -/// -/// Sources: -/// Steve Archer - Original development -/// Technical Analysis of Stock Trends (Edwards, Magee) -/// -/// Note: Provides a more detailed analysis of volume flow than traditional OBV -/// -[SkipLocalsInit] -public sealed class Aobv : AbstractBase -{ - private double _cumulativeAobv; - private double _prevClose; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Aobv() - { - WarmupPeriod = 1; - Name = "AOBV"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Aobv(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _cumulativeAobv = 0; - _prevClose = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - double range = BarInput.High - BarInput.Low; - if (range > 0) - { - double upperThird = BarInput.High - (range / 3); - double lowerThird = BarInput.Low + (range / 3); - - // Determine volume flow based on price position - if (BarInput.Close >= upperThird) - { - _cumulativeAobv += BarInput.Volume; - } - else if (BarInput.Close <= lowerThird) - { - _cumulativeAobv -= BarInput.Volume; - } - else - { - // In middle third, use half volume based on close comparison - _cumulativeAobv += (BarInput.Close > _prevClose) ? - (BarInput.Volume / 2) : -(BarInput.Volume / 2); - } - } - - _prevClose = BarInput.Close; - - IsHot = _index >= WarmupPeriod; - return _cumulativeAobv; - } -} diff --git a/lib/volume/Cmf.cs b/lib/volume/Cmf.cs deleted file mode 100644 index 1d3ed3d2..00000000 --- a/lib/volume/Cmf.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// CMF: Chaikin Money Flow -/// A volume-weighted technical indicator that measures the amount of Money Flow Volume (MFV) -/// over a specific period. Unlike ADL which is cumulative, CMF averages the Money Flow -/// Volume over a specified period. -/// -/// -/// The CMF calculation process: -/// 1. Calculates Money Flow Multiplier (MFM): -/// MFM = ((Close - Low) - (High - Close)) / (High - Low) -/// 2. Calculates Money Flow Volume (MFV): -/// MFV = MFM × Volume -/// 3. CMF = Sum(MFV) / Sum(Volume) over N periods -/// -/// Key characteristics: -/// - Oscillator between -1 and +1 -/// - Volume-weighted measure -/// - Non-cumulative indicator -/// - Default period is 20 days -/// -/// Formula: -/// MFM = ((Close - Low) - (High - Close)) / (High - Low) -/// MFV = MFM × Volume -/// CMF = Sum(MFV over N periods) / Sum(Volume over N periods) -/// -/// Market Applications: -/// - Trend confirmation -/// - Volume analysis -/// - Price/volume divergence -/// - Support/resistance levels -/// - Market participation -/// -/// Sources: -/// Marc Chaikin - Original development -/// https://www.investopedia.com/terms/c/chaikinmoneyflow.asp -/// -/// Note: Values above zero indicate buying pressure, while values below zero indicate selling pressure -/// -[SkipLocalsInit] -public sealed class Cmf : AbstractBase -{ - private readonly int _period; - private readonly double[] _mfv; - private readonly double[] _volume; - private int _position; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cmf(int period = 20) - { - _period = period; - WarmupPeriod = period; - Name = $"CMF({_period})"; - _mfv = new double[period]; - _volume = new double[period]; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cmf(object source, int period = 20) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _position = 0; - Array.Clear(_mfv, 0, _mfv.Length); - Array.Clear(_volume, 0, _volume.Length); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static double CalculateMoneyFlowMultiplier(double close, double high, double low) - { - double range = high - low; - if (range > 0) - { - return ((close - low) - (high - close)) / range; - } - return 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate Money Flow Multiplier - double mfm = CalculateMoneyFlowMultiplier(BarInput.Close, BarInput.High, BarInput.Low); - - // Calculate Money Flow Volume - double currentMfv = mfm * BarInput.Volume; - - // Update circular buffers - _mfv[_position] = currentMfv; - _volume[_position] = BarInput.Volume; - _position = (_position + 1) % _period; - - // Calculate CMF - double sumMfv = 0; - double sumVolume = 0; - for (int i = 0; i < _period; i++) - { - sumMfv += _mfv[i]; - sumVolume += _volume[i]; - } - - double cmf = Math.Abs(sumVolume) > double.Epsilon ? sumMfv / sumVolume : 0; - IsHot = _index >= WarmupPeriod; - return cmf; - } -} diff --git a/lib/volume/Eom.cs b/lib/volume/Eom.cs deleted file mode 100644 index 640201f8..00000000 --- a/lib/volume/Eom.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// EOM: Ease of Movement -/// A volume-based technical indicator that relates price change to volume, showing the -/// relationship between price change and volume. It emphasizes days where price changes -/// are accomplished with minimal volume and minimizes days where large volume generates -/// small price changes. -/// -/// -/// The EOM calculation process: -/// 1. Calculate the distance moved: -/// Distance = ((High + Low)/2 - (Prior High + Prior Low)/2) -/// 2. Calculate the Box Ratio: -/// BoxRatio = Volume / (High - Low) -/// 3. Calculate single-period EMV: -/// EMV = Distance / BoxRatio -/// 4. Smooth EMV using simple moving average (optional) -/// -/// Key characteristics: -/// - Volume-weighted measure -/// - Oscillates around zero -/// - Shows ease of price movement -/// - Default period is 14 days -/// -/// Formula: -/// Distance = ((H + L)/2 - (pH + pL)/2) -/// BoxRatio = Volume / (High - Low) -/// EMV = Distance / BoxRatio -/// EOM = SMA(EMV, period) -/// -/// Market Applications: -/// - Trend strength analysis -/// - Volume/price relationship -/// - Support/resistance breakouts -/// - Market momentum -/// - Divergence identification -/// -/// Sources: -/// Richard W. Arms Jr. - Original development -/// https://www.investopedia.com/terms/e/easeofmovement.asp -/// -/// Note: Positive values suggest prices are rising with light volume (bullish), -/// while negative values suggest prices are falling with light volume (bearish) -/// -[SkipLocalsInit] -public sealed class Eom : AbstractBase -{ - private readonly int _period; - private readonly double[] _emv; - private int _position; - private double _prevMidpoint; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Eom(int period = 14) - { - _period = period; - WarmupPeriod = period + 1; // Need one extra period for previous midpoint - Name = $"EOM({_period})"; - _emv = new double[period]; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Eom(object source, int period = 14) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _position = 0; - _prevMidpoint = 0; - Array.Clear(_emv, 0, _emv.Length); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - double midpoint = (BarInput.High + BarInput.Low) / 2; - double boxRatio = BarInput.Volume / (BarInput.High - BarInput.Low + double.Epsilon); // Avoid division by zero - - // Skip first period to establish previous midpoint - if (_index == 1) - { - _prevMidpoint = midpoint; - return 0; - } - - // Calculate distance moved - double distance = midpoint - _prevMidpoint; - - // Calculate EMV for this period - double emv = distance / boxRatio * 10000; // Multiply by 10000 to make values more readable - - // Store in circular buffer - _emv[_position] = emv; - _position = (_position + 1) % _period; - - // Calculate EOM (simple moving average of EMV) - double sum = 0; - for (int i = 0; i < _period; i++) - { - sum += _emv[i]; - } - double eom = sum / _period; - - // Store current midpoint for next calculation - _prevMidpoint = midpoint; - - IsHot = _index >= WarmupPeriod; - return eom; - } -} diff --git a/lib/volume/Kvo.cs b/lib/volume/Kvo.cs deleted file mode 100644 index c0fb983f..00000000 --- a/lib/volume/Kvo.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// KVO: Klinger Volume Oscillator -/// A volume-based technical indicator that compares volume to price movement to identify -/// long-term trends and potential reversals. It helps determine the long-term money flow -/// while remaining sensitive to short-term fluctuations. -/// -/// -/// The KVO calculation process: -/// 1. Calculate Trend: -/// Trend = Current DM > Previous DM ? +1 : -1 -/// 2. Calculate Volume Force (VF): -/// VF = Volume * abs(ROC) * Trend * 100 -/// 3. Calculate two EMAs of VF and their difference: -/// Signal = EMA(VF, shortPeriod) - EMA(VF, longPeriod) -/// -/// Key characteristics: -/// - Volume-weighted measure -/// - Oscillates around zero -/// - Uses two different time periods -/// - Default periods are 34 and 55 days -/// - Shows volume force and price direction -/// -/// Formula: -/// DM = (H + L + C) / 3 -/// Trend = DM > Previous DM ? +1 : -1 -/// VF = Volume * abs(ROC) * Trend * 100 -/// KVO = EMA(VF, shortPeriod) - EMA(VF, longPeriod) -/// -/// Market Applications: -/// - Trend confirmation -/// - Divergence analysis -/// - Volume/price relationship -/// - Support/resistance levels -/// - Market reversals -/// -/// Sources: -/// Stephen Klinger - Original development -/// https://www.investopedia.com/terms/k/klingeroscillator.asp -/// -/// Note: Positive values indicate buying pressure, while negative values indicate selling pressure -/// -[SkipLocalsInit] -public sealed class Kvo : AbstractBase -{ - private readonly int _longPeriod; - private double _prevDm; - private double _shortEma; - private double _longEma; - private readonly double _shortAlpha; - private readonly double _longAlpha; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Kvo(int shortPeriod = 34, int longPeriod = 55) - { - _longPeriod = longPeriod; - WarmupPeriod = longPeriod + 1; // Need one extra period for previous DM - Name = $"KVO({shortPeriod},{_longPeriod})"; - _shortAlpha = 2.0 / (shortPeriod + 1); - _longAlpha = 2.0 / (longPeriod + 1); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Kvo(object source, int shortPeriod = 34, int longPeriod = 55) : this(shortPeriod, longPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevDm = 0; - _shortEma = 0; - _longEma = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate Daily Mean - double dm = (BarInput.High + BarInput.Low + BarInput.Close) / 3; - - // Skip first period to establish previous DM - if (_index == 1) - { - _prevDm = dm; - return 0; - } - - // Calculate Trend - int trend = dm > _prevDm ? 1 : -1; - - // Calculate Rate of Change - double roc = Math.Abs(dm - _prevDm) / _prevDm; - - // Calculate Volume Force - double vf = BarInput.Volume * roc * trend * 100; - - // Calculate EMAs - if (_index <= _longPeriod) - { - // Initialize EMAs - _shortEma = vf; - _longEma = vf; - } - else - { - // Update EMAs - _shortEma = (_shortAlpha * vf) + ((1 - _shortAlpha) * _shortEma); - _longEma = (_longAlpha * vf) + ((1 - _longAlpha) * _longEma); - } - - // Store current DM for next calculation - _prevDm = dm; - - // Calculate KVO - double kvo = _shortEma - _longEma; - - IsHot = _index >= WarmupPeriod; - return kvo; - } -} diff --git a/lib/volume/Mfi.cs b/lib/volume/Mfi.cs deleted file mode 100644 index 4316d8c7..00000000 --- a/lib/volume/Mfi.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// MFI: Money Flow Index -/// A volume-weighted momentum indicator that measures the inflow and outflow of money into an asset -/// over a specific period of time. It's sometimes referred to as volume-weighted RSI. -/// -/// -/// The MFI calculation process: -/// 1. Calculate Typical Price: -/// TP = (High + Low + Close) / 3 -/// 2. Calculate Raw Money Flow: -/// RMF = TP * Volume -/// 3. Determine Positive/Negative Money Flow: -/// If TP > Previous TP: Positive Money Flow -/// If TP < Previous TP: Negative Money Flow -/// 4. Calculate Money Flow Ratio: -/// MFR = (14-period Positive Money Flow Sum) / (14-period Negative Money Flow Sum) -/// 5. Calculate Money Flow Index: -/// MFI = 100 - (100 / (1 + MFR)) -/// -/// Key characteristics: -/// - Oscillates between 0 and 100 -/// - Default period is 14 days -/// - Overbought level typically at 80 -/// - Oversold level typically at 20 -/// - Volume-weighted measure -/// -/// Formula: -/// TP = (High + Low + Close) / 3 -/// RMF = TP * Volume -/// MFR = ΣPositive Money Flow / ΣNegative Money Flow -/// MFI = 100 - (100 / (1 + MFR)) -/// -/// Market Applications: -/// - Overbought/Oversold conditions -/// - Divergence analysis -/// - Trend confirmation -/// - Price reversals -/// - Volume flow analysis -/// -/// Sources: -/// Gene Quong and Avrum Soudack - Original development -/// https://www.investopedia.com/terms/m/mfi.asp -/// -/// Note: Values above 80 indicate overbought conditions, while values below 20 indicate oversold conditions -/// -[SkipLocalsInit] -public sealed class Mfi : AbstractBase -{ - private readonly CircularBuffer _posMf; - private readonly CircularBuffer _negMf; - private double _prevTp; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mfi(int period = 14) - { - WarmupPeriod = period + 1; // Need one extra period for previous TP - Name = $"MFI({period})"; - _posMf = new CircularBuffer(period); - _negMf = new CircularBuffer(period); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Mfi(object source, int period = 14) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevTp = 0; - _posMf.Clear(); - _negMf.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate Typical Price - double tp = (BarInput.High + BarInput.Low + BarInput.Close) / 3; - - // Skip first period to establish previous TP - if (_index == 1) - { - _prevTp = tp; - return 0; - } - - // Calculate Raw Money Flow - double rmf = tp * BarInput.Volume; - - // Determine Positive/Negative Money Flow - if (tp > _prevTp) - { - _posMf.Add(rmf); - _negMf.Add(0); - } - else if (tp < _prevTp) - { - _posMf.Add(0); - _negMf.Add(rmf); - } - else - { - _posMf.Add(0); - _negMf.Add(0); - } - - // Store current TP for next calculation - _prevTp = tp; - - // Calculate Money Flow Ratio and Index - double posMfSum = _posMf.Sum(); - double negMfSum = _negMf.Sum(); - - double mfi = Math.Abs(negMfSum) < double.Epsilon ? 100 : 100 - (100 / (1 + (posMfSum / negMfSum))); - - IsHot = _index >= WarmupPeriod; - return mfi; - } -} diff --git a/lib/volume/Nvi.cs b/lib/volume/Nvi.cs deleted file mode 100644 index 6a1899c1..00000000 --- a/lib/volume/Nvi.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// NVI: Negative Volume Index -/// A cumulative indicator that focuses on days when volume decreases from the previous day. -/// It is based on the premise that smart money is active on days with lower volume. -/// -/// -/// The NVI calculation process: -/// 1. Compare current volume with previous volume -/// 2. If current volume is less than previous volume: -/// NVI = Previous NVI + (((Close - Previous Close) / Previous Close) * Previous NVI) -/// 3. If current volume is greater than or equal to previous volume: -/// NVI = Previous NVI -/// -/// Key characteristics: -/// - Cumulative indicator -/// - Only updates on lower volume days -/// - Starts at base value of 1000 -/// - Focuses on smart money activity -/// - Volume-driven measure -/// -/// Formula: -/// If Volume < Previous Volume: -/// NVI = Previous NVI + (Price % Change * Previous NVI) -/// Else: -/// NVI = Previous NVI -/// -/// Market Applications: -/// - Smart money tracking -/// - Trend identification -/// - Market timing -/// - Volume analysis -/// - Price confirmation -/// -/// Sources: -/// Paul Dysart - Original development (1930s) -/// Norman Fosback - Further development -/// https://www.investopedia.com/terms/n/nvi.asp -/// -/// Note: Rising NVI suggests smart money is buying, while falling NVI suggests smart money is selling -/// -[SkipLocalsInit] -public sealed class Nvi : AbstractBase -{ - private double _prevClose; - private double _prevVolume; - private double _prevNvi; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Nvi() - { - WarmupPeriod = 2; // Need previous volume and close - Name = "NVI"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Nvi(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevVolume = 0; - _prevNvi = 1000; // Standard starting value - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous values - if (_index == 1) - { - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - return _prevNvi; - } - - // Calculate NVI - if (BarInput.Volume < _prevVolume) - { - double priceChange = ((BarInput.Close - _prevClose) / _prevClose); - _prevNvi += priceChange * _prevNvi; - } - - // Store current values for next calculation - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - - IsHot = _index >= WarmupPeriod; - return _prevNvi; - } -} diff --git a/lib/volume/Obv.cs b/lib/volume/Obv.cs deleted file mode 100644 index 2927b3ad..00000000 --- a/lib/volume/Obv.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// OBV: On-Balance Volume -/// A momentum indicator that uses volume flow to predict changes in stock price. -/// It accumulates volume on up days and subtracts volume on down days. -/// -/// -/// The OBV calculation process: -/// 1. Compare current close with previous close -/// 2. If current close is higher: -/// OBV = Previous OBV + Current Volume -/// 3. If current close is lower: -/// OBV = Previous OBV - Current Volume -/// 4. If current close equals previous close: -/// OBV = Previous OBV -/// -/// Key characteristics: -/// - Cumulative indicator -/// - Volume-based momentum measure -/// - Leading indicator -/// - No upper or lower bounds -/// - Focuses on volume flow -/// -/// Formula: -/// If Close > Previous Close: -/// OBV = Previous OBV + Volume -/// If Close < Previous Close: -/// OBV = Previous OBV - Volume -/// If Close = Previous Close: -/// OBV = Previous OBV -/// -/// Market Applications: -/// - Trend confirmation -/// - Potential breakouts -/// - Divergence analysis -/// - Volume flow analysis -/// - Price movement prediction -/// -/// Sources: -/// Joe Granville - Original development (1963) -/// https://www.investopedia.com/terms/o/onbalancevolume.asp -/// -/// Note: Rising OBV suggests buying pressure, while falling OBV suggests selling pressure -/// -[SkipLocalsInit] -public sealed class Obv : AbstractBase -{ - private double _prevClose; - private double _prevObv; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Obv() - { - WarmupPeriod = 2; // Need previous close - Name = "OBV"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Obv(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevObv = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate OBV - if (BarInput.Close > _prevClose) - { - _prevObv += BarInput.Volume; - } - else if (BarInput.Close < _prevClose) - { - _prevObv -= BarInput.Volume; - } - // If prices equal, OBV remains the same - - // Store current close for next calculation - _prevClose = BarInput.Close; - - IsHot = _index >= WarmupPeriod; - return _prevObv; - } -} diff --git a/lib/volume/Pvi.cs b/lib/volume/Pvi.cs deleted file mode 100644 index e66affc3..00000000 --- a/lib/volume/Pvi.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PVI: Positive Volume Index -/// A cumulative indicator that focuses on days when volume increases from the previous day. -/// It is based on the premise that the public is active on days with higher volume. -/// -/// -/// The PVI calculation process: -/// 1. Compare current volume with previous volume -/// 2. If current volume is greater than previous volume: -/// PVI = Previous PVI + (((Close - Previous Close) / Previous Close) * Previous PVI) -/// 3. If current volume is less than or equal to previous volume: -/// PVI = Previous PVI -/// -/// Key characteristics: -/// - Cumulative indicator -/// - Only updates on higher volume days -/// - Starts at base value of 1000 -/// - Focuses on public activity -/// - Volume-driven measure -/// -/// Formula: -/// If Volume > Previous Volume: -/// PVI = Previous PVI + (Price % Change * Previous PVI) -/// Else: -/// PVI = Previous PVI -/// -/// Market Applications: -/// - Public participation tracking -/// - Trend identification -/// - Market timing -/// - Volume analysis -/// - Price confirmation -/// -/// Sources: -/// Norman Fosback - Original development -/// https://www.investopedia.com/terms/p/pvi.asp -/// -/// Note: Rising PVI suggests public buying pressure, while falling PVI suggests public selling pressure -/// -[SkipLocalsInit] -public sealed class Pvi : AbstractBase -{ - private double _prevClose; - private double _prevVolume; - private double _prevPvi; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvi() - { - WarmupPeriod = 2; // Need previous volume and close - Name = "PVI"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvi(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevVolume = 0; - _prevPvi = 1000; // Standard starting value - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous values - if (_index == 1) - { - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - return _prevPvi; - } - - // Calculate PVI - if (BarInput.Volume > _prevVolume) - { - double priceChange = ((BarInput.Close - _prevClose) / _prevClose); - _prevPvi += priceChange * _prevPvi; - } - - // Store current values for next calculation - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - - IsHot = _index >= WarmupPeriod; - return _prevPvi; - } -} diff --git a/lib/volume/Pvo.cs b/lib/volume/Pvo.cs deleted file mode 100644 index 17a1a4ee..00000000 --- a/lib/volume/Pvo.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PVO: Percentage Volume Oscillator -/// A momentum indicator for volume that shows the relationship between two volume moving averages -/// as a percentage. Similar to the Price Oscillator but uses volume instead of price. -/// -/// -/// The PVO calculation process: -/// 1. Calculate short-term EMA of volume -/// 2. Calculate long-term EMA of volume -/// 3. Calculate PVO: -/// PVO = ((Short EMA - Long EMA) / Long EMA) * 100 -/// -/// Key characteristics: -/// - Volume-based momentum indicator -/// - Oscillates around zero -/// - Shows volume trends -/// - Default periods are 12 and 26 days -/// - Percentage-based measure -/// -/// Formula: -/// Short EMA = EMA(Volume, shortPeriod) -/// Long EMA = EMA(Volume, longPeriod) -/// PVO = ((Short EMA - Long EMA) / Long EMA) * 100 -/// -/// Market Applications: -/// - Volume trend analysis -/// - Divergence identification -/// - Volume momentum measurement -/// - Market tops and bottoms -/// - Trading volume patterns -/// -/// Sources: -/// https://www.investopedia.com/terms/p/pvo.asp -/// -/// Note: Positive values indicate higher short-term volume, while negative values indicate higher long-term volume -/// -[SkipLocalsInit] -public sealed class Pvo : AbstractBase -{ - private readonly int _longPeriod; - private double _shortEma; - private double _longEma; - private readonly double _shortAlpha; - private readonly double _longAlpha; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvo(int shortPeriod = 12, int longPeriod = 26) - { - _longPeriod = longPeriod; - WarmupPeriod = longPeriod; - Name = $"PVO({shortPeriod},{_longPeriod})"; - _shortAlpha = 2.0 / (shortPeriod + 1); - _longAlpha = 2.0 / (longPeriod + 1); - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvo(object source, int shortPeriod = 12, int longPeriod = 26) : this(shortPeriod, longPeriod) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _shortEma = 0; - _longEma = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Initialize or update EMAs - if (_index <= _longPeriod) - { - _shortEma = BarInput.Volume; - _longEma = BarInput.Volume; - return 0; - } - - // Update EMAs - _shortEma = (_shortAlpha * BarInput.Volume) + ((1 - _shortAlpha) * _shortEma); - _longEma = (_longAlpha * BarInput.Volume) + ((1 - _longAlpha) * _longEma); - - // Calculate PVO - - double pvo = Math.Abs(_longEma) >= double.Epsilon ? ((_shortEma - _longEma) / _longEma) * 100 : 0; - - IsHot = _index >= WarmupPeriod; - return pvo; - } -} diff --git a/lib/volume/Pvol.cs b/lib/volume/Pvol.cs deleted file mode 100644 index 2d914ce7..00000000 --- a/lib/volume/Pvol.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PVOL: Price-Volume -/// A technical indicator that measures the relationship between price and volume changes, -/// helping to identify the strength of price movements. -/// -/// -/// The PVOL calculation process: -/// 1. Calculate price change: -/// Price Change = (Close - Previous Close) / Previous Close -/// 2. Calculate volume change: -/// Volume Change = (Volume - Previous Volume) / Previous Volume -/// 3. Calculate PVOL: -/// PVOL = Price Change * Volume Change * 100 -/// -/// Key characteristics: -/// - Measures price-volume relationship -/// - Oscillates around zero -/// - Shows momentum strength -/// - Identifies volume-supported moves -/// - No specific boundaries -/// -/// Formula: -/// Price Change = (Close - Previous Close) / Previous Close -/// Volume Change = (Volume - Previous Volume) / Previous Volume -/// PVOL = Price Change * Volume Change * 100 -/// -/// Market Applications: -/// - Price movement confirmation -/// - Volume analysis -/// - Trend strength assessment -/// - Divergence identification -/// - Market momentum analysis -/// -/// Note: High positive values indicate strong upward momentum with volume support, -/// while high negative values indicate strong downward momentum with volume support -/// -[SkipLocalsInit] -public sealed class Pvol : AbstractBase -{ - private double _prevClose; - private double _prevVolume; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvol() - { - WarmupPeriod = 2; // Need previous close and volume - Name = "PVOL"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvol(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevVolume = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous values - if (_index == 1) - { - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - return 0; - } - - // Calculate price and volume changes - double priceChange = (Math.Abs(_prevClose) >= double.Epsilon) ? (BarInput.Close - _prevClose) / _prevClose : 0; - double volumeChange = (Math.Abs(_prevVolume) >= double.Epsilon) ? (BarInput.Volume - _prevVolume) / _prevVolume : 0; - - // Store current values for next calculation - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - - // Calculate PVOL - double pvol = priceChange * volumeChange * 100; - - IsHot = _index >= WarmupPeriod; - return pvol; - } -} diff --git a/lib/volume/Pvr.cs b/lib/volume/Pvr.cs deleted file mode 100644 index c2528d9b..00000000 --- a/lib/volume/Pvr.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PVR: Price Volume Rank -/// A technical indicator that ranks price and volume movements to identify -/// significant market moves based on their combined strength. -/// -/// -/// The PVR calculation process: -/// 1. Calculate price change percentage: -/// Price Change = ((Close - Previous Close) / Previous Close) * 100 -/// 2. Calculate volume ratio: -/// Volume Ratio = Current Volume / Previous Volume -/// 3. Calculate PVR: -/// PVR = Price Change * Volume Ratio -/// -/// Key characteristics: -/// - Combines price and volume analysis -/// - No specific boundaries -/// - Measures movement significance -/// - Volume-weighted price change -/// - Identifies strong moves -/// -/// Formula: -/// Price Change = ((Close - Previous Close) / Previous Close) * 100 -/// Volume Ratio = Volume / Previous Volume -/// PVR = Price Change * Volume Ratio -/// -/// Market Applications: -/// - Significant move identification -/// - Volume-supported moves -/// - Trend strength analysis -/// - Breakout confirmation -/// - Market momentum measurement -/// -/// Note: Higher absolute values indicate more significant price moves with volume support -/// -[SkipLocalsInit] -public sealed class Pvr : AbstractBase -{ - private double _prevClose; - private double _prevVolume; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvr() - { - WarmupPeriod = 2; // Need previous close and volume - Name = "PVR"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvr(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevVolume = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous values - if (_index == 1) - { - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - return 0; - } - - // Calculate price change percentage - double priceChange = (Math.Abs(_prevClose) > double.Epsilon) ? ((BarInput.Close - _prevClose) / _prevClose) * 100 : 0; - - // Calculate volume ratio - double volumeRatio = (Math.Abs(_prevVolume) > double.Epsilon) ? BarInput.Volume / _prevVolume : 1; - - // Store current values for next calculation - _prevClose = BarInput.Close; - _prevVolume = BarInput.Volume; - - // Calculate PVR - double pvr = priceChange * volumeRatio; - - IsHot = _index >= WarmupPeriod; - return pvr; - } -} diff --git a/lib/volume/Pvt.cs b/lib/volume/Pvt.cs deleted file mode 100644 index 765d6151..00000000 --- a/lib/volume/Pvt.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// PVT: Price Volume Trend -/// A momentum indicator that combines price and volume to determine the strength of a trend. -/// Similar to OBV but uses percentage price changes in its calculation. -/// -/// -/// The PVT calculation process: -/// 1. Calculate price change percentage: -/// Price Change = (Close - Previous Close) / Previous Close -/// 2. Calculate PVT: -/// PVT = Previous PVT + (Price Change * Volume) -/// -/// Key characteristics: -/// - Cumulative indicator -/// - Volume-weighted price changes -/// - No upper or lower bounds -/// - Trend strength measure -/// - More sensitive than OBV -/// -/// Formula: -/// Price Change = (Close - Previous Close) / Previous Close -/// PVT = Previous PVT + (Price Change * Volume) -/// -/// Market Applications: -/// - Trend confirmation -/// - Divergence analysis -/// - Volume-price relationships -/// - Support/resistance levels -/// - Market momentum -/// -/// Sources: -/// Norman Fosback - Original development -/// https://www.investopedia.com/terms/p/pvt.asp -/// -/// Note: Rising PVT suggests buying pressure, while falling PVT suggests selling pressure -/// -[SkipLocalsInit] -public sealed class Pvt : AbstractBase -{ - private double _prevClose; - private double _prevPvt; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvt() - { - WarmupPeriod = 2; // Need previous close - Name = "PVT"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Pvt(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevPvt = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate price change percentage - double priceChange = (Math.Abs(_prevClose) > double.Epsilon) ? (BarInput.Close - _prevClose) / _prevClose : 0; - - // Calculate PVT - _prevPvt += priceChange * BarInput.Volume; - - // Store current close for next calculation - _prevClose = BarInput.Close; - - IsHot = _index >= WarmupPeriod; - return _prevPvt; - } -} diff --git a/lib/volume/Tvi.cs b/lib/volume/Tvi.cs deleted file mode 100644 index 9ef29870..00000000 --- a/lib/volume/Tvi.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// TVI: Trade Volume Index -/// A technical indicator that determines whether a security is being accumulated or distributed -/// based on price changes relative to a minimum tick value. -/// -/// -/// The TVI calculation process: -/// 1. Calculate price change: -/// Price Change = Close - Previous Close -/// 2. Compare price change to minimum tick value: -/// If |Price Change| >= Minimum Tick: -/// Add/Subtract volume based on price direction -/// -/// Key characteristics: -/// - Volume-based trend indicator -/// - Uses minimum tick value -/// - Cumulative measure -/// - No upper or lower bounds -/// - Focuses on significant moves -/// -/// Formula: -/// If |Close - Previous Close| >= Minimum Tick: -/// If Close > Previous Close: -/// TVI = Previous TVI + Volume -/// If Close < Previous Close: -/// TVI = Previous TVI - Volume -/// Else: -/// TVI = Previous TVI -/// -/// Market Applications: -/// - Trend identification -/// - Volume analysis -/// - Accumulation/distribution -/// - Price movement significance -/// - Trading signal generation -/// -/// Note: Rising TVI suggests accumulation, while falling TVI suggests distribution -/// -[SkipLocalsInit] -public sealed class Tvi : AbstractBase -{ - private readonly double _minTick; - private double _prevClose; - private double _prevTvi; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tvi(double minTick = 0.5) - { - _minTick = minTick; - WarmupPeriod = 2; // Need previous close - Name = $"TVI({_minTick})"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Tvi(object source, double minTick = 0.5) : this(minTick) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _prevClose = 0; - _prevTvi = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Value; - _index++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Skip first period to establish previous close - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate price change - double priceChange = BarInput.Close - _prevClose; - - // Update TVI if price change exceeds minimum tick - if (Math.Abs(priceChange) >= _minTick) - { - _prevTvi += priceChange > 0 ? BarInput.Volume : -BarInput.Volume; - } - - // Store current close for next calculation - _prevClose = BarInput.Close; - - IsHot = _index >= WarmupPeriod; - return _prevTvi; - } -} diff --git a/lib/volume/Vf.cs b/lib/volume/Vf.cs deleted file mode 100644 index 7e7c7d2a..00000000 --- a/lib/volume/Vf.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VF: Volume Force -/// A volume-based indicator that measures the strength of volume relative to price -/// movement. It helps identify whether volume is supporting or contradicting the -/// current price trend. -/// -/// -/// The VF calculation process: -/// 1. Calculate price change -/// 2. Calculate volume force as volume * price change -/// 3. Optionally smooth the result with EMA -/// -/// Key characteristics: -/// - Volume-weighted measure -/// - Trend strength indicator -/// - No upper/lower bounds -/// - Raw and smoothed versions -/// - Divergence indicator -/// -/// Formula: -/// VF = Volume * (Close - Close[1]) -/// Smoothed VF = EMA(VF, period) -/// -/// Market Applications: -/// - Volume analysis -/// - Trend confirmation -/// - Price/volume divergence -/// - Market participation -/// - Momentum confirmation -/// -/// Note: Higher values indicate stronger volume force -/// -[SkipLocalsInit] -public sealed class Vf : AbstractBase -{ - private readonly Ema _ema; - private double _prevClose; - private double _p_prevClose; - private const int DefaultPeriod = 13; - - /// The smoothing period for EMA calculation (default 13). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vf(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _ema = new(period); - WarmupPeriod = period + 1; - Name = $"VF({period})"; - } - - /// The data source object that publishes updates. - /// The smoothing period for EMA calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vf(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _ema.Init(); - _prevClose = double.NaN; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - _p_prevClose = _prevClose; - } - else - { - _prevClose = _p_prevClose; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - if (_index == 1) - { - _prevClose = BarInput.Close; - return 0; - } - - // Calculate raw volume force - double priceChange = BarInput.Close - _prevClose; - double volumeForce = BarInput.Volume * priceChange; - - // Update previous close - _prevClose = BarInput.Close; - - // Apply EMA smoothing - return _ema.Calc(volumeForce, BarInput.IsNew); - } -} diff --git a/lib/volume/Vp.cs b/lib/volume/Vp.cs deleted file mode 100644 index 4ff3a2e6..00000000 --- a/lib/volume/Vp.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VP: Volume Profile -/// A volume-based indicator that analyzes volume distribution across price levels. -/// It helps identify significant price levels where most trading activity occurs. -/// -/// -/// The VP calculation process: -/// 1. Track volume at each price level within a period -/// 2. Calculate Point of Control (POC) - price with highest volume -/// 3. Calculate Value Area (70% of total volume) -/// -/// Key characteristics: -/// - Price level analysis -/// - Volume distribution -/// - Support/resistance identification -/// - Trading activity concentration -/// - Market structure analysis -/// -/// Formula: -/// VP = Σ Volume at each price level -/// POC = Price level with max volume -/// Value Area = Price range containing 70% of volume -/// -/// Market Applications: -/// - Support/resistance levels -/// - Market structure analysis -/// - Trading activity patterns -/// - Price level significance -/// - Volume concentration -/// -/// Note: Returns Point of Control (price level with highest volume) -/// -[SkipLocalsInit] -public sealed class Vp : AbstractBase -{ - private readonly CircularBuffer _volumes; - private readonly CircularBuffer _prices; - private const int DefaultPeriod = 14; - - /// The number of periods to analyze volume distribution (default 14). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vp(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _volumes = new(period); - _prices = new(period); - WarmupPeriod = period; - Name = $"VP({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods to analyze volume distribution. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vp(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static int FindMaxVolumeIndex(CircularBuffer volumes) - { - int maxIndex = 0; - double maxVolume = volumes[0]; - - for (int i = 1; i < volumes.Count; i++) - { - if (volumes[i] > maxVolume) - { - maxVolume = volumes[i]; - maxIndex = i; - } - } - - return maxIndex; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Store volume and price - _volumes.Add(BarInput.Volume, BarInput.IsNew); - _prices.Add(BarInput.Close, BarInput.IsNew); - - // Find price level with highest volume (Point of Control) - int pocIndex = FindMaxVolumeIndex(_volumes); - return _prices[pocIndex]; - } -} diff --git a/lib/volume/Vwap.cs b/lib/volume/Vwap.cs deleted file mode 100644 index 4193276b..00000000 --- a/lib/volume/Vwap.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VWAP: Volume Weighted Average Price -/// A trading benchmark that shows the ratio of the value traded to total volume -/// traded over a specific period. VWAP equals the dollar value of all trading -/// periods divided by the total trading volume for the current day. -/// -/// -/// The VWAP calculation process: -/// 1. Calculate typical price for each period -/// 2. Multiply typical price by volume -/// 3. Calculate cumulative values -/// 4. Divide cumulative (price * volume) by cumulative volume -/// -/// Key characteristics: -/// - Intraday trading benchmark -/// - Volume-weighted measure -/// - Institutional trading reference -/// - Price momentum indicator -/// - Trading efficiency measure -/// -/// Formula: -/// VWAP = Σ(Price * Volume) / ΣVolume -/// where Price = (High + Low + Close)/3 -/// -/// Market Applications: -/// - Best execution analysis -/// - Trading algorithms -/// - Price momentum -/// - Market impact analysis -/// - Order timing -/// -/// Sources: -/// https://www.investopedia.com/terms/v/vwap.asp -/// -/// Note: Commonly used by institutional traders -/// -[SkipLocalsInit] -public sealed class Vwap : AbstractBase -{ - private double _cumulativeTPV; // Cumulative (Typical Price * Volume) - private double _cumulativeVolume; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vwap() - { - WarmupPeriod = 1; - Name = "VWAP"; - Init(); - } - - /// The data source object that publishes updates. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vwap(object source) : this() - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Init() - { - base.Init(); - _cumulativeTPV = 0; - _cumulativeVolume = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Update cumulative values only for new bars - if (BarInput.IsNew) - { - _cumulativeTPV += BarInput.HLC3 * BarInput.Volume; - _cumulativeVolume += BarInput.Volume; - } - - // Calculate VWAP - return _cumulativeVolume > 0 ? _cumulativeTPV / _cumulativeVolume : BarInput.HLC3; - } -} diff --git a/lib/volume/Vwma.cs b/lib/volume/Vwma.cs deleted file mode 100644 index 714c9abb..00000000 --- a/lib/volume/Vwma.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Runtime.CompilerServices; -namespace QuanTAlib; - -/// -/// VWMA: Volume Weighted Moving Average -/// A technical indicator that combines price and volume to show the average price -/// weighted by volume over a period. It gives more weight to prices with higher -/// volume, making it more responsive to high-volume price movements. -/// -/// -/// The VWMA calculation process: -/// 1. Multiply price by volume for each period -/// 2. Sum (price * volume) over the period -/// 3. Sum volume over the period -/// 4. Divide sums to get weighted average -/// -/// Key characteristics: -/// - Volume-sensitive average -/// - Trend indicator -/// - Support/resistance levels -/// - Price momentum -/// - Volume emphasis -/// -/// Formula: -/// VWMA = Σ(Price * Volume) / ΣVolume -/// where sums are taken over the specified period -/// -/// Market Applications: -/// - Trend identification -/// - Support/resistance levels -/// - Volume analysis -/// - Price momentum -/// - Trading signals -/// -/// Note: More responsive to high-volume price movements -/// -[SkipLocalsInit] -public sealed class Vwma : AbstractBase -{ - private readonly CircularBuffer _priceVolume; - private readonly CircularBuffer _volume; - private const int DefaultPeriod = 20; - - /// The number of periods for VWMA calculation (default 20). - /// Thrown when period is less than 1. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vwma(int period = DefaultPeriod) - { - if (period < 1) - throw new ArgumentOutOfRangeException(nameof(period)); - - _priceVolume = new(period); - _volume = new(period); - WarmupPeriod = period; - Name = $"VWMA({period})"; - } - - /// The data source object that publishes updates. - /// The number of periods for VWMA calculation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vwma(object source, int period = DefaultPeriod) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override void ManageState(bool isNew) - { - if (isNew) - _index++; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - protected override double Calculation() - { - ManageState(BarInput.IsNew); - - // Calculate and store price * volume - double priceVolume = BarInput.Close * BarInput.Volume; - _priceVolume.Add(priceVolume, BarInput.IsNew); - _volume.Add(BarInput.Volume, BarInput.IsNew); - - // Calculate sums - double sumPriceVolume = _priceVolume.Sum(); - double sumVolume = _volume.Sum(); - - // Calculate VWMA - return sumVolume > 0 ? sumPriceVolume / sumVolume : BarInput.Close; - } -} diff --git a/lib/volume/_list.md b/lib/volume/_list.md deleted file mode 100644 index dce6b41d..00000000 --- a/lib/volume/_list.md +++ /dev/null @@ -1,22 +0,0 @@ -# Volume indicators -Done: 19, Todo: 0 - -✔️ ADL - Chaikin Accumulation Distribution Line -✔️ ADOSC - Chaikin Accumulation Distribution Oscillator -✔️ AOBV - Archer On-Balance Volume -✔️ CMF - Chaikin Money Flow -✔️ EOM - Ease of Movement -✔️ KVO - Klinger Volume Oscillator -✔️ MFI - Money Flow Index -✔️ NVI - Negative Volume Index -✔️ OBV - On-Balance Volume -✔️ PVI - Positive Volume Index -✔️ PVOL - Price-Volume -✔️ PVO - Percentage Volume Oscillator -✔️ PVR - Price Volume Rank -✔️ PVT - Price Volume Trend -✔️ TVI - Trade Volume Index -✔️ VF - Volume Force -✔️ VP - Volume Profile -✔️ VWAP - Volume Weighted Average Price -✔️ VWMA - Volume Weighted Moving Average diff --git a/notebooks/Htit.dib b/notebooks/Htit.dib deleted file mode 100644 index 403113e0..00000000 --- a/notebooks/Htit.dib +++ /dev/null @@ -1,198 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\src\obj\Debug\QuanTAlib.dll" - -#r "nuget:Skender.Stock.Indicators" - -using Skender.Stock.Indicators; -using QuanTAlib; - -#!csharp - - public class Htit : AbstractBase - { - private readonly int _period; - private readonly CircularBuffer _pr, _sp, _dt, _pd, _q1, _i1, _q2, _i2, _re, _im, _sd, _it; - - public Htit(int period = 50) : base() - { - _period = period; - _pr = new CircularBuffer(period); - _sp = new CircularBuffer(period); - _dt = new CircularBuffer(period); - _pd = new CircularBuffer(period); - _q1 = new CircularBuffer(period); - _i1 = new CircularBuffer(period); - _q2 = new CircularBuffer(period); - _i2 = new CircularBuffer(period); - _re = new CircularBuffer(period); - _im = new CircularBuffer(period); - _sd = new CircularBuffer(period); - _it = new CircularBuffer(period); - Name = "Htit"; - WarmupPeriod = 12; // Minimum required data points - Init(); - } - - public Htit(object source, int period = 50) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - public override void Init() - { - base.Init(); - _pr.Clear(); - _sp.Clear(); - _dt.Clear(); - _pd.Clear(); - _q1.Clear(); - _i1.Clear(); - _q2.Clear(); - _i2.Clear(); - _re.Clear(); - _im.Clear(); - _sd.Clear(); - _it.Clear(); - } - - protected override void ManageState(bool isNew) - { - if (isNew) - { - _index++; - } - } - - protected override double GetLastValid() - { - return _it[^1]; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - _pr.Add(Input.Value, Input.IsNew); - - if (_index > 6) - { - double adj = (0.075 * _pd[^2]) + 0.54; - - // smooth and detrender - _sp.Add(((4 * _pr[^1]) + (3 * _pr[^2]) + (2 * _pr[^3]) + _pr[^4]) / 10, Input.IsNew); - _dt.Add(((0.0962 * _sp[^1]) + (0.5769 * _sp[^3]) - (0.5769 * _sp[^5]) - (0.0962 * _sp[^7])) * adj, Input.IsNew); - - // in-phase and quadrature - _q1.Add(((0.0962 * _dt[^1]) + (0.5769 * _dt[^3]) - (0.5769 * _dt[^5]) - (0.0962 * _dt[^7])) * adj, Input.IsNew); - _i1.Add(_dt[^4], Input.IsNew); - - // advance the phases by 90 degrees - double jI = ((0.0962 * _i1[^1]) + (0.5769 * _i1[^3]) - (0.5769 * _i1[^5]) - (0.0962 * _i1[^7])) * adj; - double jQ = ((0.0962 * _q1[^1]) + (0.5769 * _q1[^3]) - (0.5769 * _q1[^5]) - (0.0962 * _q1[^7])) * adj; - - // phasor addition for 3-bar averaging - _i2.Add(_i1[^1] - jQ, Input.IsNew); - _q2.Add(_q1[^1] + jI, Input.IsNew); - - _i2[^1] = (0.2 * _i2[^1]) + (0.8 * _i2[^2]); // smoothing it - _q2[^1] = (0.2 * _q2[^1]) + (0.8 * _q2[^2]); - - // homodyne discriminator - _re.Add((_i2[^1] * _i2[^2]) + (_q2[^1] * _q2[^2]), Input.IsNew); - _im.Add((_i2[^1] * _q2[^2]) - (_q2[^1] * _i2[^2]), Input.IsNew); - - _re[^1] = (0.2 * _re[^1]) + (0.8 * _re[^2]); // smoothing it - _im[^1] = (0.2 * _im[^1]) + (0.8 * _im[^2]); - - // calculate period - _pd.Add(_im[^1] != 0 && _re[^1] != 0 - ? 2 * Math.PI / Math.Atan(_im[^1] / _re[^1]) - : 0, Input.IsNew); - - // adjust period to thresholds - _pd[^1] = (_pd[^1] > 1.5 * _pd[^2]) ? 1.5 * _pd[^2] : _pd[^1]; - _pd[^1] = (_pd[^1] < 0.67 * _pd[^2]) ? 0.67 * _pd[^2] : _pd[^1]; - _pd[^1] = (_pd[^1] < 6.0) ? 6.0 : _pd[^1]; - _pd[^1] = (_pd[^1] > 50.0) ? 50.0 : _pd[^1]; - - // smooth the period - _pd[^1] = (0.2 * _pd[^1]) + (0.8 * _pd[^2]); - _sd.Add((0.33 * _pd[^1]) + (0.67 * _sd[^2]), Input.IsNew); - -//check this loop - // smooth dominant cycle period - int dcPeriods = (int)(_sd[^1] + 0.5); - double sumPr = 0; - for (int d = 1; d < dcPeriods+1; d++) //0 -> 5 - { - sumPr += _pr[^d]; - } - _it.Add(dcPeriods > 0 ? sumPr / dcPeriods : _pr[^1], Input.IsNew); - - -Console.WriteLine($"{_index}\t {_it[^1]:F2}"); - - // final indicators - double Trendline, SmoothPrice; - - Trendline = _index >= 12 // 12th bar - ? ((4 * _it[^1]) + (3 * _it[^2]) + (2 * _it[^3]) + _it[^4]) / 10.0 - : _pr[^1]; - SmoothPrice = ((4 * _pr[^1]) + (3 * _pr[^2]) + (2 * _pr[^3]) + _pr[^4]) / 10.0; - - Value = Trendline; - } - - else - { - Value = _pr[^1]; - _pd.Add(0, Input.IsNew); - _sp.Add(0, Input.IsNew); - _dt.Add(0, Input.IsNew); - _i1.Add(0, Input.IsNew); - _q1.Add(0, Input.IsNew); - _i2.Add(0, Input.IsNew); - _q2.Add(0, Input.IsNew); - _re.Add(0, Input.IsNew); - _im.Add(0, Input.IsNew); - _sd.Add(0, Input.IsNew); - _it.Add(_pr[^1], Input.IsNew); - } - - IsHot = _index >= WarmupPeriod; - return Value; - } - } - -#!csharp - -Random rnd = new((int)DateTime.Now.Ticks); -GbmFeed feed = new(sigma: 0.5, mu: 0.0); - -TBarSeries bars = new(feed); -feed.Add(15); - -IEnumerable quotes = feed.Select(q => new Quote { - Date = q.Time, - Open = (decimal)q.Open, - High = (decimal)q.High, - Low = (decimal)q.Low, - Close = (decimal)q.Close, - Volume = (decimal)q.Volume -}); - -Htit ma = new(); -TSeries QL = new(); -foreach (TBar item in feed) { QL.Add(ma.Calc(new TValue(item.Time, item.Close))); } -var SK = quotes.Select(q => (q.Date, (double)q.Close)).GetHtTrendline().Select(i => i.Trendline.Null2NaN()!); - -Console.WriteLine($"Data\tSkend\tQuanTAlib"); -for (int i = 8; i < feed.Length; i++) -{ - Console.WriteLine($"{i}\t{feed[i].Close,6:F2}\t{SK.ElementAt(i),6:F2}\t{QL[i].Value,6:F2} {Math.Truncate(SK.ElementAt(i)*100)==Math.Truncate(QL[i].Value*100)}"); -} diff --git a/notebooks/Skender.dib b/notebooks/Skender.dib deleted file mode 100644 index 52eab105..00000000 --- a/notebooks/Skender.dib +++ /dev/null @@ -1,45 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "nuget:Skender.Stock.Indicators" -#r "..\lib\obj\Debug\QuanTAlib.dll" - -#!csharp - -using Skender.Stock.Indicators; -using QuanTAlib; - -GbmFeed gbm = new(); -Atr atr = new(gbm, 5); -TSeries res = new(atr); -gbm.Add(100); - -IEnumerable quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, - High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume }); -var SkResults = quotes.GetAtr(5).Select(i => i.Atr.Null2NaN()!); -for (int i=0; i< gbm.Length; i++) { - Console.WriteLine($"{gbm.High[i].Value,6:F2} {gbm.Low[i].Value,6:F2} {gbm.Close[i].Value,6:F2}\t\t{res[i].Value,10:F4} {SkResults.ElementAt(i),10:F4}"); -} - -#!csharp - -Random rnd = new((int)DateTime.Now.Ticks); -GbmFeed feed = new(sigma: 0.5, mu: 0.0); -TBarSeries bars = new(feed); -feed.Add(20); -IEnumerable quotes; - -int period = rnd.Next(5) + 2; -Atr ma = new(period: period); -TSeries QL = new(); -foreach (TBar item in bars) { - Console.WriteLine($"{ma.Calc(item)}"); - //QL.Add(ma.Calc(item)); -} - -#!csharp - -bars diff --git a/notebooks/Tulip.dib b/notebooks/Tulip.dib deleted file mode 100644 index 1fe572c1..00000000 --- a/notebooks/Tulip.dib +++ /dev/null @@ -1,28 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "nuget: Tulip.NETCore, 0.8.0.1" - -#!csharp - -using Tulip; - -double[] data = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; -int period = 3; -private double[] outdata = new double[data.Count()]; - -double[][] arrin = new double[][] { data }; -double[][] arrout = new double[][] { outdata }; -Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout); - -for (int i=0; i -{ - private readonly double[] _buffer; - private int _start = 0; - private int _size = 0; - - public int Capacity { get; } - public int Count => _size; - - public CircularBuffer(int capacity) - { - Capacity = capacity; - _buffer = GC.AllocateArray(capacity, pinned: true); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(double item, bool isNew = true) - { - if (_size == 0 || isNew) - { - if (_size < Capacity) - { - _buffer[(_start + _size) % Capacity] = item; - _size++; - } - else - { - _buffer[_start] = item; - _start = (_start + 1) % Capacity; - } - } - else - { - _buffer[(_start + _size - 1) % Capacity] = item; - } - } - - public double this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - index = index < 0 ? 0 : (index >= _size ? _size - 1 : index); - return _buffer[(_start + index) % Capacity]; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - index = index < 0 ? 0 : (index >= _size ? _size - 1 : index); - _buffer[(_start + index) % Capacity] = value; - } - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void ThrowArgumentOutOfRangeException() - { - throw new ArgumentOutOfRangeException("index", "Index is out of range."); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Newest() - { - if (_size == 0) - return 0; - return _buffer[(_start + _size - 1) % Capacity]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Oldest() - { - if (_size == 0) - ThrowInvalidOperationException(); - return _buffer[_start]; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void ThrowInvalidOperationException() - { - throw new InvalidOperationException("Buffer is empty."); - } - - public Enumerator GetEnumerator() => new(this); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public struct Enumerator : IEnumerator - { - private readonly CircularBuffer _buffer; - private int _index; - private double _current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Enumerator(CircularBuffer buffer) - { - _buffer = buffer; - _index = -1; - _current = default; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - if (_index + 1 >= _buffer._size) - return false; - - _index++; - _current = _buffer[_index]; - return true; - } - - public double Current => _current; - object IEnumerator.Current => Current; - - public void Reset() - { - _index = -1; - _current = default; - } - - public void Dispose() { } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(double[] destination, int destinationIndex) - { - if (_size == 0) - return; - - if (_start + _size <= Capacity) - { - Array.Copy(_buffer, _start, destination, destinationIndex, _size); - } - else - { - int firstPartLength = Capacity - _start; - Array.Copy(_buffer, _start, destination, destinationIndex, firstPartLength); - Array.Copy(_buffer, 0, destination, destinationIndex + firstPartLength, _size - firstPartLength); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetSpan() - { - if (_size == 0) - return ReadOnlySpan.Empty; - - if (_start + _size <= Capacity) - { - return new ReadOnlySpan(_buffer, _start, _size); - } - else - { - return new ReadOnlySpan(ToArray()); - } - } - - public double[] InternalBuffer => _buffer; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetInternalSpan() => _buffer.AsSpan(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() - { - Array.Clear(_buffer, 0, _buffer.Length); - _start = 0; - _size = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Max() - { - if (_size == 0) - ThrowInvalidOperationException(); - - return MaxSimd(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Min() - { - if (_size == 0) - ThrowInvalidOperationException(); - - return MinSimd(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Sum() - { - return SumSimd(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double Average() - { - if (_size == 0) - ThrowInvalidOperationException(); - - return SumSimd() / _size; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double MaxSimd() - { - var span = GetSpan(); - var vectorSize = Vector.Count; - var maxVector = new Vector(double.MinValue); - - int i = 0; - for (; i <= span.Length - vectorSize; i += vectorSize) - { - maxVector = Vector.Max(maxVector, new Vector(span.Slice(i, vectorSize))); - } - - double max = double.MinValue; - for (int j = 0; j < vectorSize; j++) - { - max = Math.Max(max, maxVector[j]); - } - - for (; i < span.Length; i++) - { - max = Math.Max(max, span[i]); - } - - return max; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double MinSimd() - { - var span = GetSpan(); - var vectorSize = Vector.Count; - var minVector = new Vector(double.MaxValue); - - int i = 0; - for (; i <= span.Length - vectorSize; i += vectorSize) - { - minVector = Vector.Min(minVector, new Vector(span.Slice(i, vectorSize))); - } - - double min = double.MaxValue; - for (int j = 0; j < vectorSize; j++) - { - min = Math.Min(min, minVector[j]); - } - - for (; i < span.Length; i++) - { - min = Math.Min(min, span[i]); - } - - return min; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private double SumSimd() - { - var span = GetSpan(); - var vectorSize = Vector.Count; - var sumVector = Vector.Zero; - - int i = 0; - for (; i <= span.Length - vectorSize; i += vectorSize) - { - sumVector += new Vector(span.Slice(i, vectorSize)); - } - - double sum = 0; - for (int j = 0; j < vectorSize; j++) - { - sum += sumVector[j]; - } - - for (; i < span.Length; i++) - { - sum += span[i]; - } - - return sum; - } - - public double[] ToArray() - { - double[] array = new double[_size]; - CopyTo(array, 0); - return array; - } - - public void ParallelOperation(Func operation) - { - const int MinimumPartitionSize = 1024; - - if (_size < MinimumPartitionSize) - { - var span = GetSpan(); - var array = span.ToArray(); - operation(array, 0, array.Length); - return; - } - - int partitionCount = Environment.ProcessorCount; - int partitionSize = _size / partitionCount; - - if (partitionSize < MinimumPartitionSize) - { - partitionCount = Math.Max(1, _size / MinimumPartitionSize); - partitionSize = _size / partitionCount; - } - - var buffer = ToArray(); - var results = new double[partitionCount]; - - Parallel.For(0, partitionCount, i => - { - int start = i * partitionSize; - int length = (i == partitionCount - 1) ? _size - start : partitionSize; - results[i] = operation(buffer, start, length); - }); - - } - -} - -#!csharp - -public interface iTValue { - DateTime Time { get; } - double Value { get; } - bool IsNew { get; } - bool IsHot { get; } -} - -public readonly record struct TValue(DateTime Time, double Value, bool IsNew = true, bool IsHot = true) : iTValue { - public DateTime Time { get; init; } = Time; - public double Value { get; init; } = Value; - public bool IsNew { get; init; } = IsNew; - public bool IsHot { get; init; } = IsHot; - public DateTime t => Time; - public double v => Value; - - public TValue() : this(DateTime.UtcNow, 0) { } - public TValue(double value, bool isNew=true, bool isHot=true) : this(DateTime.UtcNow, value, IsNew:isNew, IsHot:isHot) { } - public static implicit operator double(TValue tv) => tv.Value; - public static implicit operator DateTime(TValue tv) => tv.Time; - public static implicit operator TValue(double value) => new TValue(DateTime.UtcNow, value); - - public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}, {Value:F2}, IsNew: {IsNew}, IsHot: {IsHot}]"; -} - -public delegate void ValueSignal(object source, in ValueEventArgs args); - -public class ValueEventArgs : EventArgs { - public TValue Tick { get; } - public ValueEventArgs(TValue value) { Tick = value; } -} - -public class TSeries : List { - private readonly TValue Default = new(DateTime.MinValue, double.NaN); - public IEnumerable t => this.Select(item => item.t); - public IEnumerable v => this.Select(item => item.v); - public TValue Last => Count > 0 ? this[^1] : Default; - public TValue First => Count > 0 ? this[0] : Default; - public int Length => Count; - public string Name { get; set; } - public event ValueSignal Pub = delegate { }; - - public TSeries() { this.Name = "Data"; } - - public TSeries (object source) : this() { - var pubEvent = source.GetType().GetEvent("Pub"); - if (pubEvent != null) { - /* - var nameProperty = source.GetType().GetProperty("Name"); - if (nameProperty != null) { - Name = nameProperty.GetValue(nameProperty)?.ToString()!; - } - */ - pubEvent.AddEventHandler(source, new ValueSignal(Sub)); - } - } - public static explicit operator List(TSeries series) => series.Select(item => item.Value).ToList(); - public static explicit operator double[](TSeries series) => series.Select(item => item.Value).ToArray(); - - public new virtual void Add(TValue tick) { - if (tick.IsNew) { base.Add(tick); } - else { this[^1] = tick; } - Pub?.Invoke(this, new ValueEventArgs(tick)); - } - public virtual void Add(DateTime Time, double Value, bool IsNew=true, bool IsHot=true) => this.Add(new TValue(Time, Value, IsNew, IsHot)); - public virtual void Add(double Value, bool IsNew=true, bool IsHot=true) => this.Add(new TValue(DateTime.UtcNow, Value, IsNew, IsHot)); - - public void Add(IEnumerable values) { - var valueList = values.ToList(); - int count = valueList.Count; - DateTime startTime = DateTime.UtcNow - TimeSpan.FromHours(count); - - for (int i = 0; i < count; i++) { - this.Add(startTime, valueList[i]); - startTime = startTime.AddHours(1); - } - } - public void Add(TSeries series) { - if (series == this) { - // If adding itself, create a copy to avoid modification during enumeration - var copy = new TSeries { Name = this.Name }; - copy.AddRange(this); - AddRange(copy); - } else { - AddRange(series); - } - } - public new virtual void AddRange(IEnumerable collection) { - foreach (var item in collection) { - Add(item); - } - } - public void Sub(object source, in ValueEventArgs args) { Add(args.Tick); } -} - -#!csharp - -TValue a = new(10.0); -TSeries ll = new(); -ll.Add(a); -ll.Add(10); -TSeries ll1 = new(); -ll.Add(new double[]{1, 2, 3, 4}); -ll.Add(new List{1, 2, 3, 4}); -ll.Add(ll); - -display((double[])ll); - -#!csharp - -public interface iTBar { - DateTime Time { get; } - double Open { get; } - double High { get; } - double Low { get; } - double Close { get; } - double Volume { get; } - bool IsNew { get; } -} - -public readonly record struct TBar(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) :iTBar { - public DateTime Time { get; init; } = Time; - public double Open { get; init; } = Open; - public double High { get; init; } = High; - public double Low { get; init; } = Low; - public double Close { get; init; } = Close; - public double Volume { get; init; } = Volume; - public bool IsNew { get; init; } = IsNew; - - public double HL2 => (High + Low) * 0.5; - public double OC2 => (Open + Close) * 0.5; - public double OHL3 => (Open + High + Low) /3; - public double HLC3 => (High + Low + Close) /3; - public double OHLC4 => (Open + High + Low + Close) * 0.25; - public double HLCC4 => (High + Low + Close + Close) * 0.25; - - public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { } - public TBar(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : this(DateTime.UtcNow, Open, High, Low, Close, Volume, IsNew) { } - - // when TBar casts to double, it returns its Close - public static implicit operator double(TBar bar) => bar.Close; - public static implicit operator DateTime(TBar tv) => tv.Time; - - // castings for sloppy people - a single double injected into a TBar, and a single TValue injected into a TBar - public TBar (double value) : this(Time: DateTime.UtcNow, Open: value, High: value, Low: value, Close: value, Volume: value, IsNew: true) {} - public TBar (TValue value) : this(Time: value.Time, Open: value.Value, High: value.Value, Low: value.Value, Close: value.Value, Volume: value.Value, IsNew: value.IsNew) {} - - public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]"; -} - -public delegate void BarSignal(object source, in TBarEventArgs args); - -public class TBarEventArgs : EventArgs { - public TBar Bar { get; } - public TBarEventArgs(TBar bar) { Bar = bar; } -} - -public class TBarSeries : List { - private readonly TBar Default = new(DateTime.MinValue, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN); - - public TSeries Open; - public TSeries High; - public TSeries Low; - public TSeries Close; - public TSeries Volume; - - - public TBar Last => Count > 0 ? this[^1] : Default; - public TBar First => Count > 0 ? this[0] : Default; - public int Length => Count; - public string Name { get; set; } - public event BarSignal Pub = delegate { }; - - public TBarSeries() { - this.Name = "Bar"; - Open = new(); - High = new(); - Low = new(); - Close = new(); - Volume = new(); - } - public TBarSeries (object source) : this() { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new BarSignal(Sub)); - } - - public new virtual void Add(TBar bar) { - if (bar.IsNew) { base.Add(bar); }else { this[^1] = bar; } - Pub?.Invoke(this, new TBarEventArgs(bar)); - - Open.Add(bar.Time, bar.Open, IsNew: bar.IsNew, IsHot: true); - High.Add(bar.Time, bar.High, IsNew: bar.IsNew, IsHot: true); - Low.Add(bar.Time, bar.Low, IsNew: bar.IsNew, IsHot: true); - Close.Add(bar.Time, bar.Close, IsNew: bar.IsNew, IsHot: true); - Volume.Add(bar.Time, bar.Volume, IsNew: bar.IsNew, IsHot: true); - } - public void Add(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) => - this.Add(new TBar(Time, Open, High, Low, Close, Volume, IsNew)); - - public void Add(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) => - this.Add(new TBar(DateTime.Now, Open, High, Low, Close, Volume, IsNew)); - - public void Add(TBarSeries series) { - if (series == this) { - // If adding itself, create a copy to avoid modification during enumeration - var copy = new TBarSeries { Name = this.Name }; - copy.AddRange(this); - AddRange(copy); - } else { - AddRange(series); - } - } - public new virtual void AddRange(IEnumerable collection) { - foreach (var item in collection) { - Add(item); - } - } - - public void Sub(object source, in TBarEventArgs args) { - Add(args.Bar); - } -} - -#!csharp - -TBarSeries ll = new(); -ll.Add(1,2,3,4,5); -ll.Add(1,2,3,4,5); -ll.Add(1,2,3,4,5); -ll.Add(ll); -//ll.Add(a); -//ll.Add(10); -//TSeries ll1 = new(); -//ll.Add(new double[]{1, 2, 3, 4}); -//ll.Add(new List{1, 2, 3, 4}); -//ll.Add(ll); - -display(ll.Open.Last.Value); - -#!csharp - -using System; -using System.Collections.Generic; -using System.CommandLine.Invocation; - -public abstract class AbstractBase : iTValue -{ - public DateTime Time { get; set; } - public double Value { get; set; } - public bool IsNew { get; set; } - public bool IsHot { get; set; } - - public TValue Input { get; set; } - - public TValue Tick => new(Time, Value, IsNew, IsHot); // Stores the current value of indicator - public event ValueSignal Pub = delegate { }; // Publisher of generated values - - protected int _index; //tracking the position of output - protected double _lastValidValue; - // other _internal vars defined here - - protected AbstractBase() - { //add parameters into constructor - } - - public void Sub(object source, in ValueEventArgs args) => Calc(args.Tick); - - public virtual void Init() - { - _index = 0; - _lastValidValue = 0; - } - - public virtual TValue Calc(TValue input) - { - Input = input; - if (double.IsNaN(input.Value) || double.IsInfinity(input.Value)) - { - return Process(new TValue(input.Time, GetLastValid(), input.IsNew, input.IsHot)); - } - this.Value = Calculation(); - return Process(new TValue(Time: Input.Time, Value: this.Value, IsNew: Input.IsNew, IsHot: this.IsHot)); - } - - protected virtual double GetLastValid() - { - // should return last valid value - return _lastValidValue; - } - protected abstract void ManageState(bool isNew); - protected abstract double Calculation(); - protected virtual TValue Process(TValue value) - { - this.Time = value.Time; - this.Value = value.Value; - this.IsNew = value.IsNew; - this.IsHot = value.IsHot; - Pub?.Invoke(this, new ValueEventArgs(value)); - return value; - } -} - -#!csharp - -using System; - - public class EmaCalc : AbstractBase - { - private readonly int _period; - private CircularBuffer _sma; - private double _lastEma, _p_lastEma; - private double _k, _e, _p_e; - private bool _isInitialized, _useSma; - - public EmaCalc(int period, bool useSma = true) : base() - { - if (period < 1) { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); - } - _period = period; - _useSma = useSma; - _sma = new(period); - - Init(); - } - - public EmaCalc(object source, int period, bool useSma = true) : this(period, useSma) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - public override void Init() - { - base.Init(); - _k = 2.0 / (_period + 1); - _e = 1.0; - _lastEma = 0; - _isInitialized = false; - _sma = new(_period); - } - - protected override void ManageState(bool isNew) { - if (isNew) { - _p_lastEma = _lastEma; - _p_e = _e; - _index++; - } else { - _lastEma = _p_lastEma; - _e = _p_e; - } - } - - protected override double GetLastValid() { - return _lastEma; - } - - protected override double Calculation() { - double result, _ema; - ManageState(Input.IsNew); - - // when _UseSma == true, use SMA calculation until we have enough data points - if (!_isInitialized && _useSma) { - _sma.Add(Input.Value, Input.IsNew); - _ema = _sma.Average(); - result = _ema; - if (_index >= _period) { - _isInitialized = true; - } - } else { - // dunamic k when within period; (index is zero-based, therefore +2) - double _dk = (_index +1 >= _period) ? _k : 2.0 / (_index + 2); - - // compensator for early ema values - _e = (_e > 1e-10) ? (1 - _dk) * _e : 0; - - _ema = _dk * (Input.Value - _lastEma) + _lastEma; - - // _useSma decides if we use compensator or not - result = (_useSma || _e == 0)? _ema : _ema / (1 - _e); - } - - _lastEma = _ema; - IsHot = _index >= _period; - return result; - } - } - -#!csharp - -double[] input = new[]{1.0, 2,3,4,5}; - -TSeries mm = new(); -mm.Add(input); -mm.Display(); - -#!csharp - -public class Convolution : AbstractBase - { - private readonly double[] _kernel; - private readonly int _kernelSize; - private CircularBuffer _buffer; - private double[] _normalizedKernel; - - public Convolution(double[] kernel) - { - if (kernel == null || kernel.Length == 0) - { - throw new ArgumentException("Kernel must not be null or empty.", nameof(kernel)); - } - _kernel = kernel; - _kernelSize = kernel.Length; - _buffer = new CircularBuffer(_kernelSize); - _normalizedKernel = new double[_kernelSize]; - Init(); - } - - public Convolution(object source, double[] kernel) : this(kernel) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - private void Init() - { - _index = 0; - _lastValidValue = 0; - Array.Copy(_kernel, _normalizedKernel, _kernelSize); - } - - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double GetLastValid() - { - return _lastValidValue; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - _buffer.Add(Input.Value, Input.IsNew); - - // Normalize kernel on each calculation until buffer is full - if (_index <= _kernelSize) - { - NormalizeKernel(); - } - - double result = ConvolveBuffer(); - IsHot = _index >= _kernelSize; - - return result; - } - - private void NormalizeKernel() - { - int activeLength = Math.Min(_index, _kernelSize); - double sum = 0; - - // Calculate the sum of the active kernel elements - for (int i = 0; i < activeLength; i++) - { - sum += _kernel[i]; - } - - // Normalize the kernel or set equal weights if the sum is zero - double normalizationFactor = (sum != 0) ? sum : activeLength; - for (int i = 0; i < activeLength; i++) - { - _normalizedKernel[i] = _kernel[i] / normalizationFactor; - } - - // Set the rest of the normalized kernel to zero - Array.Clear(_normalizedKernel, activeLength, _kernelSize - activeLength); - } - - private double ConvolveBuffer() - { - double sum = 0; - var bufferSpan = _buffer.GetSpan(); - int activeLength = Math.Min(_index, _kernelSize); - - for (int i = 0; i < activeLength; i++) - { - sum += bufferSpan[activeLength - 1 - i] * _normalizedKernel[i]; - } - - return sum; - } - } - -#!csharp - -public class Wma : AbstractBase - { - private readonly int _period; - private readonly Convolution _convolution; - - public Wma(int period) - { - if (period < 1) - { - throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period)); - } - _period = period; - _convolution = new Convolution(GenerateWmaKernel(_period)); - Init(); - } - - public Wma(object source, int period) : this(period) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - private static double[] GenerateWmaKernel(int period) - { - double[] kernel = new double[period]; - double weightSum = period * (period + 1) / 2.0; - - for (int i = 0; i < period; i++) - { - kernel[i] = (period - i) / weightSum; - } - - return kernel; - } - - private new void Init() - { - base.Init(); - _convolution.Init(); - } - - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - } - } - - protected override double GetLastValid() - { - return _lastValidValue; - } - - protected override double Calculation() - { - ManageState(Input.IsNew); - - // Use Convolution for calculation - TValue convolutionResult = _convolution.Calc(Input); - - double result = convolutionResult.Value; - IsHot = _index >= _period; - - return result; - } - } - -#!csharp - -TSeries input = new(); -double[] kernel = new[]{4.0,3,2,1}; - -Wma cc = new(input, 5); -TSeries output = new(cc); - -input.Add(new double[]{1.0,2,3,4,5,6,7,8}); - - -display((double[])output); diff --git a/notebooks/charting.dib b/notebooks/charting.dib deleted file mode 100644 index 6aaaed19..00000000 --- a/notebooks/charting.dib +++ /dev/null @@ -1,82 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "../lib/obj/Debug/QuanTAlib.dll" -using QuanTAlib; -QuanTAlib.Formatters.Initialize(); - -#!csharp - -TSeries Spike = new() { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -TSeries Impulse = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }; -TSeries Triangle = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 }; -TSeries Sawtooth = new() { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -TSeries Sine = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 }; -TSeries Chirp = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 }; -TSeries White = new() { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09}; -TSeries Gauss = new() { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61}; -TSeries B = new() { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06}; -TSeries HF = new() { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86}; -TSeries ImpulseHF = new() { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71}; -TSeries SawtoothHF = new() { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3}; -TSeries SineG = new() { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35}; -TSeries ChirpG = new() { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58}; -TSeries Complex = new() { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83}; -TSeries Market = new() { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25}; - -#!csharp - -#r "nuget: ScottPlot" - -using ScottPlot; -using Microsoft.DotNet.Interactive.Formatting; -Formatter.Register(typeof(ScottPlot.Plot), (p, w) => - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -TSeries ma1 = Spike; -TSeries out1 = new(); -Jma calc1 = new(period: 7, phase: 0, factor: 0.30, buffer: 2); -foreach (var value in ma1) { out1.Add(calc1.Calc(value)); } -double[] gma1 = ma1.v.ToArray()[52..]; -double[] gsig1 = out1.v.ToArray()[52..]; - -TSeries ma2 = Impulse; -TSeries out2 = new(); -Jma calc2 = new(period: 7, phase: 0, factor: 0.20, buffer: 2); -foreach (var value in ma2) { out2.Add(calc2.Calc(value)); } -double[] gma2 = ma2.v.ToArray()[52..]; -double[] gsig2 = out2.v.ToArray()[52..]; - -#!csharp - -Plot plt1 = new(); -var p1a = plt1.Add.Signal(gma1); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; -var p1b = plt1.Add.Signal(gsig1); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 3; -plt1.Title("Spike - JMA(10)"); - -Plot plt2 = new(); -var p2a = plt2.Add.Signal(gma2); p2a.Color = ScottPlot.Colors.Red; p2a.LineWidth = 2; -var p2b = plt2.Add.Signal(gsig2); p2b.Color = ScottPlot.Colors.Blue; p2b.LineWidth = 3; -plt2.Title("Impulse - JMA(10)"); - -plt1.Display(); -plt2.Display(); - -#!csharp - -#r "nuget: Plotly.net.Interactive" -#r "nuget: Plotly.NET.CSharp" - -using Plotly.NET.Interactive; -using Plotly.NET.CSharp; - -#!csharp - -var ch1 = Chart.Line( x: Enumerable.Range(0,gsig.Count()), y: gsig, Name: "signal"); -var ch2 = Chart.Line( x: Enumerable.Range(0,gma.Count()), y: gma); -Chart.Combine(new[] {ch1,ch2}).Display(); diff --git a/notebooks/core.dib b/notebooks/core.dib deleted file mode 100644 index 1fa02006..00000000 --- a/notebooks/core.dib +++ /dev/null @@ -1,68 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\lib\obj\Debug\QuanTAlib.dll" - -#r "nuget:Skender.Stock.Indicators" -using Skender.Stock.Indicators; -using QuanTAlib; -QuanTAlib.Formatters.Initialize(); - -#!csharp - -Atr ma = new(10); -GbmFeed gbm = new(); -gbm.Add(30); -IEnumerable quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume }); -var SkResults = quotes.GetAtr(10).Select(i => i.Atr.Null2NaN()!); -for (int i=0; i< gbm.Length; i++) { - ma.Calc(gbm[i]); - Console.WriteLine($"{i,3} {ma.Value,10:F3} \t {SkResults.ElementAt(i):F3}"); -} - -#!csharp - -Atr ma = new(10); -GbmFeed gbm = new(); -gbm.Add(30); -IEnumerable quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume }); -var SkResults = quotes.GetTr().Select(i => i.Tr.Null2NaN()!); -for (int i=0; i< gbm.Length; i++) { - ma.Calc(new TBar(gbm[i])); - - Console.WriteLine($"{gbm.High[i].Value,6:F4} \t{gbm.Low[i].Value,6:F4} \t{gbm.Close[i].Value,6:F4} \t{ma.Tr,10:F4} \t{SkResults.ElementAt(i),10:F4}"); -} - -#!csharp - -//ATR test -GbmFeed gbm = new(); -TBarSeries feed = new(gbm); - -Atr ma1 = new(gbm, 10); -TSeries res1 = new(ma1); -gbm.Add(30); -IEnumerable quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume }); -var SkResults = quotes.GetAtr(10).Select(i => i.Atr.Null2NaN()!); -for (int i=0; i< gbm.Length; i++) { - double delta = Math.Round(res1[i].Value, 10) - Math.Round(SkResults.ElementAt(i), 10); - //Console.WriteLine($"{i,3} {gbm.High[i].Value,6:F2} {gbm.Low[i].Value,6:F2} {gbm.Close[i].Value,6:F2} {res1[i].Value,10:F4} {SkResults.ElementAt(i),10:F4}\t{delta}"); - Console.WriteLine($"{i,3} h:{gbm.High[i].Value,6:F2} l:{gbm.Low[i].Value,6:F2} c:{gbm.Close[i].Value,6:F2} {res1[i].Atr,10:F4} {SkResults.ElementAt(i),10:F4}\t{delta}"); -} - -#!csharp - -//EMA test -GbmFeed gbm = new(); -Ema ema1 = new(gbm.Close, 10, useSma: true); -TSeries res1 = new(ema1); -gbm.Add(30); -IEnumerable quotes = gbm.Close.Select(item => new Quote { Date = item.Time, Close = (decimal)item.Value }); -var SkResults = quotes.GetEma(10).Select(i => i.Ema.Null2NaN()!); -for (int i=0; i< gbm.Length; i++) { - double delta = Math.Round(res1[i].Value, 10) - Math.Round(SkResults.ElementAt(i), 10); - Console.WriteLine($"{i,3} {gbm.Close[i].Value,6:F2} {res1[i].Value,10:F4} {SkResults.ElementAt(i),10:F4}\t{delta}"); -} diff --git a/notebooks/ema.dib b/notebooks/ema.dib deleted file mode 100644 index b1b0d5c7..00000000 --- a/notebooks/ema.dib +++ /dev/null @@ -1,63 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "../lib/obj/Debug/QuanTAlib.dll" -using QuanTAlib; -QuanTAlib.Formatters.Initialize(); - -#!csharp - -public class Ema { - double lastema; - double k, extra; - int i, p; - public Ema(int p) { - k = 1/((double) p+1); - extra = 1; - lastema = 0; - } - public double Calc(double value) { - extra = (1 - k) * extra; - double ema = k * (value - lastema) + lastema; - lastema = ema; - return ema / (1 - extra); - } -} - -#!csharp - -public class Ema { - private double smooth, k; - private double extra; - private int i, p; - - public Ema(int period) { - p = period; - k = 1.0 / (p + 1); - extra = 1; - smooth = 0; - i = 0; - } - - public double Calc(double value) { - i++; - k = 1/((double)Math.Min(p,i)+1); - - extra *= (1-k); - smooth = k * (value - smooth) + smooth; - return extra < 1e-10 ? smooth : smooth / (1 - extra); - - } -} - -#!csharp - -Ema ma = new(3); -double[] input = new[]{1.0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0}; -for (int i=0; i - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - - static double[] CalculateEmaWeights(int period, int barCount) - { - double[] weights = new double[barCount]; - double alpha = 2.0 / (period + 1); - double weightSum = 0; - for (int i = 0; i < barCount; i++) - { - weights[i] = Math.Pow(1 - alpha, i) * alpha; - weightSum += weights[i]; - } - for (int i = 0; i < barCount; i++) - { - weights[i] /= weightSum; - } - return weights; - } - -#!csharp - -Plot plt = new(); -double[] weights = CalculateEmaWeights(10, 30); -var bar = plt.Add.Bars(weights); -plt.Add.Annotation("EMA(10) Weights Chart", Alignment.UpperRight); -var vline = plt.Add.VerticalLine(10.5, width: 1, ScottPlot.Color.FromColor(System.Drawing.Color.Black)); -plt.Display(); - -#!csharp - -#r "../lib/obj/Debug/QuanTAlib.dll" -using QuanTAlib; -QuanTAlib.Formatters.Initialize(); - -#!csharp - -TSeries Spike = new() { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -TSeries SpikeJMA = new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.000552258,-0.000634509,-0.000546757,-0.000418793,-0.000300729,-0.000207311,-0.000138943,-9.12206E-05,-5.89537E-05,-3.76301E-05,-2.3779E-05,-1.49021E-05,-9.27419E-06,-5.73755E-06,-3.53147E-06,-2.16396E-06,-1.32082E-06,-8.03405E-07,-4.87171E-07,-2.94594E-07,-1.77697E-07,-1.06942E-07,-6.42273E-08,-3.85007E-08,-2.3039E-08,-1.37646E-08,-8.21143E-09,-4.89192E-09,-2.91062E-09,-1.72971E-09,-1.02679E-09,-6.08884E-10,0.57216502,0.329278183,0.111882943,0.02038988,-0.00579442,-0.009287974,-0.007184303,-0.004666439,-0.002864099,-0.001904733,-0.001310906,-0.000931811,-0.000671491,-0.000485478,-0.000348532,-0.000247325,-0.00017322,-0.000119743,-8.17596E-05,-5.51943E-05,-3.68781E-05,-2.44116E-05,-1.60241E-05,-1.04391E-05,-6.75421E-06,-4.34304E-06,-2.77694E-06,-1.76649E-06,-1.11846E-06,-7.05115E-07,-4.42777E-07,-2.77032E-07,-1.72747E-07}; -TSeries Impulse = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }; -TSeries ImpulseJMA = new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.000552258,-0.000634509,-0.000546757,-0.000418793,-0.000300729,-0.000207311,-0.000138943,-9.12206E-05,-5.89537E-05,-3.76301E-05,-2.3779E-05,-1.49021E-05,-9.27419E-06,-5.73755E-06,-3.53147E-06,-2.16396E-06,-1.32082E-06,-8.03405E-07,-4.87171E-07,-2.94594E-07,-1.77697E-07,-1.06942E-07,-6.42273E-08,-3.85007E-08,-2.3039E-08,-1.37646E-08,-8.21143E-09,-4.89192E-09,-2.91062E-09,-1.72971E-09,-1.02679E-09,-6.08884E-10,0.57216502,0.901443203,1.013326146,1.033716025,1.027921605,1.018633631,1.011449329,1.00678289,1.004181353,1.002789251,1.001927584,1.001373173,1.000992004,1.000715566,1.000511417,1.000361007,1.000251496,1.000172974,1.000117554,1.000079021,1.000052594,1.000034694,1.000022702,1.000014747,1.000009517,1.000006105,1.000003895,1.000002473,1.000001563,1.000000984,1.000000617,1.000000385,1.00000024 }; -TSeries Triangle = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 }; -TSeries TriangleJMA = new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1.581506365,2.477581913,3.488202137,4.521009922,5.548667586,6.567230027,7.578661013,8.58543932,9.589389814,10.59167402,11.59299,12.59374694,13.59418202,14.59443201,15.59457564,16.59465816,17.59470556,18.59473279,19.59474843,20.58051252,21.54811378,22.51426859,23.48461289,24.45940996,25.43756768,26.41800953,27.39996296,28.38293081,29.36660689,30.35080461,31.33541428,32.32037808,33.30566888,33.60143774,33.44671824,32.76693797,31.6743202,30.43080342,29.17128703,27.99351702,26.87387633,25.82071013,24.78859626,23.78848957,22.78804437,21.80499239,20.81281231,19.83220792,18.84031318,17.85875467,16.86608953,15.88343316,14.89022444,13.90693661,12.913562,11.92991131,10.93653629,9.952765982,8.959539985,7.975860495,6.982898571,5.999241471,5.006469162,4.022728123,3.03008006 }; -TSeries Sawtooth = new() { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -TSeries SawtoothJMA = new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1.581506365,2.477581913,3.488202137,4.521009922,5.548667586,6.567230027,7.578661013,8.58543932,9.589389814,10.59167402,11.59299,12.59374694,13.59418202,14.59443201,15.59457564,16.59465816,17.59470556,18.59473279,19.59474843,20.58051252,21.54811378,22.51426859,23.48461289,24.45940996,25.43756768,26.41800953,27.39996296,28.38293081,29.36660689,30.35080461,31.33541428,32.32037808,33.30566888,33.60143774,14.4444661,3.393709459,-0.381095509,-1.087259716,-0.909541115,-0.630797534,-0.431229171,-0.301811285,-0.214698512,-0.155744776,-0.113122186,-0.081470163,-0.057940086,-0.040643203,-0.028127973,-0.019222458,-0.012985805,-0.008681539,-0.005749677,-0.003775885,-0.002460865,-0.001592844,-0.001024611,-0.000655382,-0.00041706,-0.000264159,-0.000166597,-0.000104653,-6.55023E-05,-4.08602E-05,-2.54092E-05}; -TSeries Sine = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 }; -TSeries SineJMA = new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.39,0.490864998,0.636321842,0.775644322,0.887670382,0.96723697,1.002698087,0.994210739,0.97484737,0.899842304,0.760161465,0.598500604,0.417065675,0.226525923,0.028051774,-0.173435555,-0.363836139,-0.541493028,-0.701687888,-0.830525691,-0.924540364,-0.976284568,-1.000434282,-1.002692279,-0.985640624,-0.936128884,-0.822093878,-0.639429302,-0.423527364,-0.195049986,0.026649267,0.230378819,0.416212213,0.587236179,0.726645879,0.840145143,0.922346148,0.974370173,0.998644546,1.001578941,0.980088368,0.929810972,0.819518184,0.64081841,0.420019212,0.180501608,-0.042184191,-0.258138204,-0.444721632,-0.611894672,-0.75049231,-0.857197199,-0.932680738,-0.97935623,-1.000589656,-0.999280528,-0.971643229,-0.914409033,-0.805305412,-0.628446355,-0.408677504,-0.1685546,0.064709114,0.282360193,0.471727962,0.635976367 }; -TSeries Chirp = new() {0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 }; -TSeries ChirpJMA = new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.93,0.561053238,-0.153321154,-0.747445764,-0.827042762,-0.356534975,0.329365258,0.808933304,0.80763454,0.359594859,-0.283946188,-0.780875466,-0.902685225,-0.697018971,-0.08283369,0.516589836,0.888855938,0.948751948,0.779079352,0.219827259,-0.413194221,-0.823676712,-0.966424648,-0.980133795,-0.734382753,-0.187559001,0.381690406,0.771852221,0.950406869,0.992587561,0.906965755,0.568135762,0.057898772,-0.428978529,-0.765170274,-0.939400473,-0.997544642,-0.960715401,-0.780475234,-0.40457484,0.048409781,0.4620447,0.75237274,0.922499475,0.99544436,0.990182899,0.907531892,0.699745667,0.36999061,-0.018042543,-0.374980934,-0.659514743,-0.851442288,-0.960664115,-1.004200191,-0.986072069,-0.905943806,-0.759349136,-0.521563135,-0.211047868,0.115261471,0.410601038,0.645846908,0.817157712,0.92809772,0.989536632 }; -TSeries White = new() { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09}; -TSeries WhiteJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.03,0.000615565,-0.061226573,-0.092671199,-0.129255272,-0.162995702,-0.151470277,-0.092881104,-0.022100823,0.041629282,0.034531011,-0.00690482,-0.057127156,-0.070531037,-0.052561514,-0.063900933,-0.081162364,-0.053975569,-0.003614763,0.007307236,-0.000322726,-0.024840458,-0.018839953,-0.005344501,-0.031085715,-0.032009583,-0.063752546,-0.078008451,-0.076403205,-0.0929075,-0.088024391,-0.087878012,-0.07544228,-0.041364649,-0.00440562,0.005778424,-0.002553758,-0.001239273,0.028362304,0.012498302,-0.007029157,-0.043178553,-0.020123975,-0.061044025,-0.088517916,-0.099905576,-0.102094773,-0.106909564,-0.093572608,-0.097302028,-0.110538244,-0.086147961,-0.087969842,-0.07229411,-0.074396177,-0.054072297,-0.040179437,-0.034162407,-0.050151585,-0.033698183,-0.0108771,-0.011076622,-0.020007675,-0.048169729,-0.073949068,-0.091959026}; -TSeries Gauss = new() { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61}; -TSeries GaussJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001854025,0.011540727,0.011884188,-0.022070199,-0.057369472,-0.051431987,-0.036997357,-0.025664992,-0.032226648,-0.06037637,-0.061423963,-0.036892161,0.008572487,0.058119604,0.108100023,0.133835735,0.129098894,0.093270858,0.04601512,-0.021358793,-0.0867853,-0.129632777,-0.15961389,-0.142828375,-0.123790362,-0.144340705,-0.119583475,-0.02732417,0.022509545,0.093793303,-0.099826639,-0.216160255,-0.274653675,-0.288848025,-0.280078428,-0.227015768,-0.063702909,0.064855103,0.171342223,0.240000551,-0.247868893,-0.178073225,-0.05581201,0.021314181,0.088914096,0.152366403,0.202793617,0.210356779,0.204598892,0.135245478,0.147739125,0.092238129,0.061372665,0.024723623,0.013480088,0.038466805,0.069932732,0.063288258,-0.019191085,-0.097103187,-0.063479437,-0.041277564,0.101208843,0.226564254,0.3324448}; -TSeries B = new() { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06}; -TSeries BJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.28,-0.249647418,-0.236137311,-0.092463769,-0.135681216,0.081810351,-0.10737838,0.158877264,-0.121022022,0.157409626,-0.110712469,0.113649408,-0.075459625,0.058705622,-0.03146432,0.018768059,-0.005724484,0.002866003,-0.005347622,-0.002037477,0.001061143,-0.004823112,0.007612129,-0.008318097,0.01176324,-0.023491307,0.038452069,-0.053167834,0.069454301,-0.083773765,0.088390998,-0.093198114,0.083064505,-0.076311968,0.060105968,-0.040755859,0.02672713,-0.017252438,0.003870028,-0.006498957,0.003238924,0.000547304,-0.00071129,0.005308638,-0.005960141,0.008773952,-0.011210224,0.015074455,-0.034416451,0.046128851,-0.058583481,0.078264889,-0.078887801,0.091633873,-0.079308124,0.078776195,-0.057654673,0.048302298,-0.026718666,0.01992987,-0.004897167,0.00466543,-0.006232267,-0.002021568,-0.001167666,-0.00561375}; -TSeries HF = new() { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86}; -TSeries HFJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.009659222,-0.040599553,-0.163792103,-0.267881527,-0.222132422,-0.006792776,0.1652809,0.189468517,-0.003756276,-0.171611112,-0.219673237,-0.03300223,0.141560684,0.221586098,0.063591357,-0.110778668,-0.209827889,-0.090081173,0.08575362,0.199874895,0.119603923,-0.05541179,-0.183498905,-0.142326793,0.03293993,0.17327896,0.162956455,-0.017391711,-0.169867254,-0.189994223,-0.010065626,0.152957221,0.205341138,0.038713249,-0.126568002,-0.205841173,-0.06402948,0.098789546,0.193539028,0.08428847,-0.078530746,-0.186526214,-0.113784853,0.048749086,0.170952283,0.135372811,-0.025218031,-0.158841788,-0.15234029,0.014510823,0.161290048,0.183155809,0.014187729,-0.143632601,-0.196231797,-0.04068555,0.119889198,0.19852797,0.06310687,-0.094480351,-0.18637946,-0.082123757,0.075749245,0.181223306,0.110597239}; -TSeries ImpulseHF = new() { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71}; -TSeries ImpulseHFJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.003461081,-0.011642869,-0.048606972,-0.081865532,-0.066699028,0.004769395,0.061214257,0.066684176,-0.000581688,-0.05790682,-0.073898443,-0.009849831,0.049232603,0.075125066,0.019740445,-0.040036202,-0.073433985,-0.032178662,0.028208365,0.067331942,0.040941342,-0.017234625,-0.059553851,-0.045931589,0.013039637,0.059810689,0.055076438,-0.007043616,-0.058392452,-0.064847235,-0.004085511,0.050829451,0.366220782,0.54546044,0.661280091,0.828257429,1.047815691,1.178437926,1.232617161,1.175409162,1.094265475,1.032680473,1.028996048,1.060829073,1.086121863,1.064452157,1.00462356,0.955209515,0.952483181,1.004256436,1.051127644,1.05790993,1.004105353,0.953026934,0.936162097,0.986603514,1.039284876,1.065119067,1.021791115,0.96988946,0.9395387,0.974261146,1.026993387,1.062164997,1.037299819}; -TSeries SawtoothHF = new() { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3}; -TSeries SawtoothHFJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.162339653,0.601887587,-0.138147159,1.309223994,5.107713418,8.974394558,10.40295885,9.064227513,7.107532593,7.252214128,10.29253719,14.3422971,16.59550868,15.89741763,13.81397238,12.94610444,15.38646358,19.54492633,22.58742652,23.29047041,21.14259379,19.88472662,20.67288266,24.48774716,28.15328646,29.31043033,28.30880272,26.87074867,26.39868719,29.62694489,33.64590149,35.40176299,35.40262728,32.44992039,16.31419263,6.006475565,2.921574936,2.223213675,0.363348158,-2.56004758,-4.212503588,-4.511484408,-2.01012721,0.279699545,1.556338949,0.733997068,-0.907882416,-1.868190362,-1.078138134,0.727883722,1.831670906,1.372206184,-0.576868493,-1.796676323,-1.608469841,0.271762471,1.547428697,1.743028127,-0.036241215,-1.385714085,-1.83810226,-0.352149236,1.087926207,1.814346637,0.651940618}; -TSeries SineG = new() { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35}; -TSeries SineGJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.135063871,0.399412629,0.568872884,0.655439988,0.727204599,0.985254566,1.112235515,1.150214911,1.056603797,0.850932718,0.730112974,0.654269037,0.593070789,0.475249449,0.324220683,-0.021881615,-0.391582296,-0.739173509,-0.929605151,-1.151983599,-1.258910502,-1.30184982,-1.308701469,-1.196229363,-1.106382636,-1.053626396,-0.828404263,-0.426205314,-0.204837262,0.164514163,0.092688593,0.072220649,0.140038433,0.294703177,0.445530475,0.711949941,1.09235409,1.287255822,1.387026593,1.415102546,0.594414816,0.516509742,0.518120551,0.503063413,0.473652641,0.42622561,0.326965192,-0.029781089,-0.268764145,-0.778292891,-0.896555805,-1.023481762,-1.077021387,-1.109129526,-1.097761437,-1.012370223,-0.917088527,-0.848344828,-0.814846374,-0.770797888,-0.329923163,-0.06907177,0.531362662,0.905121738,1.154870446}; -TSeries ChirpG = new() { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58}; -TSeries ChirpGJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.3,0.740001439,-0.042556461,-0.769542976,-1.105423545,-0.563312376,0.451052389,0.881976808,0.812897183,0.233094721,-0.529073435,-0.756396598,-0.770130145,-0.466413792,0.150821753,0.776095562,0.987773287,1.009651331,0.657200693,0.082303074,-0.720745569,-1.110291722,-1.190420458,-1.17195634,-0.566303969,-0.176459783,0.062321499,0.809328574,1.253329503,1.191011656,1.114939918,-0.013000588,-0.494064023,-0.797251223,-0.979338687,-1.096367683,-1.088245888,-0.763286688,-0.425472648,0.071930431,0.417858737,0.292028504,0.721092503,1.008767012,1.117325384,1.141306605,1.099161127,0.967706129,0.467009246,0.096168919,-0.606193593,-0.784356282,-0.999208322,-1.061687357,-1.088313979,-1.011248918,-0.770847088,-0.545534111,-0.400816068,-0.317677099,-0.160314675,0.460017228,0.755349431,1.21020452,1.463883777,1.588694006}; -TSeries Complex = new() { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83}; -TSeries ComplexJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175.44,175.6810893,175.8382605,176.4050072,176.1609533,175.974375,175.2236006,175.5533713,174.9884683,174.615941,174.3770309,175.0623389,175.27043,176.32984,175.7164891,176.0973323,175.5682376,175.188465,173.2282697,171.8336671,171.1425322,170.4440719,169.7014159,170.7344496,171.3188789,173.3480163,174.1515576,175.0636931,176.2771412,177.5128437,177.8875485,177.87213,177.3582234,177.4250293,177.357529,177.4802419,177.6010334,177.7295287,177.8216397,177.8136695,175.6183153,174.6439913,174.2091633,173.3115795,172.1448758,171.6820873,171.5763613,172.9091515,174.0986078,175.3366475,175.4742249,175.5553884,174.8667808,174.6161513,173.8022615,172.9494297,172.4487235,172.1450989,171.9957087,171.7495045,171.879957,172.2274366,172.3995248,172.7694942,173.0853957,173.5105324}; -TSeries Market = new() { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25}; -TSeries MarketJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68.75,69.11126386,68.28856883,67.88047045,70.61221899,73.37735131,73.16751764,72.5016599,72.10679156,72.09353157,73.81775589,74.94089624,75.60649969,75.96759618,75.9599046,75.85557397,75.64181903,75.25160642,74.84644659,74.61728297,74.17868676,73.67238488,73.1842394,73.10785283,73.34958901,73.85707168,74.42911902,74.93038851,75.09287507,74.94649321,74.80499937,74.33318217,73.66893412,73.12071155,72.71498835,72.26423085,71.9702028,71.79260915,71.69675123,71.86943138,72.07979919,72.43023876,72.85788116,73.73196015,74.51914619,75.00208707,75.33621901,75.38718804,75.22566212,74.87443544,74.12468013,72.85729881,71.22401395,70.37858241,69.96256092,69.53514922,68.68810853,68.25445186,68.63035835,69.0349436,69.44967111,69.46200796,69.24863466,68.96050991,66.39400988,65.00557185}; - -#!csharp - -TSeries ma = Spike; -TSeries re = SpikeJMA; -TSeries out1 = new(); - -Jma calc = new(period: 10, phase: 0, factor: 0.45); - -foreach (var value in ma) { out1.Add(calc.Calc(value)); } - -Plot plt = new(); -var sigplot = plt.Add.Signal(ma.v.ToArray()[60..80]); -var jmaplot = plt.Add.Signal(re.v.ToArray()[60..80]); sigplot.Color = ScottPlot.Colors.Red; sigplot.LineWidth = 2; jmaplot.LineWidth = 3; -var jma1plot = plt.Add.Signal(out1.v.ToArray()[60..80]); jma1plot.Color = ScottPlot.Colors.Purple; jma1plot.LineWidth = 3; - -plt.Display(); diff --git a/notebooks/means.dib b/notebooks/means.dib deleted file mode 100644 index 3ac96ef8..00000000 --- a/notebooks/means.dib +++ /dev/null @@ -1,28 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "..\lib\obj\Debug\QuanTAlib.dll" -using QuanTAlib; -QuanTAlib.Formatters.Initialize(); - -#!csharp - -TSeries input = new(); -Beta ma1 = new (6); -Beta ma2 = new (input, 6); - -Random random = new Random(); - -for (int i = 0; i < 100; i++) { - double randomValue = random.NextDouble() * 100; - input.Add(randomValue); - ma1.Calc(randomValue); -} - -#!csharp - -display(ma1); -display(ma2); diff --git a/notebooks/talib.dib b/notebooks/talib.dib deleted file mode 100644 index 9d789170..00000000 --- a/notebooks/talib.dib +++ /dev/null @@ -1,29 +0,0 @@ -#!meta - -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} - -#!csharp - -#r "nuget: Atypical.TechnicalAnalysis.Functions, 0.0.0-alpha.0.173" - -#!csharp - -using TechnicalAnalysis.Functions; - -double[] data = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; -// Define the start and end indices -int startIdx = 0; -int endIdx = data.Length - 1; - -// Call the Sma method -TechnicalAnalysis.TACore.Globals.Compatibility = TechnicalAnalysis.Common.Compatibility.Default; -EmaResult result = TAMath.Ema(startIdx, endIdx, data, 8); - -for (int i=startIdx; i new Candle(DateTime.Now, (decimal)price, (decimal)price, (decimal)price, (decimal)price, 0)).ToList(); - -var ema = new ExponentialMovingAverage(candles, period).Compute().ToList(); - -for (int i=0; i - w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); - -#!csharp - -GbmFeed feed = new(); -TSeries data = new(feed.Close); -Ccv ma = new(feed,5); -TSeries result = new(ma); -feed.Add(12); -display(result); - -#!markdown - -```mermaid -graph TD - A[QuanTAlib] --> B[lib] - B --> C[core] - B --> D[averages] - B --> E[momentum] - B --> F[oscillators] - B --> G[errors] - B --> H[feeds] - B --> I[patterns] - B --> J[statistics] - B --> K[volatility] - B --> L[volume] diff --git a/quantower/Averages/AfirmaIndicator.cs b/quantower/Averages/AfirmaIndicator.cs deleted file mode 100644 index f852b33d..00000000 --- a/quantower/Averages/AfirmaIndicator.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class AfirmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Taps (number of weights)", sortIndex: 1, 1, 2000, 1, 0)] - public int Taps { get; set; } = 6; - - [InputParameter("Periods for lowpass cutoff", sortIndex: 2, 1, 2000, 1, 0)] - public int Periods { get; set; } = 6; - - [InputParameter("Window Type", sortIndex: 3, variants: [ - "Rectangular", Afirma.WindowType.Rectangular, - "Hanning", Afirma.WindowType.Hanning1, - "Hamming", Afirma.WindowType.Hanning2, - "Blackman", Afirma.WindowType.Blackman, - "Blackman-Harris", Afirma.WindowType.BlackmanHarris - ])] - public Afirma.WindowType Window { get; set; } = Afirma.WindowType.Hanning1; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - private Afirma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods + Taps; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public AfirmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "AFIRMA - Adaptive Finite Impulse Response Moving Average"; - Description = "Adaptive Finite Impulse Response Moving Average with ARMA component"; - - Series = new(name: $"AFIRMA {Taps}:{Periods}:{Window}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Afirma(periods: Periods, taps: Taps, window: Window); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - Series!.SetValue(result.Value); - } - - public override string ShortName => $"AFIRMA {Taps}:{Periods}:{Window}:{SourceName}"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/AlmaIndicator.cs b/quantower/Averages/AlmaIndicator.cs deleted file mode 100644 index c5112fce..00000000 --- a/quantower/Averages/AlmaIndicator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class AlmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 10; - - [InputParameter("Offset", sortIndex: 2, minimum: 0, maximum: 1, decimalPlaces: 2)] - public double Offset { get; set; } = 0.85; - - [InputParameter("Sigma", sortIndex: 3, minimum: 0, maximum: 100, decimalPlaces: 1)] - public double Sigma { get; set; } = 6.0; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Alma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Period; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"ALMA {Period}:{Offset:F2}:{Sigma:F1}:{SourceName}"; - - public AlmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "ALMA - Arnaud Legoux Moving Average"; - Description = "Arnaud Legoux Moving Average"; - Series = new(name: $"ALMA {Period}:{Offset:F2}:{Sigma:F0}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Alma(period: Period, offset: Offset, sigma: Sigma); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/DemaIndicator.cs b/quantower/Averages/DemaIndicator.cs deleted file mode 100644 index 1fa15213..00000000 --- a/quantower/Averages/DemaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class DemaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Dema? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Period; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"DEMA {Period}:{SourceName}"; - - public DemaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "DEMA - Double Exponential Moving Average"; - Description = "A faster-responding moving average that reduces lag by applying the EMA twice."; - Series = new(name: $"DEMA {Period}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Dema(period: Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/DsmaIndicator.cs b/quantower/Averages/DsmaIndicator.cs deleted file mode 100644 index 02370c74..00000000 --- a/quantower/Averages/DsmaIndicator.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class DsmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 10; - - [InputParameter("Scale factor", sortIndex: 2, minimum: 0.01, maximum: 1.0, increment: 0.01, decimalPlaces: 2)] - public double Scale { get; set; } = 0.5; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Dsma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths { get; private set; } - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"DSMA {Period}:{Scale:F2}:{SourceName}"; - - public DsmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "DSMA - Deviation Scaled Moving Average"; - Description = "A moving average that adjusts its responsiveness based on price deviations from the mean."; - Series = new(name: $"DSMA {Period}:{Scale:F2}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Dsma(Period, Scale); - MinHistoryDepths = ma.WarmupPeriod; - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/DwmaIndicator.cs b/quantower/Averages/DwmaIndicator.cs deleted file mode 100644 index 2cb65bc1..00000000 --- a/quantower/Averages/DwmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class DwmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Dwma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Period; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"DWMA {Period}:{SourceName}"; - - public DwmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "DWMA - Double Weighted Moving Average"; - Description = "A moving average that applies double weighting to recent prices for increased responsiveness."; - Series = new(name: $"DWMA {Period}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Dwma(Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/EmaIndicator.cs b/quantower/Averages/EmaIndicator.cs deleted file mode 100644 index 8c790662..00000000 --- a/quantower/Averages/EmaIndicator.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class EmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - [InputParameter("Use SMA for warmup period", sortIndex: 2)] - public bool UseSMA { get; set; } = false; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Ema? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"EMA {Periods}:{SourceName}"; - - public EmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "EMA - Exponential Moving Average"; - Description = "Exponential Moving Average"; - Series = new(name: $"EMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Ema(Periods, useSma: UseSMA); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/EpmaIndicator.cs b/quantower/Averages/EpmaIndicator.cs deleted file mode 100644 index 45f6af1c..00000000 --- a/quantower/Averages/EpmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class EpmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Epma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"EPMA {Periods}:{SourceName}"; - - public EpmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "EPMA - Exponential Percentage Moving Average"; - Description = "Exponential Percentage Moving Average"; - Series = new(name: $"EPMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Epma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/FramaIndicator.cs b/quantower/Averages/FramaIndicator.cs deleted file mode 100644 index 8d15d1d9..00000000 --- a/quantower/Averages/FramaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class FramaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Frama? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods * 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"FRAMA {Periods}:{SourceName}"; - - public FramaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "FRAMA - Fractal Adaptive Moving Average"; - Description = "Fractal Adaptive Moving Average"; - Series = new(name: $"FRAMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Frama(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/FwmaIndicator.cs b/quantower/Averages/FwmaIndicator.cs deleted file mode 100644 index b59da7b8..00000000 --- a/quantower/Averages/FwmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class FwmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Fwma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"FWMA {Periods}:{SourceName}"; - - public FwmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "FWMA - Fibonacci Weighted Moving Average"; - Description = "Fibonacci Weighted Moving Average"; - Series = new(name: $"FWMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Fwma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/GmaIndicator.cs b/quantower/Averages/GmaIndicator.cs deleted file mode 100644 index fa8700a3..00000000 --- a/quantower/Averages/GmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class GmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Gma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"GMA {Periods}:{SourceName}"; - - public GmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "GMA - Gaussian Moving Average"; - Description = "Gaussian Moving Average"; - Series = new(name: $"GMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Gma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/HmaIndicator.cs b/quantower/Averages/HmaIndicator.cs deleted file mode 100644 index ec903a34..00000000 --- a/quantower/Averages/HmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class HmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Hma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods + (int)Math.Sqrt(Periods) - 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"HMA {Periods}:{SourceName}"; - - public HmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "HMA - Hull Moving Average"; - Description = "Hull Moving Average"; - Series = new(name: $"HMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Hma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/HtitIndicator.cs b/quantower/Averages/HtitIndicator.cs deleted file mode 100644 index f8831085..00000000 --- a/quantower/Averages/HtitIndicator.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class HtitIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Data source", sortIndex: 1, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Htit? ma; - protected LineSeries? Series; - protected string? SourceName; - public static int MinHistoryDepths => 12; // Based on WarmupPeriod in Htit - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"HTIT:{SourceName}"; - - public HtitIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "HTIT - Hilbert Transform Instantaneous Trendline"; - Description = "Hilbert Transform Instantaneous Trendline (Note: This indicator may not be fully functional)"; - Series = new(name: "HTIT", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Htit(); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/HwmaIndicator.cs b/quantower/Averages/HwmaIndicator.cs deleted file mode 100644 index b92072aa..00000000 --- a/quantower/Averages/HwmaIndicator.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class HwmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods (only when nA=nB=nC=0)", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("nA", sortIndex: 2, 0, 1, 0.01, 2)] - public double NA { get; set; } = 0; - - [InputParameter("nB", sortIndex: 3, 0, 1, 0.01, 2)] - public double NB { get; set; } = 0; - - [InputParameter("nC", sortIndex: 4, 0, 1, 0.01, 2)] - public double NC { get; set; } = 0; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Hwma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"HWMA {Periods}:{NA}:{NB}:{NC}:{SourceName}"; - - public HwmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "HWMA - Holt-Winter Moving Average"; - Description = "Holt-Winter Moving Average"; - Series = new(name: $"HWMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - if ((NA, NB, NC) == (0, 0, 0)) - { - ma = new Hwma(Periods); - } - else - { - ma = new Hwma(Periods, NA, NB, NC); - } - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/JmaIndicator.cs b/quantower/Averages/JmaIndicator.cs deleted file mode 100644 index 7eaca362..00000000 --- a/quantower/Averages/JmaIndicator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class JmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Phase", sortIndex: 2, -100, 100, 1, 0)] - public int Phase { get; set; } = 0; - - [InputParameter("Beta factor", sortIndex: 3, minimum: 0, maximum: 5, increment: 0.01, decimalPlaces: 2)] - public double Factor { get; set; } = 0.45; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Jma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Math.Max(65, Periods * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"JMA {Periods}:{Phase}:{Factor:F2}:{SourceName}"; - - public JmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "JMA - Jurik Moving Average"; - Description = "Jurik Moving Average (Note: This indicator may have consistency issues)"; - Series = new(name: $"JMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Jma(period: Periods, phase: Phase, factor: Factor); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/KamaIndicator.cs b/quantower/Averages/KamaIndicator.cs deleted file mode 100644 index c7456879..00000000 --- a/quantower/Averages/KamaIndicator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class KamaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Fast", sortIndex: 2, 1, 100, 1, 0)] - public int Fast { get; set; } = 2; - - [InputParameter("Slow", sortIndex: 3, 1, 100, 1, 0)] - public int Slow { get; set; } = 30; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Kama? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"KAMA {Periods}:{Fast}:{Slow}:{SourceName}"; - - public KamaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "KAMA - Kaufman's Adaptive Moving Average"; - Description = "Kaufman's Adaptive Moving Average"; - Series = new(name: $"KAMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Kama(Periods, Fast, Slow); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/LtmaIndicator.cs b/quantower/Averages/LtmaIndicator.cs deleted file mode 100644 index 496d5701..00000000 --- a/quantower/Averages/LtmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class LtmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Gamma", sortIndex: 1, 0.01, 1, 0.01, 2)] - public double Gamma { get; set; } = 0.1; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Ltma? ma; - protected LineSeries? Series; - protected string? SourceName; - public static int MinHistoryDepths => 4; // Based on WarmupPeriod in Ltma - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"LTMA {Gamma}:{SourceName}"; - - public LtmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "LTMA - Laguerre Time Moving Average"; - Description = "Laguerre Time Moving Average"; - Series = new(name: $"LTMA {Gamma}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Ltma(Gamma); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/MaafIndicator.cs b/quantower/Averages/MaafIndicator.cs deleted file mode 100644 index 15550e4d..00000000 --- a/quantower/Averages/MaafIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MaafIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 3, 1000, 1, 0)] - public int Periods { get; set; } = 10; - - [InputParameter("Threshold", sortIndex: 2, 0.0001, 0.1, 0.0001, 4)] - public double Threshold { get; set; } = 0.002; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Maaf? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"MAAF {Periods}:{Threshold}:{SourceName}"; - - public MaafIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "MAAF - Median Adaptive Averaging Filter"; - Description = "Median Adaptive Averaging Filter (Note: This indicator may have consistency issues)"; - Series = new(name: $"MAAF {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Maaf(Periods, Threshold); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/MamaIndicator.cs b/quantower/Averages/MamaIndicator.cs deleted file mode 100644 index 870fc2c1..00000000 --- a/quantower/Averages/MamaIndicator.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MamaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Fast Limit", sortIndex: 1, 0.01, 1, 0.01, 2)] - public double FastLimit { get; set; } = 0.5; - - [InputParameter("Slow Limit", sortIndex: 2, 0.01, 1, 0.01, 2)] - public double SlowLimit { get; set; } = 0.05; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Mama? ma; - protected LineSeries? MamaSeries; - protected LineSeries? FamaSeries; - protected string? SourceName; - public static int MinHistoryDepths => 6; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"MAMA {FastLimit}:{SlowLimit}:{SourceName}"; - - public MamaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "MAMA - MESA Adaptive Moving Average"; - Description = "MESA Adaptive Moving Average"; - MamaSeries = new(name: "MAMA", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - FamaSeries = new(name: "FAMA", color: Color.Red, width: 2, style: LineStyle.Solid); - AddLineSeries(MamaSeries); - AddLineSeries(FamaSeries); - } - - protected override void OnInit() - { - ma = new Mama(FastLimit, SlowLimit); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - MamaSeries!.SetValue(result.Value); - MamaSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - FamaSeries!.SetValue(ma.Fama.Value); - FamaSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, MamaSeries!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.PaintSmoothCurve(args, FamaSeries!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/MgdiIndicator.cs b/quantower/Averages/MgdiIndicator.cs deleted file mode 100644 index 77b0b381..00000000 --- a/quantower/Averages/MgdiIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MgdiIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("K-Factor", sortIndex: 2, 0.1, 2, 0.1, 1)] - public double KFactor { get; set; } = 0.6; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Mgdi? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"MGDI {Periods}:{KFactor}:{SourceName}"; - - public MgdiIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "MGDI - McGinley Dynamic Indicator"; - Description = "McGinley Dynamic Indicator"; - Series = new(name: $"MGDI {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Mgdi(Periods, KFactor); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/MmaIndicator.cs b/quantower/Averages/MmaIndicator.cs deleted file mode 100644 index 57cc296c..00000000 --- a/quantower/Averages/MmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Mma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"MMA {Periods}:{SourceName}"; - - public MmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "MMA - Modified Moving Average"; - Description = "Modified Moving Average"; - Series = new(name: $"MMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Mma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/PwmaIndicator.cs b/quantower/Averages/PwmaIndicator.cs deleted file mode 100644 index 17d7b667..00000000 --- a/quantower/Averages/PwmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class PwmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Pwma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"PWMA {Periods}:{SourceName}"; - - public PwmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "PWMA - Pascal's Weighted Moving Average"; - Description = "Pascal's Weighted Moving Average"; - Series = new(name: $"PWMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Pwma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/RemaIndicator.cs b/quantower/Averages/RemaIndicator.cs deleted file mode 100644 index 80a0916b..00000000 --- a/quantower/Averages/RemaIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RemaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Lambda", sortIndex: 2, 0, 1, 0.01, 2)] - public double Lambda { get; set; } = 0.5; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Rema? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"REMA {Periods}:{Lambda}:{SourceName}"; - - public RemaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "REMA - Regularized Exponential Moving Average"; - Description = "Regularized Exponential Moving Average"; - Series = new(name: $"REMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Rema(Periods, Lambda); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/RmaIndicator.cs b/quantower/Averages/RmaIndicator.cs deleted file mode 100644 index 25270465..00000000 --- a/quantower/Averages/RmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Rma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods * 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"RMA {Periods}:{SourceName}"; - - public RmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "RMA - Relative Moving Average (Wilder's Moving Average)"; - Description = "Relative Moving Average, also known as Wilder's Moving Average"; - Series = new(name: $"RMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Rma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/SinemaIndicator.cs b/quantower/Averages/SinemaIndicator.cs deleted file mode 100644 index 8b961acd..00000000 --- a/quantower/Averages/SinemaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class SinemaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Sinema? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"SINEMA {Periods}:{SourceName}"; - - public SinemaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "SINEMA - Sine-Weighted Moving Average"; - Description = "Sine-Weighted Moving Average"; - Series = new(name: $"SINEMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Sinema(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/SmaIndicator.cs b/quantower/Averages/SmaIndicator.cs deleted file mode 100644 index 31bd9107..00000000 --- a/quantower/Averages/SmaIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class SmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 1000, 1, 0)] - public int Period { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Sma? ma; - private Mape? error; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Period; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public SmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "SMA - Simple Moving Average"; - Description = "Simple Moving Average"; - Series = new(name: $"SMA {Period}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Sma(Period); - error = new(Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - error!.Calc(input, result); - - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - Series!.SetValue(result.Value); - } - - public override string ShortName => $"SMA {Period}:{SourceName}"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/SmmaIndicator.cs b/quantower/Averages/SmmaIndicator.cs deleted file mode 100644 index b43070a2..00000000 --- a/quantower/Averages/SmmaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class SmmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Smma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"SMMA {Periods}:{SourceName}"; - - public SmmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "SMMA - Smoothed Moving Average"; - Description = "Smoothed Moving Average"; - Series = new(name: $"SMMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Smma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/T3Indicator.cs b/quantower/Averages/T3Indicator.cs deleted file mode 100644 index ccf62cdd..00000000 --- a/quantower/Averages/T3Indicator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class T3Indicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Volume Factor", sortIndex: 2, 0, 1, 0.01, 2)] - public double VolumeFactor { get; set; } = 0.7; - - [InputParameter("Use SMA", sortIndex: 3)] - public bool UseSma { get; set; } = true; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private T3? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"T3 {Periods}:{VolumeFactor}:{UseSma}:{SourceName}"; - - public T3Indicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "T3 - Tillson T3 Moving Average"; - Description = "Tillson T3 Moving Average"; - Series = new(name: $"T3 {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new T3(Periods, VolumeFactor, UseSma); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/TemaIndicator.cs b/quantower/Averages/TemaIndicator.cs deleted file mode 100644 index f37a03c9..00000000 --- a/quantower/Averages/TemaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class TemaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Tema? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => (int)Math.Ceiling(-Periods * Math.Log(1 - 0.85)); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"TEMA {Periods}:{SourceName}"; - - public TemaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "TEMA - Triple Exponential Moving Average"; - Description = "Triple Exponential Moving Average"; - Series = new(name: $"TEMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Tema(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/TrimaIndicator.cs b/quantower/Averages/TrimaIndicator.cs deleted file mode 100644 index 2350d4e5..00000000 --- a/quantower/Averages/TrimaIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class TrimaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Trima? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"TRIMA {Periods}:{SourceName}"; - - public TrimaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "TRIMA - Triangular Moving Average"; - Description = "Triangular Moving Average"; - Series = new(name: $"TRIMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Trima(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/VidyaIndicator.cs b/quantower/Averages/VidyaIndicator.cs deleted file mode 100644 index 3b4c395c..00000000 --- a/quantower/Averages/VidyaIndicator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class VidyaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Short Period", sortIndex: 1, 1, 1000, 1, 0)] - public int ShortPeriod { get; set; } = 14; - - [InputParameter("Long Period", sortIndex: 2, 0, 1000, 1, 0)] - public int LongPeriod { get; set; } = 0; - - [InputParameter("Alpha", sortIndex: 3, 0.01, 1, 0.01, 2)] - public double Alpha { get; set; } = 0.2; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Vidya? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => LongPeriod == 0 ? ShortPeriod * 4 : LongPeriod; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"VIDYA {ShortPeriod}:{LongPeriod}:{Alpha}:{SourceName}"; - - public VidyaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "VIDYA - Variable Index Dynamic Average"; - Description = "Variable Index Dynamic Average"; - Series = new(name: $"VIDYA {ShortPeriod}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Vidya(ShortPeriod, LongPeriod, Alpha); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/WmaIndicator.cs b/quantower/Averages/WmaIndicator.cs deleted file mode 100644 index 0c76128d..00000000 --- a/quantower/Averages/WmaIndicator.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class WmaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Wma? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"WMA {Periods}:{SourceName}"; - - public WmaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "WMA - Weighted Moving Average"; - Description = "Weighted Moving Average"; - Series = new(name: $"WMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Wma(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } -#pragma warning disable CA1416 // Validate platform compatibility - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/ZlemaIndicator.cs b/quantower/Averages/ZlemaIndicator.cs deleted file mode 100644 index 30bf7200..00000000 --- a/quantower/Averages/ZlemaIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class ZlemaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Zlema? ma; - private Huber? err; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"ZLEMA {Periods}:{SourceName}"; - - public ZlemaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "ZLEMA - Zero Lag Exponential Moving Average"; - Description = "Zero Lag Exponential Moving Average"; - Series = new(name: $"ZLEMA {Periods}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new(Periods); - err = new(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - err!.Calc(input, result); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Averages/_Averages.csproj b/quantower/Averages/_Averages.csproj deleted file mode 100644 index db8b5c11..00000000 --- a/quantower/Averages/_Averages.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Averages - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/quantower/Experiments/ConvolutionIndicator.cs b/quantower/Experiments/ConvolutionIndicator.cs deleted file mode 100644 index f46ad6a4..00000000 --- a/quantower/Experiments/ConvolutionIndicator.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Drawing; -using System.Linq; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class ConvolutionIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Kernel (comma/space/semicolon separated numbers)", sortIndex: 1)] - public string KernelString { get; set; } = "0.25, 0.5, 0.25, -0.5"; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Convolution? conv; - private Mape? error; - protected LineSeries? Series; - protected string? SourceName; - private double[]? kernel; - public int MinHistoryDepths => kernel?.Length ?? 3; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public ConvolutionIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "CONV - Convolution Filter"; - Description = "Convolution Filter with custom kernel"; - kernel = ParseKernel(KernelString); - Series = new(name: $"CONV {string.Join(",", kernel.Select(x => x.ToString("F2")))}", - color: IndicatorExtensions.Averages, - width: 2, - style: LineStyle.Solid); - AddLineSeries(Series); - } - - private static double[] ParseKernel(string kernelStr) - { - // Split on common delimiters: comma, semicolon, space, tab, pipe - var numbers = kernelStr.Split(new[] { ',', ';', ' ', '\t', '|' }, - StringSplitOptions.RemoveEmptyEntries | - StringSplitOptions.TrimEntries); - - var kernel = new double[numbers.Length]; - for (int i = 0; i < numbers.Length; i++) - { - if (!double.TryParse(numbers[i], out kernel[i])) - { - // Default to simple 3-point moving average if parsing fails - return new double[] { 0.25, 0.5, 0.25, -0.5 }; - } - } - return kernel; - } - - protected override void OnInit() - { - kernel = ParseKernel(KernelString); - conv = new Convolution(kernel); - error = new(kernel.Length); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = conv!.Calc(input); - error!.Calc(input, result); - - Series!.SetMarker(0, Color.Transparent); - Series!.SetValue(result.Value); - } - - public override string ShortName => $"CONV {KernelString}:{SourceName}"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, kernel!.Length, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Experiments/FlowIndicator.cs b/quantower/Experiments/FlowIndicator.cs deleted file mode 100644 index 40649719..00000000 --- a/quantower/Experiments/FlowIndicator.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Drawing; -using System.Drawing.Drawing2D; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class FlowIndicator : Indicator, IWatchlistIndicator -{ - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public FlowIndicator() - { - Name = "Flow Visualization"; - SeparateWindow = false; - } - - protected override void OnInit() - { - // placeholder - } - - protected override void OnUpdate(UpdateArgs args) - { - // placeholder - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - Graphics gr = args.Graphics; - gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; - var mainWindow = this.CurrentChart.Windows[args.WindowIndex]; - var converter = mainWindow.CoordinatesConverter; - var clientRect = mainWindow.ClientRectangle; - gr.SetClip(clientRect); - DateTime leftTime = new[] { converter.GetTime(clientRect.Left), this.HistoricalData.Time(this!.Count - 1) }.Max(); - DateTime rightTime = new[] { converter.GetTime(clientRect.Right), this.HistoricalData.Time(0) }.Min(); - - int leftIndex = (int)this.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1; - int rightIndex = (int)this.HistoricalData.GetIndexByTime(rightTime.Ticks); - int width = this.CurrentChart.BarsWidth; - - for (int i = rightIndex; i < leftIndex; i++) - { - int barX1 = (int)converter.GetChartX(this.HistoricalData.Time(i)); - int barY1 = (int)converter.GetChartY(this.HistoricalData.Open(i)); - int barYHigh = (int)converter.GetChartY(this.HistoricalData.High(i)); - int barYLow = (int)converter.GetChartY(this.HistoricalData.Low(i)); - int barX2 = barX1 + width; - int barY2 = (int)converter.GetChartY(this.HistoricalData.Close(i)); - using (Brush transparentBrush = new SolidBrush(Color.FromArgb(250, 70, 70, 70))) - { - gr.FillRectangle(transparentBrush, barX1, barYHigh - 1, CurrentChart.BarsWidth, Math.Abs(barYLow - barYHigh) + 2); - } - using (Brush circ = new SolidBrush(Color.FromArgb(100, 255, 255, 0))) - { - int size = 3; - gr.FillEllipse(circ, barX1 - size, barY1 - size, 2 * size, 2 * size); - gr.FillEllipse(circ, barX2 - size, barY2 - size, 2 * size, 2 * size); - } - using (Pen defaultPen = new(Color.Yellow, 3)) - { - defaultPen.StartCap = LineCap.Round; - defaultPen.EndCap = LineCap.Round; - gr.DrawLine(defaultPen, barX1, barY1, barX2, barY2); - } - if (i > 0) - { - int barX0 = (int)converter.GetChartX(this.HistoricalData.Time(i - 1)); - int barY0 = (int)converter.GetChartY(this.HistoricalData.Open(i - 1)); - using (Pen dottedPen = new(Color.Yellow, 1)) - { - dottedPen.DashStyle = DashStyle.Dot; - gr.DrawLine(dottedPen, barX2, barY2, barX0, barY0); - } - } - } - } -} diff --git a/quantower/Experiments/QemaIndicator.cs b/quantower/Experiments/QemaIndicator.cs deleted file mode 100644 index 1bb65542..00000000 --- a/quantower/Experiments/QemaIndicator.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class QemaIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("K1", sortIndex: 1, 0.01, 1, 0.01, 2)] - public double K1 { get; set; } = 0.2; - - [InputParameter("K2", sortIndex: 2, 0.01, 1, 0.01, 2)] - public double K2 { get; set; } = 0.2; - - [InputParameter("K3", sortIndex: 3, 0.01, 1, 0.01, 2)] - public double K3 { get; set; } = 0.2; - - [InputParameter("K4", sortIndex: 4, 0.01, 1, 0.01, 2)] - public double K4 { get; set; } = 0.2; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Qema? ma; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => (int)((2 - Math.Min(Math.Min(K1, K2), Math.Min(K3, K4))) / Math.Min(Math.Min(K1, K2), Math.Min(K3, K4))); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"QEMA {K1},{K2},{K3},{K4}:{SourceName}"; - - public QemaIndicator() - { - OnBackGround = true; - SeparateWindow = false; - SourceName = Source.ToString(); - Name = "QEMA - Quadruple Exponential Moving Average"; - Description = "Quadruple Exponential Moving Average"; - Series = new(name: $"QEMA {K1},{K2},{K3},{K4}", color: IndicatorExtensions.Averages, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Qema(K1, K2, K3, K4); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Experiments/TestIndicator.cs b/quantower/Experiments/TestIndicator.cs deleted file mode 100644 index 37f416d2..00000000 --- a/quantower/Experiments/TestIndicator.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class TestIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 20, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Sma? ma; - protected LineSeries? Series; - public int MinHistoryDepths { get; set; } - int IWatchlistIndicator.MinHistoryDepths => 0; //QuanTAlib indicators generate value immediately - - - public TestIndicator() - { - OnBackGround = true; - SeparateWindow = false; - Name = "TEST"; - Description = "test and test and test and more test."; - Series = new(name: $"{Name}", color: IndicatorExtensions.Volatility, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - ma = new Sma(Period); - base.OnInit(); - } - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - Series!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - Series!.SetValue(result); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ma!.WarmupPeriod, ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Experiments/_Experiments.csproj b/quantower/Experiments/_Experiments.csproj deleted file mode 100644 index fc59e16d..00000000 --- a/quantower/Experiments/_Experiments.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Experiments - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/quantower/IndicatorExtensions.cs b/quantower/IndicatorExtensions.cs deleted file mode 100644 index e3a7e369..00000000 --- a/quantower/IndicatorExtensions.cs +++ /dev/null @@ -1,219 +0,0 @@ -using TradingPlatform.BusinessLayer; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace QuanTAlib; - -public enum SourceType -{ - Open, High, Low, Close, HL2, OC2, OHL3, HLC3, OHLC4, HLCC4 -} - -public enum MaType -{ - Alma, Dema, Dsma, Dwma, Ema, Epma, Frama, Fwma, Gma, Hma, Hwma, Jma, Kama, Maaf, Mgdi, MMa, Pwma, Rema, Rma, Sinema, Sma, Smma, T3, Tema, Trima, Vidya, Wma, Zlema -} - -public static class IndicatorExtensions -{ - public static readonly Color Averages = Color.FromArgb(255, 255, 128); // #FFFF80 - Yellow - public static readonly Color Volume = Color.FromArgb(128, 255, 128); // #80FF80 - Green - public static readonly Color Volatility = Color.FromArgb(255, 128, 128); // #FF8080 - Red - public static readonly Color Statistics = Color.FromArgb(128, 128, 255); // #8080FF - Blue - public static readonly Color Oscillators = Color.FromArgb(255, 128, 255); // #FF80FF - Magenta - public static readonly Color Momentum = Color.FromArgb(128, 255, 255); // #80FFFF - Cyan - public static readonly Color Experiments = Color.FromArgb(255, 165, 0); // #FFA500 - Orange - - public static TValue GetInputValue(this Indicator indicator, UpdateArgs args, SourceType source) - { - var historicalData = indicator.HistoricalData; - - TBar bar = new TBar( - Time: historicalData.Time(), - Open: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Open], - High: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.High], - Low: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Low], - Close: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Close], - Volume: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Volume], - IsNew: args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar - ); - - double price = source switch - { - SourceType.Open => bar.Open, - SourceType.High => bar.High, - SourceType.Low => bar.Low, - SourceType.Close => bar.Close, - SourceType.HL2 => bar.HL2, - SourceType.OC2 => bar.OC2, - SourceType.OHL3 => bar.OHL3, - SourceType.HLC3 => bar.HLC3, - SourceType.OHLC4 => bar.OHLC4, - SourceType.HLCC4 => bar.HLCC4, - _ => bar.Close - }; - - return new TValue(bar.Time, price, bar.IsNew); - } - - public static TBar GetInputBar(this Indicator indicator, UpdateArgs args) - { - var historicalData = indicator.HistoricalData; - - return new TBar( - Time: historicalData.Time(), - Open: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Open], - High: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.High], - Low: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Low], - Close: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Close], - Volume: historicalData[indicator.Count - 1, SeekOriginHistory.Begin][PriceType.Volume], - IsNew: args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar - ); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public static void PaintHLine(this Indicator indicator, PaintChartEventArgs args, double value, Pen pen) - { - if (indicator.CurrentChart == null) - return; - - Graphics gr = args.Graphics; - var mainWindow = indicator.CurrentChart.Windows[args.WindowIndex]; - var converter = mainWindow.CoordinatesConverter; - var clientRect = mainWindow.ClientRectangle; - gr.SetClip(clientRect); - int leftX = clientRect.Left; - int rightX = clientRect.Right; - int Y = (int)converter.GetChartY(value); - using (pen) - { - gr.DrawLine(pen, new Point(leftX, Y), new Point(rightX, Y)); - } - } - - public static void PaintSmoothCurve(this Indicator indicator, PaintChartEventArgs args, LineSeries series, int warmupPeriod, bool showColdValues = true, double tension = 0.2) - { - if (!series.Visible || indicator.CurrentChart == null) - return; - - Graphics gr = args.Graphics; - gr.SmoothingMode = SmoothingMode.AntiAlias; - var mainWindow = indicator.CurrentChart.Windows[args.WindowIndex]; - var converter = mainWindow.CoordinatesConverter; - - var clientRect = mainWindow.ClientRectangle; - - gr.SetClip(clientRect); - DateTime leftTime = new[] { converter.GetTime(clientRect.Left), indicator.HistoricalData.Time(indicator!.Count - 1) }.Max(); - DateTime rightTime = new[] { converter.GetTime(clientRect.Right), indicator.HistoricalData.Time(0) }.Min(); - - int leftIndex = (int)indicator.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1; - int rightIndex = (int)indicator.HistoricalData.GetIndexByTime(rightTime.Ticks); - - List allPoints = new List(); - for (int i = rightIndex; i < leftIndex; i++) - { - int barX = (int)converter.GetChartX(indicator.HistoricalData.Time(i)); - int barY = (int)converter.GetChartY(series[i]); - int halfBarWidth = indicator.CurrentChart.BarsWidth / 2; - Point point = new Point(barX + halfBarWidth, barY); - allPoints.Add(point); - } - - if (allPoints.Count > 1) - { - if (allPoints.Count < 2) return; - - using (Pen defaultPen = new(series.Color, series.Width) { DashStyle = ConvertLineStyleToDashStyle(series.Style) }) - using (Pen coldPen = new(series.Color, series.Width) { DashStyle = DashStyle.Dot }) - { - int hotCount = indicator.Count - warmupPeriod - rightIndex; - // Draw the hot part - if (hotCount > 0) - { - var hotPoints = allPoints.Take(Math.Min(hotCount + 1, allPoints.Count)).ToArray(); - gr.DrawCurve(defaultPen, hotPoints, 0, hotPoints.Length - 1, (float)tension); - } - - // Draw the cold part - if (showColdValues && hotCount < allPoints.Count) - { - var coldPoints = allPoints.Skip(Math.Max(0, hotCount)).ToArray(); - gr.DrawCurve(coldPen, coldPoints, 0, coldPoints.Length - 1, (float)tension); - } - } - } - } - - public static void PaintHistogram(this Indicator indicator, PaintChartEventArgs args, LineSeries series, int warmupPeriod, bool showColdValues = true) - { - if (!series.Visible || indicator.CurrentChart == null) - return; - - Graphics gr = args.Graphics; - gr.SmoothingMode = SmoothingMode.AntiAlias; - var mainWindow = indicator.CurrentChart.Windows[args.WindowIndex]; - var converter = mainWindow.CoordinatesConverter; - var clientRect = mainWindow.ClientRectangle; - - gr.SetClip(clientRect); - DateTime leftTime = new[] { converter.GetTime(clientRect.Left), indicator.HistoricalData.Time(indicator!.Count - 1) }.Max(); - DateTime rightTime = new[] { converter.GetTime(clientRect.Right), indicator.HistoricalData.Time(0) }.Min(); - int leftIndex = (int)indicator.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1; - int rightIndex = (int)indicator.HistoricalData.GetIndexByTime(rightTime.Ticks); - - for (int i = rightIndex; i < leftIndex; i++) - { - int barX = (int)converter.GetChartX(indicator.HistoricalData.Time(i)); - int barY = (int)converter.GetChartY(series[i]); - int barY0 = (int)converter.GetChartY(0); - int HistBarWidth = indicator.CurrentChart.BarsWidth - 2; - - if (series[i] > 0) - { - using (Brush hist = new SolidBrush(Color.FromArgb(150, 0, 255, 0))) - { - gr.FillRectangle(hist, barX, barY, HistBarWidth, Math.Abs(barY - barY0)); - } - } - else - { - using (Brush hist = new SolidBrush(Color.FromArgb(150, 255, 0, 0))) - { - gr.FillRectangle(hist, barX, barY0, HistBarWidth, Math.Abs(barY0 - barY)); - } - } - } - } - - public static void DrawText(this Indicator indicator, PaintChartEventArgs args, string text) - { - if (indicator.CurrentChart == null) - return; - - Graphics gr = args.Graphics; - var clientRect = indicator.CurrentChart.MainWindow.ClientRectangle; - - Font font = new Font("Inter", 8); - SizeF textSize = gr.MeasureString(text, font); - RectangleF textRect = new RectangleF(clientRect.Left + 5, - clientRect.Bottom - textSize.Height - 10, - textSize.Width + 10, textSize.Height + 10); - - gr.FillRectangle(Brushes.DarkBlue, textRect); - gr.DrawString(text, font, Brushes.White, new PointF(textRect.X + 6, textRect.Y + 5)); - } - - private static DashStyle ConvertLineStyleToDashStyle(LineStyle lineStyle) - { - return lineStyle switch - { - LineStyle.Solid => DashStyle.Solid, - LineStyle.Dash => DashStyle.Dash, - LineStyle.Dot => DashStyle.Dot, - LineStyle.DashDot => DashStyle.DashDot, - _ => DashStyle.Solid, - }; - } -} diff --git a/quantower/Momentum/AdxIndicator.cs b/quantower/Momentum/AdxIndicator.cs deleted file mode 100644 index d376d60d..00000000 --- a/quantower/Momentum/AdxIndicator.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class AdxIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Adx? adx; - protected LineSeries? AdxSeries; - public int MinHistoryDepths => Math.Max(5, Periods * 3); // Need extra periods for ADX calculation - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public AdxIndicator() - { - Name = "ADX - Average Directional Movement Index"; - Description = "Measures the strength of a trend, regardless of its direction."; - SeparateWindow = true; - - AdxSeries = new($"ADX {Periods}", color: IndicatorExtensions.Momentum, 2, LineStyle.Solid); - AddLineSeries(AdxSeries); - } - - protected override void OnInit() - { - adx = new Adx(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = adx!.Calc(input); - - AdxSeries!.SetValue(result.Value); - AdxSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"ADX ({Periods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, AdxSeries!, adx!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/AdxrIndicator.cs b/quantower/Momentum/AdxrIndicator.cs deleted file mode 100644 index 2a55689a..00000000 --- a/quantower/Momentum/AdxrIndicator.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class AdxrIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Adxr? adxr; - protected LineSeries? AdxrSeries; - public int MinHistoryDepths => Math.Max(5, Periods * 4); // Need extra periods for ADXR calculation - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public AdxrIndicator() - { - Name = "ADXR - Average Directional Movement Index Rating"; - Description = "Measures trend strength by comparing current ADX with historical ADX values."; - SeparateWindow = true; - - AdxrSeries = new($"ADXR {Periods}", Color.Blue, 2, LineStyle.Solid); - AddLineSeries(AdxrSeries); - } - - protected override void OnInit() - { - adxr = new Adxr(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = adxr!.Calc(input); - - AdxrSeries!.SetValue(result.Value); - AdxrSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"ADXR ({Periods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintHLine(args, 25, new Pen(color: IndicatorExtensions.Momentum, width: 1)); // Strong trend line - this.PaintHLine(args, 20, new Pen(color: IndicatorExtensions.Momentum, width: 1)); // Weak trend line - this.PaintSmoothCurve(args, AdxrSeries!, adxr!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/ApoIndicator.cs b/quantower/Momentum/ApoIndicator.cs deleted file mode 100644 index 23748888..00000000 --- a/quantower/Momentum/ApoIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class ApoIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Fast Period", sortIndex: 1, 1, 2000, 1, 0)] - public int FastPeriod { get; set; } = 12; - - [InputParameter("Slow Period", sortIndex: 2, 1, 2000, 1, 0)] - public int SlowPeriod { get; set; } = 26; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Apo? apo; - protected LineSeries? ApoSeries; - public int MinHistoryDepths => Math.Max(FastPeriod, SlowPeriod) * 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public ApoIndicator() - { - Name = "APO - Absolute Price Oscillator"; - Description = "Shows the difference between two moving averages of different periods."; - SeparateWindow = true; - - ApoSeries = new($"APO {FastPeriod},{SlowPeriod}", color: IndicatorExtensions.Momentum, 2, LineStyle.Solid); - AddLineSeries(ApoSeries); - } - - protected override void OnInit() - { - apo = new Apo(FastPeriod, SlowPeriod); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = apo!.Calc(input); - - ApoSeries!.SetValue(result.Value); - ApoSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"APO ({FastPeriod},{SlowPeriod})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, ApoSeries!, apo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/DmiIndicator.cs b/quantower/Momentum/DmiIndicator.cs deleted file mode 100644 index 7cd72f7b..00000000 --- a/quantower/Momentum/DmiIndicator.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class DmiIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Dmi? dmi; - protected LineSeries? PlusDiSeries; - protected LineSeries? MinusDiSeries; - public int MinHistoryDepths => Math.Max(5, Periods * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public DmiIndicator() - { - Name = "DMI - Directional Movement Index"; - Description = "Identifies the directional movement of a price by comparing successive highs and lows."; - SeparateWindow = true; - - PlusDiSeries = new($"+DI {Periods}", color: Color.Red, 2, LineStyle.Solid); - MinusDiSeries = new($"-DI {Periods}", color: Color.Blue, 2, LineStyle.Solid); - AddLineSeries(PlusDiSeries); - AddLineSeries(MinusDiSeries); - } - - protected override void OnInit() - { - dmi = new Dmi(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - var result = dmi!.Calc(input); - - PlusDiSeries!.SetValue(dmi.PlusDI); - MinusDiSeries!.SetValue(dmi.MinusDI); - PlusDiSeries!.SetMarker(0, Color.Transparent); - MinusDiSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"DMI ({Periods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, PlusDiSeries!, dmi!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.PaintSmoothCurve(args, MinusDiSeries!, dmi!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/DmxIndicator.cs b/quantower/Momentum/DmxIndicator.cs deleted file mode 100644 index fa55606a..00000000 --- a/quantower/Momentum/DmxIndicator.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class DmxIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("DMI Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int DmiPeriods { get; set; } = 14; - - [InputParameter("JMA Smoothing Periods", sortIndex: 2, 1, 2000, 1, 0)] - public int JmaPeriods { get; set; } = 12; - - [InputParameter("JMA Phase", sortIndex: 3, -100, 100, 1, 0)] - public int JmaPhase { get; set; } = 100; - - [InputParameter("JMA Factor", sortIndex: 4, 0.01, 1, 0.01, 2)] - public double JmaFactor { get; set; } = 0.3; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Dmx? dmx; - protected LineSeries? PlusDiSeries; - protected LineSeries? MinusDiSeries; - public int MinHistoryDepths => Math.Max(5, (DmiPeriods + JmaPeriods) * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public DmxIndicator() - { - Name = "DMX - Enhanced Directional Movement Index"; - Description = "An enhanced version of DMI using JMA smoothing for better noise reduction and responsiveness."; - SeparateWindow = true; - - PlusDiSeries = new($"+DI {DmiPeriods}", color: Color.Red, 2, LineStyle.Solid); - MinusDiSeries = new($"-DI {DmiPeriods}", color: Color.Blue, 2, LineStyle.Solid); - AddLineSeries(PlusDiSeries); - AddLineSeries(MinusDiSeries); - } - - protected override void OnInit() - { - dmx = new Dmx(DmiPeriods, JmaPeriods, JmaPhase, JmaFactor); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - var result = dmx!.Calc(input); - - PlusDiSeries!.SetValue(dmx.PlusDI); - MinusDiSeries!.SetValue(dmx.MinusDI); - PlusDiSeries!.SetMarker(0, Color.Transparent); - MinusDiSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"DMX ({DmiPeriods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, PlusDiSeries!, dmx!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.PaintSmoothCurve(args, MinusDiSeries!, dmx!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/DpoIndicator.cs b/quantower/Momentum/DpoIndicator.cs deleted file mode 100644 index 0937956d..00000000 --- a/quantower/Momentum/DpoIndicator.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class DpoIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 3)] - public bool ShowColdValues { get; set; } = true; - - private Dpo? dpo; - protected LineSeries? DpoSeries; - public int MinHistoryDepths => Period * 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public DpoIndicator() - { - Name = "DPO - Detrended Price Oscillator"; - Description = "Removes trend from price by comparing current price to a past moving average, helping identify cycles in the price."; - SeparateWindow = true; - - DpoSeries = new($"DPO {Period}", color: IndicatorExtensions.Momentum, 2, LineStyle.Solid); - AddLineSeries(DpoSeries); - } - - protected override void OnInit() - { - dpo = new Dpo(Period); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = this.GetInputBar(args); - TValue result = dpo!.Calc(input); - - DpoSeries!.SetValue(result.Value); - DpoSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"DPO ({Period})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, DpoSeries!, dpo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/MacdIndicator.cs b/quantower/Momentum/MacdIndicator.cs deleted file mode 100644 index fd39ce81..00000000 --- a/quantower/Momentum/MacdIndicator.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Diagnostics.Metrics; -using System.Drawing; -using System.Drawing.Drawing2D; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MacdIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Slow EMA", sortIndex: 1, 1, 1000, 1, 0)] - public int Slow { get; set; } = 26; - - [InputParameter("Fast EMA", sortIndex: 2, 1, 2000, 1, 0)] - public int Fast { get; set; } = 12; - - [InputParameter("Signal line", sortIndex: 3, 1, 2000, 1, 0)] - public int Signal { get; set; } = 9; - - [InputParameter("Use SMA for warmup period", sortIndex: 2)] - public bool UseSMA { get; set; } = false; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Macd? macd; - private Slope? histSlope; - protected LineSeries? MainSeries; - protected LineSeries? SignalSeries; - protected LineSeries? HistogramSeries; - protected LineSeries? HistSlopeSeries; - - protected string? SourceName; - public int MinHistoryDepths => Slow; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"MACD {Slow}:{Fast}:{Signal}"; - - public MacdIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "MACD - Moving Average Convergence Divergence"; - Description = "MACD"; - MainSeries = new(name: $"MAIN", color: Color.RoyalBlue, width: 2, style: LineStyle.Solid); - SignalSeries = new(name: $"SIGNAL", color: Color.Red, width: 2, style: LineStyle.Solid); - HistogramSeries = new(name: $"HISTOGRAM", color: Color.White, width: 2, style: LineStyle.Solid); - HistSlopeSeries = new(name: $"SLOPE", color: Color.Transparent, width: 2, style: LineStyle.Solid); - HistSlopeSeries.Visible = false; - - AddLineSeries(MainSeries); - AddLineSeries(SignalSeries); - AddLineSeries(HistogramSeries); - AddLineSeries(HistSlopeSeries); - } - - protected override void OnInit() - { - macd = new(fastPeriod: Fast, slowPeriod: Slow, signalPeriod: Signal); - histSlope = new(2); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - macd!.Calc(input); - - double main = macd.MacdLine; - double signal = macd.SignalLine; - double histogram = macd.Value; - histSlope!.Calc(histogram); - - MainSeries!.SetValue(main); - MainSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - - SignalSeries!.SetValue(signal); - SignalSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - - HistogramSeries!.SetValue(histogram); - HistogramSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - - HistSlopeSeries!.SetValue(histSlope.Value); - HistSlopeSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } -#pragma warning disable CA1416 // Validate platform compatibility - - public override void OnPaintChart(PaintChartEventArgs args) - { - Graphics gr = args.Graphics; - gr.SmoothingMode = SmoothingMode.AntiAlias; - var mainWindow = this.CurrentChart.Windows[args.WindowIndex]; - var converter = mainWindow.CoordinatesConverter; - var clientRect = mainWindow.ClientRectangle; - - gr.SetClip(clientRect); - DateTime leftTime = new[] { converter.GetTime(clientRect.Left), this.HistoricalData.Time(this!.Count - 1) }.Max(); - DateTime rightTime = new[] { converter.GetTime(clientRect.Right), this.HistoricalData.Time(0) }.Min(); - int leftIndex = (int)this.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1; - int rightIndex = (int)this.HistoricalData.GetIndexByTime(rightTime.Ticks); - - for (int i = rightIndex; i < leftIndex; i++) - { - int barX = (int)converter.GetChartX(this.HistoricalData.Time(i)); - int barY = (int)converter.GetChartY(HistogramSeries![i] * 2.0); - int barY0 = (int)converter.GetChartY(0); - int HistBarWidth = this.CurrentChart.BarsWidth - 2; - - Brush lowGreen = new SolidBrush(Color.FromArgb(255, 0, 100, 0)); - Brush highGreen = new SolidBrush(Color.FromArgb(255, 50, 255, 50)); - Brush lowRed = new SolidBrush(Color.FromArgb(255, 100, 0, 0)); - Brush highRed = new SolidBrush(Color.FromArgb(255, 255, 50, 50)); - - if (HistogramSeries[i] > 0) - { - Brush col = HistSlopeSeries![i] > 0 ? highGreen : lowGreen; - gr.FillRectangle(col, barX, barY, HistBarWidth, Math.Abs(barY - barY0)); - } - else - { - Brush col = HistSlopeSeries![i] < 0 ? highRed : lowRed; - gr.FillRectangle(col, barX, barY0, HistBarWidth, Math.Abs(barY0 - barY)); - } - } - - this.PaintSmoothCurve(args, MainSeries!, macd!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.3); - this.PaintSmoothCurve(args, SignalSeries!, macd!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - base.OnPaintChart(args); - } -} - diff --git a/quantower/Momentum/MomIndicator.cs b/quantower/Momentum/MomIndicator.cs deleted file mode 100644 index adcf838a..00000000 --- a/quantower/Momentum/MomIndicator.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MomIndicator : Indicator -{ - [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int Period { get; set; } = 10; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Mom? mom; - protected LineSeries? Series; - protected string? SourceName; - - public override string ShortName => $"MOM({Period})"; - - public MomIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "MOM - Momentum"; - Description = "A basic momentum indicator that measures the change in price over a specified period"; - - Series = new(name: $"MOM({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - mom = new Mom(period: Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = mom!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, mom!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/PmoIndicator.cs b/quantower/Momentum/PmoIndicator.cs deleted file mode 100644 index 1de142e6..00000000 --- a/quantower/Momentum/PmoIndicator.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class PmoIndicator : Indicator -{ - [InputParameter("First Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int Period1 { get; set; } = 35; - - [InputParameter("Second Period", sortIndex: 2, minimum: 1, maximum: 2000, increment: 1)] - public int Period2 { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Pmo? pmo; - protected LineSeries? Series; - protected string? SourceName; - - public override string ShortName => $"PMO({Period1},{Period2})"; - - public PmoIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "PMO - Price Momentum Oscillator"; - Description = "A momentum indicator that uses exponential moving averages of ROC to identify overbought and oversold conditions"; - - Series = new(name: $"PMO({Period1},{Period2})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - pmo = new Pmo(period1: Period1, period2: Period2); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = pmo!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, pmo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/PoIndicator.cs b/quantower/Momentum/PoIndicator.cs deleted file mode 100644 index f6ab642c..00000000 --- a/quantower/Momentum/PoIndicator.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class PoIndicator : Indicator -{ - [InputParameter("Fast Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int FastPeriod { get; set; } = 10; - - [InputParameter("Slow Period", sortIndex: 2, minimum: 1, maximum: 2000, increment: 1)] - public int SlowPeriod { get; set; } = 21; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Po? po; - protected LineSeries? Series; - protected string? SourceName; - - public override string ShortName => $"PO({FastPeriod},{SlowPeriod})"; - - public PoIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "PO - Price Oscillator"; - Description = "A momentum indicator that measures the difference between two moving averages to identify price momentum"; - - Series = new(name: $"PO({FastPeriod},{SlowPeriod})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - if (FastPeriod >= SlowPeriod) - { - FastPeriod = 10; - SlowPeriod = 21; - } - po = new Po(fastPeriod: FastPeriod, slowPeriod: SlowPeriod); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = po!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, po!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/PpoIndicator.cs b/quantower/Momentum/PpoIndicator.cs deleted file mode 100644 index 5ffe39e1..00000000 --- a/quantower/Momentum/PpoIndicator.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class PpoIndicator : Indicator -{ - [InputParameter("Fast Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int FastPeriod { get; set; } = 12; - - [InputParameter("Slow Period", sortIndex: 2, minimum: 1, maximum: 2000, increment: 1)] - public int SlowPeriod { get; set; } = 26; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Ppo? ppo; - protected LineSeries? Series; - protected string? SourceName; - - public override string ShortName => $"PPO({FastPeriod},{SlowPeriod})"; - - public PpoIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "PPO - Percentage Price Oscillator"; - Description = "A momentum indicator that shows the percentage difference between two moving averages"; - - Series = new(name: $"PPO({FastPeriod},{SlowPeriod})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - if (FastPeriod >= SlowPeriod) - { - FastPeriod = 12; - SlowPeriod = 26; - } - ppo = new Ppo(fastPeriod: FastPeriod, slowPeriod: SlowPeriod); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ppo!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, ppo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/RocIndicator.cs b/quantower/Momentum/RocIndicator.cs deleted file mode 100644 index 77ef27b8..00000000 --- a/quantower/Momentum/RocIndicator.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RocIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int Period { get; set; } = 12; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Roc? roc; - protected LineSeries? Series; - protected LineSeries? ZeroLine; - protected string? SourceName; - public int MinHistoryDepths => Math.Max(5, Period * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"ROC({Period})"; - - public RocIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "ROC - Rate of Change"; - Description = "A momentum indicator that measures the percentage change in price over a specified period"; - - Series = new(name: $"ROC({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - ZeroLine = new("Zero", Color.Gray, 1, LineStyle.Dot); - AddLineSeries(Series); - AddLineSeries(ZeroLine); - } - - protected override void OnInit() - { - roc = new Roc(period: Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - if (args.Reason != UpdateReason.NewTick) - return; - - TValue input = this.GetInputValue(args, Source); - TValue result = roc!.Calc(input); - - Series!.SetValue(result.Value); - ZeroLine!.SetValue(0); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, roc!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/TrixIndicator.cs b/quantower/Momentum/TrixIndicator.cs deleted file mode 100644 index eae53f32..00000000 --- a/quantower/Momentum/TrixIndicator.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class TrixIndicator : Indicator -{ - [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int Period { get; set; } = 18; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Trix? trix; - protected LineSeries? Series; - protected string? SourceName; - - public override string ShortName => $"TRIX({Period})"; - - public TrixIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "TRIX - Triple Exponential Average Rate of Change"; - Description = "A momentum oscillator that shows the percentage rate of change of a triple exponentially smoothed moving average"; - - Series = new(name: $"TRIX({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - trix = new Trix(period: Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = trix!.Calc(input); - - Series!.SetValue(result.Value); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, trix!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/VelIndicator.cs b/quantower/Momentum/VelIndicator.cs deleted file mode 100644 index 67b2df2e..00000000 --- a/quantower/Momentum/VelIndicator.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class VelIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Period", sortIndex: 1, minimum: 1, maximum: 2000, increment: 1)] - public int Period { get; set; } = 10; - - [InputParameter("Phase", sortIndex: 2, minimum: -100, maximum: 100, increment: 1)] - public int Phase { get; set; } = 100; - - [InputParameter("Factor", sortIndex: 3, minimum: 0.1, maximum: 0.9, increment: 0.1, decimalPlaces: 2)] - public double Factor { get; set; } = 0.25; - - [InputParameter("Data source", sortIndex: 4, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Vel? vel; - protected LineSeries? Series; - protected LineSeries? ZeroLine; - protected string? SourceName; - public int MinHistoryDepths => Math.Max(5, Period * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public override string ShortName => $"VEL({Period})"; - - public VelIndicator() - { - OnBackGround = true; - SeparateWindow = true; - SourceName = Source.ToString(); - Name = "VEL - Velocity"; - Description = "An enhanced momentum indicator that applies JMA smoothing to momentum calculation"; - - Series = new(name: $"VEL({Period})", color: IndicatorExtensions.Momentum, width: 2, style: LineStyle.Solid); - ZeroLine = new("Zero", Color.Gray, 1, LineStyle.Dot); - AddLineSeries(Series); - AddLineSeries(ZeroLine); - } - - protected override void OnInit() - { - vel = new Vel(period: Period, phase: Phase, factor: Factor); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - if (args.Reason != UpdateReason.NewTick) - return; - - TValue input = this.GetInputValue(args, Source); - TValue result = vel!.Calc(input); - - Series!.SetValue(result.Value); - ZeroLine!.SetValue(0); - Series!.SetMarker(0, Color.Transparent); - } - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, vel!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/VortexIndicator.cs b/quantower/Momentum/VortexIndicator.cs deleted file mode 100644 index 78853f69..00000000 --- a/quantower/Momentum/VortexIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class VortexIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Vortex? vortex; - protected LineSeries? ValueSeries; - protected LineSeries? PlusLine; - protected LineSeries? MinusLine; - protected LineSeries? ZeroLine; - public int MinHistoryDepths => Math.Max(5, Periods * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public VortexIndicator() - { - Name = "VORTEX - Vortex Indicator"; - Description = "A technical indicator consisting of two oscillating lines that identify trend reversals"; - SeparateWindow = true; - - ValueSeries = new($"VORTEX({Periods})", color: IndicatorExtensions.Momentum, 2, LineStyle.Solid); - PlusLine = new($"VI+({Periods})", color: Color.Green, 2, LineStyle.Solid); - MinusLine = new($"VI-({Periods})", color: Color.Red, 2, LineStyle.Solid); - ZeroLine = new("Zero", Color.Gray, 1, LineStyle.Dot); - - AddLineSeries(ValueSeries); - AddLineSeries(PlusLine); - AddLineSeries(MinusLine); - AddLineSeries(ZeroLine); - } - - protected override void OnInit() - { - vortex = new Vortex(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - var result = vortex!.Calc(input); - - ValueSeries!.SetValue(result); - PlusLine!.SetValue(vortex.ViPlus); - MinusLine!.SetValue(vortex.ViMinus); - ZeroLine!.SetValue(0); - - ValueSeries!.SetMarker(0, Color.Transparent); - PlusLine!.SetMarker(0, Color.Transparent); - MinusLine!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"VORTEX({Periods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, ValueSeries!, vortex!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.PaintSmoothCurve(args, PlusLine!, vortex!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - this.PaintSmoothCurve(args, MinusLine!, vortex!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Momentum/_Momentum.csproj b/quantower/Momentum/_Momentum.csproj deleted file mode 100644 index 8a50319a..00000000 --- a/quantower/Momentum/_Momentum.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Momentum - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/quantower/Oscillators/CtiIndicator.cs b/quantower/Oscillators/CtiIndicator.cs deleted file mode 100644 index 51cdb57b..00000000 --- a/quantower/Oscillators/CtiIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using TradingPlatform.BusinessLayer; -using System.Drawing; - -namespace QuanTAlib -{ - public class CtiIndicator : Indicator, IWatchlistIndicator - { - [InputParameter("Period", 0, 1, 100, 1, 0)] - public int Period { get; set; } = 20; - - [InputParameter("Source Type", 1, variants: new object[] - { - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL2", SourceType.HL2, - "OC2", SourceType.OC2, - "OHL3", SourceType.OHL3, - "HLC3", SourceType.HLC3, - "OHLC4", SourceType.OHLC4, - "HLCC4", SourceType.HLCC4 - })] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show Cold Values", 2)] - public bool ShowColdValues { get; set; } = true; - - private Cti? cti; - protected LineSeries? Series; - protected string? SourceName; - public int MinHistoryDepths => Period + 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public CtiIndicator() - { - OnBackGround = false; - SeparateWindow = true; - this.Name = "CTI - Ehler's Correlation Trend Indicator"; - SourceName = Source.ToString(); - this.Description = "A momentum oscillator that measures the correlation between the price and a lagged version of the price."; - Series = new($"CTI {Period}", color: IndicatorExtensions.Oscillators, width: 2, LineStyle.Solid); - AddLineSeries(Series); - } - - protected override void OnInit() - { - cti = new Cti(this.Period); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = cti!.Calc(input); - - Series!.SetValue(result); - Series!.SetMarker(0, Color.Transparent); - } - - public override string ShortName => $"CTI ({Period}:{SourceName})"; - -#pragma warning disable CA1416 // Validate platform compatibility - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, Series!, cti!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.0); - } - } -} diff --git a/quantower/Oscillators/RsiIndicator.cs b/quantower/Oscillators/RsiIndicator.cs deleted file mode 100644 index 0f4fd41d..00000000 --- a/quantower/Oscillators/RsiIndicator.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RsiIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Rsi? rsi; - protected string? SourceName; - protected LineSeries? RsiSeries; - public int MinHistoryDepths => Periods + 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public RsiIndicator() - { - Name = "RSI - Relative Strength Index"; - Description = "Measures the speed and magnitude of recent price changes to evaluate overbought or oversold conditions."; - SeparateWindow = true; - SourceName = Source.ToString(); - RsiSeries = new($"RSI {Periods}", color: IndicatorExtensions.Oscillators, 2, LineStyle.Solid); - AddLineSeries(RsiSeries); - } - - protected override void OnInit() - { - rsi = new Rsi(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - rsi!.Calc(input); - - RsiSeries!.SetValue(rsi.Value); - RsiSeries!.SetMarker(0, Color.Transparent); - } - - public override string ShortName => $"RSI ({Periods}:{SourceName})"; - -#pragma warning disable CA1416 // Validate platform compatibility - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, RsiSeries!, rsi!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Oscillators/RsxIndicator.cs b/quantower/Oscillators/RsxIndicator.cs deleted file mode 100644 index 16fb8d43..00000000 --- a/quantower/Oscillators/RsxIndicator.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RsxIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Rsi Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Rsx? rsx; - protected string? SourceName; - protected LineSeries? RsxSeries; - public int MinHistoryDepths => Period + 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public RsxIndicator() - { - Name = "RSX - Jurik Trend Strengt Index"; - Description = "Measures the speed and magnitude of recent price changes to evaluate overbought or oversold conditions."; - SeparateWindow = true; - SourceName = Source.ToString(); - RsxSeries = new($"RSX {Period}", color: IndicatorExtensions.Oscillators, 2, LineStyle.Solid); - AddLineSeries(RsxSeries); - } - - protected override void OnInit() - { - rsx = new(Period); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - rsx!.Calc(input); - - RsxSeries!.SetValue(rsx.Value); - RsxSeries!.SetMarker(0, Color.Transparent); - } - - public override string ShortName => $"RSX ({Period}:{SourceName})"; - -#pragma warning disable CA1416 // Validate platform compatibility - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintSmoothCurve(args, RsxSeries!, rsx!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Oscillators/_Oscillators.csproj b/quantower/Oscillators/_Oscillators.csproj deleted file mode 100644 index 67da1dbe..00000000 --- a/quantower/Oscillators/_Oscillators.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Oscillators - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/quantower/Statistics/CurvatureIndicator.cs b/quantower/Statistics/CurvatureIndicator.cs deleted file mode 100644 index 7bade979..00000000 --- a/quantower/Statistics/CurvatureIndicator.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class CurvatureIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 3, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Curvature? curvature; - protected LineSeries? CurvatureSeries; - protected LineSeries? LineSeries; - protected string? SourceName; - public int MinHistoryDepths => (Periods * 2) - 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public CurvatureIndicator() - { - Name = "Curvature"; - Description = "Calculates the rate of change of the slope over a specified period"; - SeparateWindow = true; - SourceName = Source.ToString(); - - CurvatureSeries = new("Curvature", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(CurvatureSeries); - } - - protected override void OnInit() - { - curvature = new Curvature(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = curvature!.Calc(input); - - CurvatureSeries!.SetValue(result.Value); - if (curvature.Line.HasValue) - { - LineSeries!.SetValue(curvature.Line.Value); - } - } - - public override string ShortName => $"Curvature ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/EntropyIndicator.cs b/quantower/Statistics/EntropyIndicator.cs deleted file mode 100644 index cea46fa5..00000000 --- a/quantower/Statistics/EntropyIndicator.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; -namespace QuanTAlib; - -public class EntropyIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Entropy? entropy; - protected LineSeries? EntropySeries; - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public EntropyIndicator() - { - Name = "Entropy"; - Description = "Measures the unpredictability of data using Shannon's Entropy"; - SeparateWindow = true; - SourceName = Source.ToString(); - - EntropySeries = new("Entropy", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(EntropySeries); - } - - protected override void OnInit() - { - entropy = new Entropy(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = entropy!.Calc(input); - - EntropySeries!.SetValue(result.Value); - } - - public override string ShortName => $"Entropy ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/KurtosisIndicator.cs b/quantower/Statistics/KurtosisIndicator.cs deleted file mode 100644 index 4e8a0e3d..00000000 --- a/quantower/Statistics/KurtosisIndicator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class KurtosisIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 4, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Kurtosis? kurtosis; - protected LineSeries? KurtosisSeries; - protected string? SourceName; - public int MinHistoryDepths => Periods - 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public KurtosisIndicator() - { - Name = "Kurtosis"; - Description = "Measures the 'tailedness' of the probability distribution of a real-valued random variable"; - SeparateWindow = true; - SourceName = Source.ToString(); - - KurtosisSeries = new("Kurtosis", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(KurtosisSeries); - } - - protected override void OnInit() - { - kurtosis = new Kurtosis(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = kurtosis!.Calc(input); - - KurtosisSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Kurtosis ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/MaxIndicator.cs b/quantower/Statistics/MaxIndicator.cs deleted file mode 100644 index ee5edb0f..00000000 --- a/quantower/Statistics/MaxIndicator.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MaxIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Decay", sortIndex: 2, 0, 10, 0.01, 2)] - public double Decay { get; set; } = 0; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.High; - - private Max? ma; - protected LineSeries? MaxSeries; - protected string? SourceName; - public static int MinHistoryDepths => 0; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public MaxIndicator() - { - Name = "Max"; - Description = "Calculates the maximum value over a specified period, with an optional decay factor"; - SeparateWindow = false; - SourceName = Source.ToString(); - - MaxSeries = new("Max", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(MaxSeries); - } - - protected override void OnInit() - { - ma = new Max(Periods, Decay); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = ma!.Calc(input); - - MaxSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Max ({Periods}, {Decay:F2}:{SourceName})"; -} diff --git a/quantower/Statistics/MedianIndicator.cs b/quantower/Statistics/MedianIndicator.cs deleted file mode 100644 index c2195066..00000000 --- a/quantower/Statistics/MedianIndicator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MedianIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Median? med; - protected LineSeries? MedianSeries; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public MedianIndicator() - { - Name = "Median"; - Description = "Calculates the median value over a specified period"; - SeparateWindow = false; - SourceName = Source.ToString(); - - MedianSeries = new("Median", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(MedianSeries); - } - - protected override void OnInit() - { - med = new Median(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = med!.Calc(input); - - MedianSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Median ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/MinIndicator.cs b/quantower/Statistics/MinIndicator.cs deleted file mode 100644 index e7545a57..00000000 --- a/quantower/Statistics/MinIndicator.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class MinIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Decay", sortIndex: 2, 0, 10, 0.01, 2)] - public double Decay { get; set; } = 0; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Low; - - private Min? mi; - protected LineSeries? MinSeries; - protected string? SourceName; - public static int MinHistoryDepths => 0; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public MinIndicator() - { - Name = "Min"; - Description = "Calculates the minimum value over a specified period, with an optional decay factor"; - SeparateWindow = false; - SourceName = Source.ToString(); - - MinSeries = new("Min", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(MinSeries); - } - - protected override void OnInit() - { - mi = new Min(Periods, Decay); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = mi!.Calc(input); - - MinSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Min ({Periods}, {Decay:F2}:{SourceName})"; -} diff --git a/quantower/Statistics/ModeIndicator.cs b/quantower/Statistics/ModeIndicator.cs deleted file mode 100644 index 2df23e93..00000000 --- a/quantower/Statistics/ModeIndicator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class ModeIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Mode? mode; - protected LineSeries? ModeSeries; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public ModeIndicator() - { - Name = "Mode"; - Description = "Calculates the most frequent value in a specified period"; - SeparateWindow = false; - SourceName = Source.ToString(); - - ModeSeries = new("Mode", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(ModeSeries); - } - - protected override void OnInit() - { - mode = new Mode(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = mode!.Calc(input); - - ModeSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Mode ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/PercentileIndicator.cs b/quantower/Statistics/PercentileIndicator.cs deleted file mode 100644 index 96c1cf65..00000000 --- a/quantower/Statistics/PercentileIndicator.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class PercentileIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Percentile", sortIndex: 2, 0, 100, 0.1, 1)] - public double PercentileValue { get; set; } = 50; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Percentile? percentile; - protected LineSeries? PercentileSeries; - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public PercentileIndicator() - { - Name = "Percentile"; - Description = "Calculates the value at a specified percentile in a given period of data points"; - SeparateWindow = false; - SourceName = Source.ToString(); - - PercentileSeries = new("Percentile", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(PercentileSeries); - } - - protected override void OnInit() - { - percentile = new Percentile(Periods, PercentileValue); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = percentile!.Calc(input); - - PercentileSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Percentile ({Periods}, {PercentileValue}%:{SourceName})"; -} diff --git a/quantower/Statistics/SkewIndicator.cs b/quantower/Statistics/SkewIndicator.cs deleted file mode 100644 index decd7444..00000000 --- a/quantower/Statistics/SkewIndicator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class SkewIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 3, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Skew? skew; - protected LineSeries? SkewSeries; - protected string? SourceName; - public static int MinHistoryDepths => 3; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public SkewIndicator() - { - Name = "Skew"; - Description = "Measures the asymmetry of the probability distribution of a real-valued random variable about its mean"; - SeparateWindow = true; - SourceName = Source.ToString(); - - SkewSeries = new("Skew", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(SkewSeries); - } - - protected override void OnInit() - { - skew = new Skew(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = skew!.Calc(input); - - SkewSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Skew ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/SlopeIndicator.cs b/quantower/Statistics/SlopeIndicator.cs deleted file mode 100644 index e5534d7c..00000000 --- a/quantower/Statistics/SlopeIndicator.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class SlopeIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Slope? slope; - protected LineSeries? SlopeSeries; - protected LineSeries? LineSeries; - protected string? SourceName; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public SlopeIndicator() - { - Name = "Slope"; - Description = "Calculates the slope of a linear regression line for the specified period"; - SeparateWindow = true; - SourceName = Source.ToString(); - - SlopeSeries = new("Slope", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - LineSeries = new("Regression Line", Color.Red, 1, LineStyle.Solid); - AddLineSeries(SlopeSeries); - AddLineSeries(LineSeries); - } - - protected override void OnInit() - { - slope = new Slope(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = slope!.Calc(input); - - SlopeSeries!.SetValue(result.Value); - if (slope.Line.HasValue) - { - LineSeries!.SetValue(slope.Line.Value); - } - } - - public override string ShortName - { - get - { - var result = $"Slope ({Periods}:{SourceName})"; - if (slope != null) - { - result += $" Slope: {Math.Round(SlopeSeries!.GetValue(), 6)}"; - if (slope.Line.HasValue) - result += $", Line: {Math.Round(slope.Line.Value, 6)}"; - if (slope.Intercept.HasValue) - result += $", Intercept: {Math.Round(slope.Intercept.Value, 6)}"; - if (slope.RSquared.HasValue) - result += $", R²: {Math.Round(slope.RSquared.Value, 6)}"; - } - return result; - } - } -} diff --git a/quantower/Statistics/StddevIndicator.cs b/quantower/Statistics/StddevIndicator.cs deleted file mode 100644 index 02d5f57a..00000000 --- a/quantower/Statistics/StddevIndicator.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class StddevIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Population", sortIndex: 2)] - public bool IsPopulation { get; set; } = false; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Stddev? stddev; - protected LineSeries? StddevSeries; - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public StddevIndicator() - { - Name = "Standard Deviation"; - Description = "Measures the amount of variation or dispersion of a set of values"; - SeparateWindow = true; - SourceName = Source.ToString(); - - StddevSeries = new("StdDev", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(StddevSeries); - } - - protected override void OnInit() - { - stddev = new Stddev(Periods, IsPopulation); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = stddev!.Calc(input); - - StddevSeries!.SetValue(result.Value); - } - - public override string ShortName => $"StdDev ({Periods}, {(IsPopulation ? "Pop" : "Sample")}:{SourceName})"; -} diff --git a/quantower/Statistics/VarianceIndicator.cs b/quantower/Statistics/VarianceIndicator.cs deleted file mode 100644 index 5f3511f9..00000000 --- a/quantower/Statistics/VarianceIndicator.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class VarianceIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 1000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Population", sortIndex: 2)] - public bool IsPopulation { get; set; } = false; - - [InputParameter("Data source", sortIndex: 3, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Variance? variance; - protected LineSeries? VarianceSeries; - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public VarianceIndicator() - { - Name = "Variance"; - Description = "Measures the spread of a set of numbers from their average value"; - SeparateWindow = true; - SourceName = Source.ToString(); - - VarianceSeries = new("Variance", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(VarianceSeries); - } - - protected override void OnInit() - { - variance = new Variance(Periods, IsPopulation); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = variance!.Calc(input); - - VarianceSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Variance ({Periods}, {(IsPopulation ? "Pop" : "Sample")}:{SourceName})"; -} diff --git a/quantower/Statistics/ZscoreIndicator.cs b/quantower/Statistics/ZscoreIndicator.cs deleted file mode 100644 index ba70a8a5..00000000 --- a/quantower/Statistics/ZscoreIndicator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class ZscoreIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 2000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Data source", sortIndex: 2, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Zscore? zScore; - protected LineSeries? ZscoreSeries; - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public ZscoreIndicator() - { - Name = "Z-Score"; - Description = "Measures how many standard deviations a price is from the mean, indicating overbought/oversold levels."; - SeparateWindow = true; - SourceName = Source.ToString(); - - ZscoreSeries = new("Z-Score", color: IndicatorExtensions.Statistics, 2, LineStyle.Solid); - AddLineSeries(ZscoreSeries); - } - - protected override void OnInit() - { - zScore = new Zscore(Periods); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - TValue result = zScore!.Calc(input); - - ZscoreSeries!.SetValue(result.Value); - } - - public override string ShortName => $"Z-Score ({Periods}:{SourceName})"; -} diff --git a/quantower/Statistics/_Statistics.csproj b/quantower/Statistics/_Statistics.csproj deleted file mode 100644 index b4c639d9..00000000 --- a/quantower/Statistics/_Statistics.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Statistics - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/quantower/Volatility/AtrIndicator.cs b/quantower/Volatility/AtrIndicator.cs deleted file mode 100644 index 0999533a..00000000 --- a/quantower/Volatility/AtrIndicator.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class AtrIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Atr? atr; - protected LineSeries? AtrSeries; - public int MinHistoryDepths => Math.Max(5, Periods * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public AtrIndicator() - { - Name = "ATR - Average True Range"; - Description = "Measures market volatility by calculating the average range between high and low prices."; - SeparateWindow = true; - - AtrSeries = new($"ATR {Periods}", Color.Blue, 2, LineStyle.Solid); - AddLineSeries(AtrSeries); - } - - protected override void OnInit() - { - atr = new Atr(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = atr!.Calc(input); - - AtrSeries!.SetValue(result.Value); - AtrSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"ATR ({Periods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintHLine(args, 0.05, new Pen(color: IndicatorExtensions.Volatility, width: 2)); - this.PaintSmoothCurve(args, AtrSeries!, atr!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Volatility/CmoIndicator.cs b/quantower/Volatility/CmoIndicator.cs deleted file mode 100644 index a507d652..00000000 --- a/quantower/Volatility/CmoIndicator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class CmoIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 9; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Cmo? cmo; - protected string? SourceName; - protected LineSeries? CmoSeries; - public int MinHistoryDepths => Periods + 1; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - - public CmoIndicator() - { - Name = "CMO - Chande Momentum Oscillator"; - Description = "Measures the momentum of price changes using the difference between the sum of recent gains and the sum of recent losses."; - SeparateWindow = true; - SourceName = Source.ToString(); - CmoSeries = new($"CMO {Periods}", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(CmoSeries); - } - - protected override void OnInit() - { - cmo = new Cmo(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - cmo!.Calc(input); - - CmoSeries!.SetValue(cmo.Value); - CmoSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - - public override string ShortName => $"CMO ({Periods}:{SourceName})"; - -#pragma warning disable CA1416 // Validate platform compatibility - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintHLine(args, 0, new Pen(Color.DarkGray, width: 1)); - this.PaintHLine(args, 50, new Pen(Color.Blue, width: 1)); - this.PaintHLine(args, -50, new Pen(Color.Blue, width: 1)); - this.PaintSmoothCurve(args, CmoSeries!, cmo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Volatility/CviIndicator.cs b/quantower/Volatility/CviIndicator.cs deleted file mode 100644 index be14de29..00000000 --- a/quantower/Volatility/CviIndicator.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class CviIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Cvi? cvi; - protected LineSeries? CviSeries; - public int MinHistoryDepths => Math.Max(5, Periods * 2); - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public CviIndicator() - { - Name = "CVI - Chaikin's Volatility"; - Description = "Measures the volatility of a financial instrument by comparing the spread between the high and low prices."; - SeparateWindow = true; - - CviSeries = new($"CVI {Periods}", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(CviSeries); - } - - protected override void OnInit() - { - cvi = new Cvi(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = cvi!.Calc(input); - - CviSeries!.SetValue(result.Value); - CviSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => $"CVI ({Periods})"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintHLine(args, 0.05, new Pen(color: IndicatorExtensions.Volatility, width: 2)); - this.PaintSmoothCurve(args, CviSeries!, cvi!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Volatility/HistoricalIndicator.cs b/quantower/Volatility/HistoricalIndicator.cs deleted file mode 100644 index 9637679f..00000000 --- a/quantower/Volatility/HistoricalIndicator.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class HistoricalIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Annualized", sortIndex: 2)] - public bool IsAnnualized { get; set; } = true; - - private Hv? historical; - protected LineSeries? HvSeries; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public HistoricalIndicator() - { - Name = "HV - Historical Volatility"; - Description = "Measures price fluctuations over time, indicating market volatility based on past price movements."; - SeparateWindow = true; - - HvSeries = new("HV", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(HvSeries); - } - - protected override void OnInit() - { - historical = new(Periods, IsAnnualized); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = historical!.Calc(input); - - HvSeries!.SetValue(result.Value); - } - - public override string ShortName => $"HV ({Periods}{(IsAnnualized ? " - Annualized" : "")})"; -} diff --git a/quantower/Volatility/JbandsIndicator.cs b/quantower/Volatility/JbandsIndicator.cs deleted file mode 100644 index e977bb63..00000000 --- a/quantower/Volatility/JbandsIndicator.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class JbandsIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - [InputParameter("vShort", sortIndex: 6, -100, 100, 1, 0)] - public int Phase { get; set; } = 10; - - private Jma? jmaUp; - private Jma? jmaLo; - protected LineSeries? UbSeries; - protected LineSeries? LbSeries; - protected string? SourceName; - public static int MinHistoryDepths => 2; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public JbandsIndicator() - { - Name = "JBANDS - Mark Jurik's Bands"; - Description = "Upper and Lower Bands."; - SeparateWindow = false; - - UbSeries = new("UB", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - LbSeries = new("LB", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(UbSeries); - AddLineSeries(LbSeries); - } - - protected override void OnInit() - { - jmaUp = new(Periods, phase: Phase); - jmaLo = new(Periods, phase: Phase); - SourceName = Source.ToString(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - jmaUp!.Calc(input.High); - jmaLo!.Calc(input.Low); - - UbSeries!.SetValue(jmaUp.UpperBand); - LbSeries!.SetValue(jmaLo.LowerBand); - } - - public override string ShortName => $"JBands ({Periods}:{Phase})"; -} diff --git a/quantower/Volatility/JvoltyIndicator.cs b/quantower/Volatility/JvoltyIndicator.cs deleted file mode 100644 index c3e5146a..00000000 --- a/quantower/Volatility/JvoltyIndicator.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class JvoltyIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 14; - - [InputParameter("Data source", sortIndex: 5, variants: [ - "Open", SourceType.Open, - "High", SourceType.High, - "Low", SourceType.Low, - "Close", SourceType.Close, - "HL/2 (Median)", SourceType.HL2, - "OC/2 (Midpoint)", SourceType.OC2, - "OHL/3 (Mean)", SourceType.OHL3, - "HLC/3 (Typical)", SourceType.HLC3, - "OHLC/4 (Average)", SourceType.OHLC4, - "HLCC/4 (Weighted)", SourceType.HLCC4 - ])] - public SourceType Source { get; set; } = SourceType.Close; - - private Jma? jma; - protected LineSeries? JvoltySeries; - public static int MinHistoryDepths => 2; - - - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public JvoltyIndicator() - { - Name = "JVOLTY - Mark Jurik's Volatility"; - Description = "Measures market volatility according to Mark Jurik."; - SeparateWindow = true; - - JvoltySeries = new("JVOLTY", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(JvoltySeries); - } - - protected override void OnInit() - { - jma = new(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TValue input = this.GetInputValue(args, Source); - jma!.Calc(input); - - JvoltySeries!.SetValue(jma.Volty); - } - - public override string ShortName => $"JVOLTY ({Periods})"; -} diff --git a/quantower/Volatility/RealizedIndicator.cs b/quantower/Volatility/RealizedIndicator.cs deleted file mode 100644 index 661626f5..00000000 --- a/quantower/Volatility/RealizedIndicator.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RealizedIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] - public int Periods { get; set; } = 20; - - [InputParameter("Annualized", sortIndex: 2)] - public bool IsAnnualized { get; set; } = true; - - private Rv? realized; - protected LineSeries? RvSeries; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public RealizedIndicator() - { - Name = "RV - Realized Volatility"; - Description = "Measures actual price volatility over a specific period, useful for risk assessment and forecasting."; - SeparateWindow = true; - - RvSeries = new("RV", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(RvSeries); - } - - protected override void OnInit() - { - realized = new(Periods, IsAnnualized); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = realized!.Calc(input); - - RvSeries!.SetValue(result.Value); - } - - public override string ShortName => $"RV ({Periods}{(IsAnnualized ? " - Annualized" : "")})"; -} diff --git a/quantower/Volatility/RviIndicator.cs b/quantower/Volatility/RviIndicator.cs deleted file mode 100644 index 516f4ac6..00000000 --- a/quantower/Volatility/RviIndicator.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class RviIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Periods", sortIndex: 1, 2, 100, 1, 0)] - public int Periods { get; set; } = 10; - - private Rvi? rvi; - protected LineSeries? RviSeries; - public int MinHistoryDepths => Periods; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public RviIndicator() - { - Name = "RVI - Relative Volatility Index"; - Description = "Measures the direction of volatility, helping to identify overbought or oversold conditions in price."; - SeparateWindow = true; - - RviSeries = new("RVI", color: IndicatorExtensions.Volatility, 2, LineStyle.Solid); - AddLineSeries(RviSeries); - } - - protected override void OnInit() - { - rvi = new Rvi(Periods); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = rvi!.Calc(input); - - RviSeries!.SetValue(result.Value); - } - - public override string ShortName => $"RVI ({Periods})"; -} diff --git a/quantower/Volatility/_Volatility.csproj b/quantower/Volatility/_Volatility.csproj deleted file mode 100644 index c6badb70..00000000 --- a/quantower/Volatility/_Volatility.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Volatility - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/quantower/Volume/ObvIndicator.cs b/quantower/Volume/ObvIndicator.cs deleted file mode 100644 index bbbdb89b..00000000 --- a/quantower/Volume/ObvIndicator.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Drawing; -using TradingPlatform.BusinessLayer; - -namespace QuanTAlib; - -public class ObvIndicator : Indicator, IWatchlistIndicator -{ - [InputParameter("Show cold values", sortIndex: 21)] - public bool ShowColdValues { get; set; } = true; - - private Obv? obv; - protected LineSeries? ObvSeries; - public int MinHistoryDepths => 5; - int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - - public ObvIndicator() - { - Name = "OBV - On-Balance Volume"; - Description = "Measures buying and selling pressure by analyzing volume in relation to price changes."; - SeparateWindow = true; - - ObvSeries = new("OBV", color: IndicatorExtensions.Volume, 2, LineStyle.Solid); - AddLineSeries(ObvSeries); - } - - protected override void OnInit() - { - obv = new Obv(); - base.OnInit(); - } - - protected override void OnUpdate(UpdateArgs args) - { - TBar input = IndicatorExtensions.GetInputBar(this, args); - TValue result = obv!.Calc(input); - - ObvSeries!.SetValue(result.Value); - ObvSeries!.SetMarker(0, Color.Transparent); - } - -#pragma warning disable CA1416 // Validate platform compatibility - - public override string ShortName => "OBV"; - - public override void OnPaintChart(PaintChartEventArgs args) - { - base.OnPaintChart(args); - this.PaintHLine(args, 0, new Pen(color: Color.DimGray, width: 1)); - this.PaintSmoothCurve(args, ObvSeries!, obv!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); - } -} diff --git a/quantower/Volume/_Volume.csproj b/quantower/Volume/_Volume.csproj deleted file mode 100644 index 9443c8f6..00000000 --- a/quantower/Volume/_Volume.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Volume - Indicator - bin\$(Configuration)\ - false - - - - - - - - - - - - - ..\..\.github\TradingPlatform.BusinessLayer.dll - - - TradingPlatform.BusinessLayer.xml - - - - - - - - diff --git a/tests/QuanTAlib.Tests/CsvFeedTests.cs b/tests/QuanTAlib.Tests/CsvFeedTests.cs new file mode 100644 index 00000000..b2ccb9ab --- /dev/null +++ b/tests/QuanTAlib.Tests/CsvFeedTests.cs @@ -0,0 +1,254 @@ +using Xunit; + +namespace QuanTAlib.Tests; + +public class CsvFeedTests +{ + private const string TestCsvPath = "daily_IBM.csv"; + + [Fact] + public void Constructor_ValidFile_LoadsData() + { + var feed = new CsvFeed(TestCsvPath); + Assert.NotNull(feed); + } + + [Fact] + public void Constructor_NonExistentFile_ThrowsFileNotFoundException() + { + Assert.Throws(() => new CsvFeed("nonexistent.csv")); + } + + [Fact] + public void Constructor_NullPath_ThrowsArgumentException() + { + Assert.Throws(() => new CsvFeed(null!)); + } + + [Fact] + public void Constructor_EmptyPath_ThrowsArgumentException() + { + Assert.Throws(() => new CsvFeed("")); + } + + [Fact] + public void Next_StreamsDataChronologically() + { + var feed = new CsvFeed(TestCsvPath); + + // Get first bar + var bar1 = feed.Next(isNew: true); + Assert.True(bar1.Time > 0); + + // Get second bar - should be later in time + var bar2 = feed.Next(isNew: true); + Assert.True(bar2.Time > bar1.Time); + + // Get third bar + var bar3 = feed.Next(isNew: true); + Assert.True(bar3.Time > bar2.Time); + } + + [Fact] + public void Next_WithRefParameter_StreamsCorrectly() + { + var feed = new CsvFeed(TestCsvPath); + + bool isNew = true; + var bar1 = feed.Next(ref isNew); + Assert.True(isNew); // Should still be true + Assert.True(bar1.Time > 0); + + isNew = true; + var bar2 = feed.Next(ref isNew); + Assert.True(isNew); + Assert.True(bar2.Time > bar1.Time); + } + + [Fact] + public void Next_UpdateCurrentBar_ReturnsSameBar() + { + var feed = new CsvFeed(TestCsvPath); + + // Get first bar + var bar1 = feed.Next(isNew: true); + + // Update current bar (should return same bar) + var bar2 = feed.Next(isNew: false); + Assert.Equal(bar1.Time, bar2.Time); + Assert.Equal(bar1.Close, bar2.Close); + + // Get next bar + var bar3 = feed.Next(isNew: true); + Assert.True(bar3.Time > bar1.Time); + } + + [Fact] + public void Next_EndOfData_SignalsNoMoreData() + { + var feed = new CsvFeed(TestCsvPath); + + // Stream through all data + TBar lastBar = default; + bool isNew = true; + int count = 0; + + while (isNew && count < 200) // Safety limit + { + lastBar = feed.Next(ref isNew); + count++; + } + + // Should have reached end and isNew should be false + Assert.False(isNew); + Assert.True(lastBar.Time > 0); + + // Calling again should return same bar with isNew=false + isNew = true; + var finalBar = feed.Next(ref isNew); + Assert.False(isNew); + Assert.Equal(lastBar.Time, finalBar.Time); + } + + [Fact] + public void Fetch_ReturnsCorrectNumberOfBars() + { + var feed = new CsvFeed(TestCsvPath); + + var startTime = new DateTime(2025, 7, 1, 0, 0, 0, DateTimeKind.Utc).Ticks; + var interval = TimeSpan.FromDays(1); + + var series = feed.Fetch(10, startTime, interval); + + Assert.True(series.Count > 0); + Assert.True(series.Count <= 10); + } + + [Fact] + public void Fetch_InvalidCount_ThrowsArgumentException() + { + var feed = new CsvFeed(TestCsvPath); + + var startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromDays(1); + + Assert.Throws(() => feed.Fetch(0, startTime, interval)); + Assert.Throws(() => feed.Fetch(-1, startTime, interval)); + } + + [Fact] + public void Fetch_ResetsStreamingPosition() + { + var feed = new CsvFeed(TestCsvPath); + + // Stream a few bars + feed.Next(isNew: true); + feed.Next(isNew: true); + feed.Next(isNew: true); + + // Fetch from start + var startTime = new DateTime(2025, 7, 1, 0, 0, 0, DateTimeKind.Utc).Ticks; + var series = feed.Fetch(5, startTime, TimeSpan.FromDays(1)); + + // Next should now stream from fetched position + var bar = feed.Next(isNew: true); + Assert.True(bar.Time >= startTime); + } + + [Fact] + public void LoadFromCsv_ParsesValuesCorrectly() + { + var feed = new CsvFeed(TestCsvPath); + + // Get first bar (oldest in chronological order) + var bar = feed.Next(isNew: true); + + // Verify it has valid OHLCV data + Assert.True(bar.Open > 0); + Assert.True(bar.High >= bar.Open); + Assert.True(bar.High >= bar.Close); + Assert.True(bar.Low <= bar.Open); + Assert.True(bar.Low <= bar.Close); + Assert.True(bar.Close > 0); + Assert.True(bar.Volume > 0); + } + + [Fact] + public void LoadFromCsv_DataInChronologicalOrder() + { + var feed = new CsvFeed(TestCsvPath); + + var bars = new List(); + bool isNew = true; + + // Collect first 10 bars + for (int i = 0; i < 10 && isNew; i++) + { + bars.Add(feed.Next(ref isNew)); + } + + // Verify chronological order (each bar later than previous) + for (int i = 1; i < bars.Count; i++) + { + Assert.True(bars[i].Time > bars[i - 1].Time, + $"Bar {i} time ({bars[i].AsDateTime}) should be after bar {i-1} time ({bars[i-1].AsDateTime})"); + } + } + + [Fact] + public void CsvFeed_WorksWithIFeedInterface() + { + IFeed feed = new CsvFeed(TestCsvPath); + + var bar1 = feed.Next(isNew: true); + Assert.True(bar1.Time > 0); + + var bar2 = feed.Next(isNew: true); + Assert.True(bar2.Time > bar1.Time); + } + + [Fact] + public void Next_MixedNewAndUpdate_WorksCorrectly() + { + var feed = new CsvFeed(TestCsvPath); + + var bar1 = feed.Next(isNew: true); + var bar1Update = feed.Next(isNew: false); + Assert.Equal(bar1.Time, bar1Update.Time); + + var bar2 = feed.Next(isNew: true); + Assert.True(bar2.Time > bar1.Time); + + var bar2Update = feed.Next(isNew: false); + Assert.Equal(bar2.Time, bar2Update.Time); + + var bar3 = feed.Next(isNew: true); + Assert.True(bar3.Time > bar2.Time); + } + + [Fact] + public void Fetch_WithEarlyStartTime_ReturnsData() + { + var feed = new CsvFeed(TestCsvPath); + + // Start from very early date (before any data) + var startTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks; + var series = feed.Fetch(5, startTime, TimeSpan.FromDays(1)); + + // Should return data starting from first available bar + Assert.True(series.Count > 0); + } + + [Fact] + public void Fetch_WithFutureStartTime_ReturnsEmpty() + { + var feed = new CsvFeed(TestCsvPath); + + // Start from future date (after all data) + var startTime = new DateTime(2030, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks; + var series = feed.Fetch(5, startTime, TimeSpan.FromDays(1)); + + // Should return empty or minimal data + Assert.True(series.Count == 0); + } +} diff --git a/tests/QuanTAlib.Tests/GBMTests.cs b/tests/QuanTAlib.Tests/GBMTests.cs new file mode 100644 index 00000000..cc7bb48f --- /dev/null +++ b/tests/QuanTAlib.Tests/GBMTests.cs @@ -0,0 +1,283 @@ +using System; +using Xunit; +using QuanTAlib; + +namespace QuanTAlib.Tests; + +public class GBMTests +{ + [Fact] + public void Next_DefaultParameter_GeneratesNewBar() + { + var gbm = new GBM(startPrice: 100.0); + + var bar1 = gbm.Next(); + var bar2 = gbm.Next(); + + Assert.NotEqual(bar1.Time, bar2.Time); + Assert.True(bar2.Time > bar1.Time); + } + + [Fact] + public void Next_IsNewTrue_AdvancesToNewBar() + { + var gbm = new GBM(startPrice: 100.0); + + var bar1 = gbm.Next(isNew: true); + var bar2 = gbm.Next(isNew: true); + + Assert.NotEqual(bar1.Time, bar2.Time); + Assert.True(bar2.Time > bar1.Time); + } + + [Fact] + public void Next_IsNewFalse_UpdatesCurrentBar() + { + var gbm = new GBM(startPrice: 100.0); + + var bar1 = gbm.Next(isNew: true); + long initialTime = bar1.Time; + + var bar2 = gbm.Next(isNew: false); + + Assert.Equal(initialTime, bar2.Time); + // Price likely changed (GBM random walk) + Assert.NotEqual(bar1.Close, bar2.Close); + } + + [Fact] + public void Next_RefBool_HonorsRequest() + { + var gbm = new GBM(startPrice: 100.0); + + // GBM always honors isNew - parameter should remain unchanged + bool isNew1 = true; + var bar1 = gbm.Next(ref isNew1); + Assert.True(isNew1, "GBM should honor isNew=true request"); + + bool isNew2 = false; + long time1 = bar1.Time; + var bar2 = gbm.Next(ref isNew2); + Assert.False(isNew2, "GBM should honor isNew=false request"); + Assert.Equal(time1, bar2.Time); + + bool isNew3 = true; + var bar3 = gbm.Next(ref isNew3); + Assert.True(isNew3, "GBM should honor isNew=true request"); + Assert.NotEqual(time1, bar3.Time); + } + + [Fact] + public void Fetch_GeneratesCorrectCount() + { + var gbm = new GBM(startPrice: 100.0); + int count = 10; + long startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromMinutes(1); + + var series = gbm.Fetch(count, startTime, interval); + + Assert.Equal(count, series.Count); + } + + [Fact] + public void Fetch_GeneratesSequentialBars() + { + var gbm = new GBM(startPrice: 100.0); + long startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromMinutes(1); + + var series = gbm.Fetch(5, startTime, interval); + + // Verify time sequence + for (int i = 1; i < series.Count; i++) + { + Assert.True(series[i].Time > series[i - 1].Time); + } + } + + [Fact] + public void Fetch_RespectsInterval() + { + var gbm = new GBM(startPrice: 100.0); + var interval = TimeSpan.FromHours(1); + long startTime = DateTime.UtcNow.Ticks; + + var series = gbm.Fetch(5, startTime, interval); + + // Verify interval spacing + for (int i = 1; i < series.Count; i++) + { + long expectedDiff = interval.Ticks; + long actualDiff = series[i].Time - series[i - 1].Time; + Assert.Equal(expectedDiff, actualDiff); + } + } + + [Fact] + public void Fetch_StartsAtSpecifiedTime() + { + var gbm = new GBM(startPrice: 100.0); + var startTime = new DateTime(2024, 1, 1, 9, 30, 0, DateTimeKind.Utc).Ticks; + var interval = TimeSpan.FromMinutes(5); + + var series = gbm.Fetch(3, startTime, interval); + + Assert.Equal(startTime, series[0].Time); + Assert.Equal(startTime + interval.Ticks, series[1].Time); + Assert.Equal(startTime + 2 * interval.Ticks, series[2].Time); + } + + [Fact] + public void Fetch_WithDifferentIntervals_WorksCorrectly() + { + var gbm = new GBM(startPrice: 100.0); + long startTime = DateTime.UtcNow.Ticks; + + // Test different intervals + var intervals = new[] { + TimeSpan.FromMinutes(1), + TimeSpan.FromMinutes(5), + TimeSpan.FromHours(1) + }; + + foreach (var interval in intervals) + { + var series = gbm.Fetch(3, startTime, interval); + + // Verify spacing + for (int i = 1; i < series.Count; i++) + { + long expectedDiff = interval.Ticks; + long actualDiff = series[i].Time - series[i - 1].Time; + Assert.Equal(expectedDiff, actualDiff); + } + } + } + + [Fact] + public void GeneratesRealisticOHLCV() + { + var gbm = new GBM(startPrice: 100.0); + long startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromMinutes(1); + var series = gbm.Fetch(10, startTime, interval); + + for (int i = 0; i < series.Count; i++) + { + var bar = series[i]; + + // High should be >= max(Open, Close) + Assert.True(bar.High >= Math.Max(bar.Open, bar.Close)); + + // Low should be <= min(Open, Close) + Assert.True(bar.Low <= Math.Min(bar.Open, bar.Close)); + + // Volume should be positive + Assert.True(bar.Volume > 0); + + // All prices should be positive + Assert.True(bar.Open > 0); + Assert.True(bar.High > 0); + Assert.True(bar.Low > 0); + Assert.True(bar.Close > 0); + } + } + + [Fact] + public void IntraBarUpdates_ModifyCurrentBar() + { + var gbm = new GBM(startPrice: 100.0); + + var bar1 = gbm.Next(isNew: true); + long initialTime = bar1.Time; + double initialClose = bar1.Close; + + // Loop until price changes (random walk might stay same but unlikely) + bool changed = false; + for (int i = 0; i < 10; i++) + { + var bar = gbm.Next(isNew: false); + Assert.Equal(initialTime, bar.Time); + if (Math.Abs(bar.Close - initialClose) > double.Epsilon) + { + changed = true; + break; + } + } + + Assert.True(changed, "Price should change during intra-bar updates"); + } + + [Fact] + public void MixedStreamingAndBatch_WorksCorrectly() + { + var gbm = new GBM(startPrice: 100.0); + + // Start with streaming + var bar1 = gbm.Next(); + var bar2 = gbm.Next(); + + // Batch generation with explicit time + long startTime = bar2.Time + TimeSpan.FromMinutes(1).Ticks; + var interval = TimeSpan.FromMinutes(1); + var series = gbm.Fetch(3, startTime, interval); + + Assert.True(series[0].Time > bar2.Time); + Assert.Equal(3, series.Count); + + // Continue streaming after batch (uses internal state) + var bar3 = gbm.Next(); + Assert.True(bar3.Time > series[2].Time); + } + + [Fact] + public void DriftAndVolatility_AffectPriceMovement() + { + // High volatility should produce more price variation + var gbmLowVol = new GBM(startPrice: 100.0, mu: 0.0, sigma: 0.01); + var gbmHighVol = new GBM(startPrice: 100.0, mu: 0.0, sigma: 0.5); + + long startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromMinutes(1); + var seriesLow = gbmLowVol.Fetch(100, startTime, interval); + var seriesHigh = gbmHighVol.Fetch(100, startTime, interval); + + // Calculate price ranges + double rangeLow = seriesLow[99].Close - seriesLow[0].Open; + double rangeHigh = seriesHigh[99].Close - seriesHigh[0].Open; + + // High volatility should generally produce larger absolute movements + Assert.True(Math.Abs(rangeHigh) > Math.Abs(rangeLow) * 0.5); + } + + [Fact] + public void ConsecutiveCalls_MaintainContinuity() + { + var gbm = new GBM(startPrice: 100.0); + + var bar1 = gbm.Next(); + var bar2 = gbm.Next(); + + // bar2.Open should equal bar1.Close (continuity) + Assert.Equal(bar1.Close, bar2.Open); + } + + [Fact] + public void Stateless_NoHistoryStorage() + { + var gbm = new GBM(startPrice: 100.0); + + // Generate multiple bars + for (int i = 0; i < 100; i++) + { + gbm.Next(); + } + + // GBM should not expose any history storage + var type = gbm.GetType(); + var barsProperty = type.GetProperty("Bars"); + + Assert.Null(barsProperty); + } +} diff --git a/tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj b/tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj new file mode 100644 index 00000000..bec47c17 --- /dev/null +++ b/tests/QuanTAlib.Tests/QuanTAlib.Tests.csproj @@ -0,0 +1,36 @@ + + + + net10.0;net8.0 + enable + enable + false + true + false + false + $(NoWarn);CS8892 + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/tests/QuanTAlib.Tests/SimdExtensionsTests.cs b/tests/QuanTAlib.Tests/SimdExtensionsTests.cs new file mode 100644 index 00000000..3818db8e --- /dev/null +++ b/tests/QuanTAlib.Tests/SimdExtensionsTests.cs @@ -0,0 +1,249 @@ +using System; +using Xunit; +using QuanTAlib; + +namespace QuanTAlib.Tests; + +public class SimdExtensionsTests +{ + [Fact] + public void SumSIMD_EmptySpan_ReturnsZero() + { + var span = ReadOnlySpan.Empty; + Assert.Equal(0.0, span.SumSIMD()); + } + + [Fact] + public void SumSIMD_SingleElement_ReturnsElement() + { + double[] data = [42.5]; + var span = new ReadOnlySpan(data); + Assert.Equal(42.5, span.SumSIMD()); + } + + [Fact] + public void SumSIMD_MultipleElements_ReturnsCorrectSum() + { + double[] data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]; + var span = new ReadOnlySpan(data); + Assert.Equal(55.0, span.SumSIMD(), precision: 10); + } + + [Fact] + public void SumSIMD_LargeArray_ReturnsCorrectSum() + { + double[] data = new double[1000]; + for (int i = 0; i < data.Length; i++) + data[i] = i + 1.0; + + var span = new ReadOnlySpan(data); + double expected = 1000.0 * 1001.0 / 2.0; // Sum of 1..1000 + Assert.Equal(expected, span.SumSIMD(), precision: 8); + } + + [Fact] + public void MinSIMD_EmptySpan_ReturnsNaN() + { + var span = ReadOnlySpan.Empty; + Assert.True(double.IsNaN(span.MinSIMD())); + } + + [Fact] + public void MinSIMD_SingleElement_ReturnsElement() + { + double[] data = [42.5]; + var span = new ReadOnlySpan(data); + Assert.Equal(42.5, span.MinSIMD()); + } + + [Fact] + public void MinSIMD_MultipleElements_ReturnsMinimum() + { + double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0]; + var span = new ReadOnlySpan(data); + Assert.Equal(1.0, span.MinSIMD()); + } + + [Fact] + public void MaxSIMD_EmptySpan_ReturnsNaN() + { + var span = ReadOnlySpan.Empty; + Assert.True(double.IsNaN(span.MaxSIMD())); + } + + [Fact] + public void MaxSIMD_SingleElement_ReturnsElement() + { + double[] data = [42.5]; + var span = new ReadOnlySpan(data); + Assert.Equal(42.5, span.MaxSIMD()); + } + + [Fact] + public void MaxSIMD_MultipleElements_ReturnsMaximum() + { + double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0]; + var span = new ReadOnlySpan(data); + Assert.Equal(9.0, span.MaxSIMD()); + } + + [Fact] + public void AverageSIMD_EmptySpan_ReturnsNaN() + { + var span = ReadOnlySpan.Empty; + Assert.True(double.IsNaN(span.AverageSIMD())); + } + + [Fact] + public void AverageSIMD_MultipleElements_ReturnsCorrectAverage() + { + double[] data = [1.0, 2.0, 3.0, 4.0, 5.0]; + var span = new ReadOnlySpan(data); + Assert.Equal(3.0, span.AverageSIMD(), precision: 10); + } + + [Fact] + public void VarianceSIMD_LessThanTwoElements_ReturnsNaN() + { + double[] data = [42.5]; + var span = new ReadOnlySpan(data); + Assert.True(double.IsNaN(span.VarianceSIMD())); + } + + [Fact] + public void VarianceSIMD_MultipleElements_ReturnsCorrectVariance() + { + double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0]; + var span = new ReadOnlySpan(data); + + // Expected variance: 4.571428... (sample variance) + double variance = span.VarianceSIMD(); + Assert.True(Math.Abs(variance - 4.571428) < 0.0001); + } + + [Fact] + public void StdDevSIMD_MultipleElements_ReturnsCorrectStdDev() + { + double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0]; + var span = new ReadOnlySpan(data); + + // Expected std dev: sqrt(4.571428) ≈ 2.138 + double stdDev = span.StdDevSIMD(); + Assert.True(Math.Abs(stdDev - 2.138) < 0.01); + } + + [Fact] + public void MinMaxSIMD_EmptySpan_ReturnsBothNaN() + { + var span = ReadOnlySpan.Empty; + var (min, max) = span.MinMaxSIMD(); + Assert.True(double.IsNaN(min)); + Assert.True(double.IsNaN(max)); + } + + [Fact] + public void MinMaxSIMD_SingleElement_ReturnsSameValue() + { + double[] data = [42.5]; + var span = new ReadOnlySpan(data); + var (min, max) = span.MinMaxSIMD(); + Assert.Equal(42.5, min); + Assert.Equal(42.5, max); + } + + [Fact] + public void MinMaxSIMD_MultipleElements_ReturnsCorrectMinMax() + { + double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0]; + var span = new ReadOnlySpan(data); + var (min, max) = span.MinMaxSIMD(); + Assert.Equal(1.0, min); + Assert.Equal(9.0, max); + } + + [Fact] + public void SIMD_WorksWithTSeriesValues() + { + var series = new TSeries(100); + + for (int i = 0; i < 100; i++) + { + series.Add(DateTime.UtcNow.Ticks + i, i + 1.0); + } + + var values = series.Values; + + double sum = values.SumSIMD(); + double avg = values.AverageSIMD(); + double min = values.MinSIMD(); + double max = values.MaxSIMD(); + var (minAlt, maxAlt) = values.MinMaxSIMD(); + + Assert.Equal(5050.0, sum, precision: 8); // Sum of 1..100 + Assert.Equal(50.5, avg, precision: 8); + Assert.Equal(1.0, min); + Assert.Equal(100.0, max); + Assert.Equal(min, minAlt); + Assert.Equal(max, maxAlt); + } + + [Fact] + public void SIMD_WorksWithTBarSeriesClose() + { + var gbm = new GBM(startPrice: 100.0); + long startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromMinutes(1); + var bars = gbm.Fetch(1000, startTime, interval); + + var closeValues = bars.Close.Values; + + double sum = closeValues.SumSIMD(); + double avg = closeValues.AverageSIMD(); + double min = closeValues.MinSIMD(); + double max = closeValues.MaxSIMD(); + + Assert.True(sum > 0); + Assert.True(avg > 0); + Assert.True(min > 0); + Assert.True(max > min); + } + + [Fact] + public void SIMD_PerformanceTest_LargeDataset() + { + // Generate large dataset + var gbm = new GBM(startPrice: 100.0); + long startTime = DateTime.UtcNow.Ticks; + var interval = TimeSpan.FromMinutes(1); + var bars = gbm.Fetch(10000, startTime, interval); + var closeValues = bars.Close.Values; + + // Warm up + _ = closeValues.SumSIMD(); + + // Test SIMD operations + var sw = System.Diagnostics.Stopwatch.StartNew(); + + double sum = closeValues.SumSIMD(); + double avg = closeValues.AverageSIMD(); + double min = closeValues.MinSIMD(); + double max = closeValues.MaxSIMD(); + var (minAlt, maxAlt) = closeValues.MinMaxSIMD(); + double variance = closeValues.VarianceSIMD(); + double stdDev = closeValues.StdDevSIMD(); + + sw.Stop(); + + // Verify results are valid + Assert.True(sum > 0); + Assert.True(avg > 0); + Assert.True(min > 0); + Assert.True(max > min); + Assert.True(variance > 0); + Assert.True(stdDev > 0); + + // Performance should be sub-millisecond for 10k elements + Assert.True(sw.ElapsedMilliseconds < 10, + $"SIMD operations took {sw.ElapsedMilliseconds}ms, expected < 10ms"); + } +} diff --git a/tests/QuanTAlib.Tests/TBarSeriesTests.cs b/tests/QuanTAlib.Tests/TBarSeriesTests.cs new file mode 100644 index 00000000..41640388 --- /dev/null +++ b/tests/QuanTAlib.Tests/TBarSeriesTests.cs @@ -0,0 +1,58 @@ +using System; +using Xunit; +using QuanTAlib; + +namespace QuanTAlib.Tests +{ + public class TBarSeriesTests + { + [Fact] + public void Add_NewBar_IncreasesCount() + { + var series = new TBarSeries(); + var bar = new TBar(DateTime.UtcNow.Ticks, 100, 110, 90, 105, 1000); + + series.Add(bar, isNew: true); + + Assert.Single(series); + Assert.Equal(105.0, series.Last.Close); + } + + [Fact] + public void Add_UpdateBar_DoesNotIncreaseCount() + { + var series = new TBarSeries(); + long time = DateTime.UtcNow.Ticks; + var bar1 = new TBar(time, 100, 110, 90, 105, 1000); + var bar2 = new TBar(time, 100, 112, 90, 108, 1200); + + series.Add(bar1, isNew: true); + series.Add(bar2, isNew: false); + + Assert.Single(series); + Assert.Equal(108.0, series.Last.Close); + Assert.Equal(112.0, series.Last.High); + } + + [Fact] + public void SubSeries_AreUpdated() + { + var series = new TBarSeries(); + var bar = new TBar(DateTime.UtcNow.Ticks, 100, 110, 90, 105, 1000); + + series.Add(bar, isNew: true); + + Assert.Single(series.Open); + Assert.Single(series.High); + Assert.Single(series.Low); + Assert.Single(series.Close); + Assert.Single(series.Volume); + + Assert.Equal(100.0, series.Open.Last.Value); + Assert.Equal(110.0, series.High.Last.Value); + Assert.Equal(90.0, series.Low.Last.Value); + Assert.Equal(105.0, series.Close.Last.Value); + Assert.Equal(1000.0, series.Volume.Last.Value); + } + } +} diff --git a/tests/QuanTAlib.Tests/TBarTests.cs b/tests/QuanTAlib.Tests/TBarTests.cs new file mode 100644 index 00000000..4e3ab3f0 --- /dev/null +++ b/tests/QuanTAlib.Tests/TBarTests.cs @@ -0,0 +1,64 @@ +using System; +using Xunit; +using QuanTAlib; + +namespace QuanTAlib.Tests +{ + public class TBarTests + { + [Fact] + public void Constructor_SetsPropertiesCorrectly() + { + long time = DateTime.UtcNow.Ticks; + double open = 100; + double high = 110; + double low = 90; + double close = 105; + double volume = 1000; + + var bar = new TBar(time, open, high, low, close, volume); + + Assert.Equal(time, bar.Time); + Assert.Equal(open, bar.Open); + Assert.Equal(high, bar.High); + Assert.Equal(low, bar.Low); + Assert.Equal(close, bar.Close); + Assert.Equal(volume, bar.Volume); + } + + [Fact] + public void HL2_CalculatesCorrectly() + { + var bar = new TBar(0, 100, 110, 90, 105, 1000); + Assert.Equal(100.0, bar.HL2); // (110 + 90) / 2 + } + + [Fact] + public void OHL3_CalculatesCorrectly() + { + var bar = new TBar(0, 100, 110, 90, 105, 1000); + Assert.Equal(100.0, bar.OHL3); // (100 + 110 + 90) / 3 + } + + [Fact] + public void HLC3_CalculatesCorrectly() + { + var bar = new TBar(0, 100, 110, 90, 100, 1000); + Assert.Equal(100.0, bar.HLC3); // (110 + 90 + 100) / 3 + } + + [Fact] + public void OHLC4_CalculatesCorrectly() + { + var bar = new TBar(0, 100, 110, 90, 100, 1000); + Assert.Equal(100.0, bar.OHLC4); // (100 + 110 + 90 + 100) / 4 + } + + [Fact] + public void HLCC4_CalculatesCorrectly() + { + var bar = new TBar(0, 100, 110, 90, 100, 1000); + Assert.Equal(100.0, bar.HLCC4); // (110 + 90 + 100 + 100) / 4 + } + } +} diff --git a/tests/QuanTAlib.Tests/TSeriesTests.cs b/tests/QuanTAlib.Tests/TSeriesTests.cs new file mode 100644 index 00000000..8849554b --- /dev/null +++ b/tests/QuanTAlib.Tests/TSeriesTests.cs @@ -0,0 +1,49 @@ +using System; +using Xunit; +using QuanTAlib; + +namespace QuanTAlib.Tests +{ + public class TSeriesTests + { + [Fact] + public void Add_NewValue_IncreasesCount() + { + var series = new TSeries(); + long time = DateTime.UtcNow.Ticks; + + series.Add(time, 10.0, isNew: true); + + Assert.Single(series); + Assert.Equal(10.0, series.Last.Value); + } + + [Fact] + public void Add_UpdateValue_DoesNotIncreaseCount() + { + var series = new TSeries(); + long time = DateTime.UtcNow.Ticks; + + series.Add(time, 10.0, isNew: true); + series.Add(time, 11.0, isNew: false); + + Assert.Single(series); + Assert.Equal(11.0, series.Last.Value); + } + + [Fact] + public void Add_MultipleValues_MaintainsOrder() + { + var series = new TSeries(); + long t0 = DateTime.UtcNow.Ticks; + long t1 = t0 + TimeSpan.TicksPerMinute; + + series.Add(t0, 10.0, isNew: true); + series.Add(t1, 20.0, isNew: true); + + Assert.Equal(2, series.Count); + Assert.Equal(10.0, series[0].Value); + Assert.Equal(20.0, series[1].Value); + } + } +} diff --git a/tests/QuanTAlib.Tests/TValueTests.cs b/tests/QuanTAlib.Tests/TValueTests.cs new file mode 100644 index 00000000..8b2e8614 --- /dev/null +++ b/tests/QuanTAlib.Tests/TValueTests.cs @@ -0,0 +1,51 @@ +using System; +using Xunit; +using QuanTAlib; + +namespace QuanTAlib.Tests +{ + public class TValueTests + { + [Fact] + public void Constructor_SetsPropertiesCorrectly() + { + long time = DateTime.UtcNow.Ticks; + double value = 123.45; + + var tValue = new TValue(time, value); + + Assert.Equal(time, tValue.Time); + Assert.Equal(value, tValue.Value); + } + + [Fact] + public void AsDateTime_ReturnsCorrectDateTime() + { + DateTime dt = new DateTime(2023, 1, 1, 12, 0, 0, DateTimeKind.Utc); + long ticks = dt.Ticks; + var tValue = new TValue(ticks, 100.0); + + Assert.Equal(dt, tValue.AsDateTime); + } + + [Fact] + public void ToString_FormatsCorrectly() + { + DateTime dt = new DateTime(2023, 1, 1, 12, 0, 0, DateTimeKind.Utc); + var tValue = new TValue(dt.Ticks, 123.456); + + string result = tValue.ToString(); + + Assert.Contains(dt.ToString("yyyy-MM-dd HH:mm:ss"), result); + Assert.Contains("123.46", result); // Default formatting usually 2 decimals or similar + } + + [Fact] + public void ImplicitConversion_ToDouble() + { + var tValue = new TValue(DateTime.UtcNow.Ticks, 42.0); + double val = tValue; + Assert.Equal(42.0, val); + } + } +} diff --git a/tests/QuanTAlib.Tests/daily_IBM.csv b/tests/QuanTAlib.Tests/daily_IBM.csv new file mode 100644 index 00000000..111591d2 --- /dev/null +++ b/tests/QuanTAlib.Tests/daily_IBM.csv @@ -0,0 +1,101 @@ +timestamp,open,high,low,close,volume +2025-11-25,304.1250,306.0000,297.0600,304.4800,2825322 +2025-11-24,299.1800,307.1800,297.5100,304.1200,6050640 +2025-11-21,293.4800,300.4800,291.8900,297.4400,5710903 +2025-11-20,294.6400,300.7100,290.1600,290.4000,5597028 +2025-11-19,290.5000,291.1099,288.0700,288.5300,3595912 +2025-11-18,297.0000,297.0000,289.9200,289.9500,4861928 +2025-11-17,305.5900,306.0000,296.5100,297.1700,3909741 +2025-11-14,300.0000,307.7200,297.5900,305.6900,3592455 +2025-11-13,312.2900,314.6000,303.6800,304.8600,5310150 +2025-11-12,319.8900,324.9000,314.5324,314.9800,6042686 +2025-11-11,309.0000,317.9100,308.4300,313.7200,4381913 +2025-11-10,306.8200,309.9400,304.2300,309.1300,2975188 +2025-11-07,309.6800,310.0000,302.6301,306.3800,5070773 +2025-11-06,306.7500,315.4400,301.0900,312.4200,6818521 +2025-11-05,301.3800,307.2000,299.7100,306.7700,4633195 +2025-11-04,300.0000,303.1700,296.0000,300.8500,5677330 +2025-11-03,308.0000,312.1411,304.2300,304.7300,4957958 +2025-10-31,312.0000,313.5000,301.6300,307.4100,7697499 +2025-10-30,306.6500,313.7500,305.0200,310.0600,4694275 +2025-10-29,312.7900,314.3300,307.5200,308.2100,4135948 +2025-10-28,312.6000,319.3500,311.4100,312.5700,6044770 +2025-10-27,307.8000,313.5000,302.8800,313.0900,9868151 +2025-10-24,283.7700,310.7500,282.2100,307.4600,16914243 +2025-10-23,264.9500,285.5791,263.5623,285.0000,16676394 +2025-10-22,281.9900,289.1700,281.3500,287.5100,10538480 +2025-10-21,283.3100,285.3100,281.6000,282.0500,4080981 +2025-10-20,281.2500,285.5000,280.9600,283.6500,3494336 +2025-10-17,276.1500,283.4000,275.3500,281.2800,5309565 +2025-10-16,281.1100,282.5600,275.6000,275.9700,2956923 +2025-10-15,278.3800,285.4500,277.0000,280.7500,3346753 +2025-10-14,275.5200,277.5300,272.5469,276.1500,3058149 +2025-10-13,279.7900,282.4399,274.6400,277.2200,4333836 +2025-10-10,288.9700,290.3850,277.5000,277.8200,4508506 +2025-10-09,289.8200,290.1300,283.3200,288.2300,4912375 +2025-10-08,294.1600,294.2000,286.4730,289.4600,5297030 +2025-10-07,295.5500,301.0425,293.2850,293.8700,7190126 +2025-10-06,288.6100,291.4500,287.8000,289.4200,2881947 +2025-10-03,287.5000,293.3200,287.3000,288.3700,4375082 +2025-10-02,285.7900,288.5400,282.7900,286.7200,3814232 +2025-10-01,280.2000,286.5900,280.1500,286.4900,4381338 +2025-09-30,280.8800,286.0250,280.5200,282.1600,5926924 +2025-09-29,286.0000,286.0000,279.6600,279.8000,6022125 +2025-09-26,280.5100,288.8500,280.1100,284.3100,9063938 +2025-09-25,272.9350,284.2300,271.1480,281.4400,11506192 +2025-09-24,272.6200,273.6499,267.3000,267.5300,3159924 +2025-09-23,272.7000,273.2962,269.2650,272.2400,5394121 +2025-09-22,266.6200,272.3100,266.0000,271.3700,5030540 +2025-09-19,266.0500,267.8700,263.6400,266.4000,9858112 +2025-09-18,258.8600,265.2300,256.8004,265.0000,4988421 +2025-09-17,257.4950,260.9644,257.0100,259.0800,3974785 +2025-09-16,256.2600,258.0000,254.4100,257.5200,2719918 +2025-09-15,254.0200,259.0500,254.0000,256.2400,4028365 +2025-09-12,256.9500,257.2500,252.4250,253.4400,3433300 +2025-09-11,257.5600,258.5450,255.6550,257.0100,3576048 +2025-09-10,259.6500,260.0800,254.5600,256.8800,5185420 +2025-09-09,256.1200,260.6600,254.8800,259.1100,4931105 +2025-09-08,248.6300,257.1500,247.0200,256.0900,6940270 +2025-09-05,248.2300,249.0300,245.4500,248.5300,3147478 +2025-09-04,245.4200,249.2800,242.8500,247.1800,4765087 +2025-09-03,240.0200,244.2500,239.4100,244.1000,3156289 +2025-09-02,240.9000,241.5500,238.2500,241.5000,3469501 +2025-08-29,245.2300,245.4599,241.7200,243.4900,2967558 +2025-08-28,245.4300,245.8800,243.3600,245.7300,2820817 +2025-08-27,242.8700,245.9600,242.0000,244.8400,3698372 +2025-08-26,241.0200,244.9800,240.3800,242.6300,5386582 +2025-08-25,242.5650,242.5650,239.4300,239.4300,3513327 +2025-08-22,240.7400,243.6800,240.2200,242.0900,3134882 +2025-08-21,242.2100,242.5000,238.6500,239.4000,2991902 +2025-08-20,242.1100,242.8800,240.3400,242.5500,3240064 +2025-08-19,240.0000,242.8300,239.4900,241.2800,3328305 +2025-08-18,239.5700,241.4200,239.1158,239.4500,3569594 +2025-08-15,237.6100,240.6200,236.7700,239.7200,4344322 +2025-08-14,238.2500,239.0000,235.6200,237.1100,4556725 +2025-08-13,236.2000,240.8411,236.2000,240.0700,5663562 +2025-08-12,236.5300,237.9600,233.3600,234.7700,8800597 +2025-08-11,242.2400,243.1500,234.7000,236.3000,9381960 +2025-08-08,248.8800,249.4800,241.6500,242.2700,6828390 +2025-08-07,252.8100,255.0000,248.8750,250.1600,6251285 +2025-08-06,251.5300,254.3200,249.2800,252.2800,3692105 +2025-08-05,252.0000,252.8000,248.9950,250.6700,5823016 +2025-08-04,251.0500,252.0800,248.1100,251.9800,5280588 +2025-08-01,251.4050,251.4791,245.6100,250.0500,9683404 +2025-07-31,259.5700,259.9900,252.2200,253.1500,6739092 +2025-07-30,261.6000,262.0000,258.9000,260.2600,3718290 +2025-07-29,264.3000,265.7999,261.0200,262.4100,4627265 +2025-07-28,260.3000,264.0000,259.6100,263.2100,5192516 +2025-07-25,260.0200,260.8000,256.3500,259.7200,7758653 +2025-07-24,261.2500,262.0486,252.7500,260.5100,22647720 +2025-07-23,284.3000,288.0800,281.4400,282.0100,8105906 +2025-07-22,284.7400,284.8800,281.2500,281.9600,4824219 +2025-07-21,286.2900,287.7300,284.3800,284.7100,3051791 +2025-07-18,283.3800,287.1600,282.2200,285.8700,4478165 +2025-07-17,281.5000,283.4566,280.9000,282.0000,3337168 +2025-07-16,282.7500,283.8700,279.8700,281.9200,2804831 +2025-07-15,283.7700,284.1550,280.7301,282.7000,2864106 +2025-07-14,282.8300,284.9250,281.7100,283.7900,2857401 +2025-07-11,285.0100,287.4300,282.9200,283.5900,3790679 +2025-07-10,288.9000,288.9000,282.2100,287.4300,3489068 +2025-07-09,291.3900,291.6000,288.6300,290.1400,2971309 +2025-07-08,293.1000,295.6100,289.4900,290.4200,2925329

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 B[lib] - B --> C[core] - B --> D[averages] - B --> E[momentum] - B --> F[oscillators] - B --> G[errors] - B --> H[feeds] - B --> I[patterns] - B --> J[statistics] - B --> K[volatility] - B --> L[volume] - - C --> C1[AbstractBase] - C --> C2[TBarSeries] - C --> C3[TSeries] - C --> C4[CircularBuffer] - - D --> D1[EMA] - D --> D2[SMA] - D --> D3[WMA] - - E --> E1[MACD] - E --> E2[ROC] - E --> E3[ADX] - - F --> F1[RSI] - F --> F2[Stoch] - F --> F3[CCI] diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 23a7f5e8..00000000 --- a/docs/index.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - QuanTAlib Documentation - - - - - - - - - - - - -