├── .env.example ├── .github └── workflows │ └── quant.yml ├── .gitignore ├── .python-version ├── LICENSE ├── Makefile ├── README.md ├── config.default.ini ├── coral ├── __init__.py ├── _factory.py └── exchange │ ├── __init__.py │ ├── rest │ ├── __init__.py │ ├── _bybit.py │ └── _factory.py │ └── ws │ ├── __init__.py │ ├── _bybit.py │ └── _factory.py ├── core ├── __init__.py ├── actors │ ├── __init__.py │ ├── _base.py │ ├── _feed.py │ ├── _strategy.py │ ├── collector │ │ ├── __init__.py │ │ └── _data.py │ ├── decorators │ │ ├── __init__.py │ │ └── _collector.py │ ├── policy │ │ ├── __init__.py │ │ ├── event.py │ │ ├── feed.py │ │ ├── signal.py │ │ └── strategy.py │ └── state │ │ ├── __init__.py │ │ ├── _memory.py │ │ ├── _rw.py │ │ └── _signal.py ├── commands │ ├── __init__.py │ ├── _base.py │ ├── account.py │ ├── broker.py │ ├── factor.py │ ├── market.py │ ├── portfolio.py │ └── position.py ├── event_decorators.py ├── events │ ├── __init__.py │ ├── _base.py │ ├── account.py │ ├── backtest.py │ ├── market.py │ ├── meta.py │ ├── portfolio.py │ ├── position.py │ ├── risk.py │ ├── signal.py │ ├── system.py │ └── trade.py ├── groups │ ├── __init__.py │ ├── command.py │ ├── event.py │ ├── query.py │ └── tasks.py ├── interfaces │ ├── __init__.py │ ├── abstract_actor.py │ ├── abstract_config.py │ ├── abstract_datasource_factory.py │ ├── abstract_event_manager.py │ ├── abstract_exchange.py │ ├── abstract_executor_actor_factory.py │ ├── abstract_feed_actor_factory.py │ ├── abstract_llm_service.py │ ├── abstract_market_repository.py │ ├── abstract_optimizer_factory.py │ ├── abstract_order_size_strategy.py │ ├── abstract_position_actor_factory.py │ ├── abstract_position_manager.py │ ├── abstract_position_risk_strategy.py │ ├── abstract_position_take_profit_strategy.py │ ├── abstract_risk_actor_factory.py │ ├── abstract_secret_service.py │ ├── abstract_signal_actor_factory.py │ ├── abstract_signal_service.py │ ├── abstract_strategy_generator.py │ ├── abstract_strategy_generator_factory.py │ ├── abstract_strategy_optimization.py │ ├── abstract_stream_strategy.py │ ├── abstract_system.py │ ├── abstract_timeseries.py │ └── abstract_wasm_manager.py ├── mixins │ ├── __init__.py │ └── _event_handler.py ├── models │ ├── __init__.py │ ├── action.py │ ├── broker.py │ ├── candle.py │ ├── candle_type.py │ ├── cap.py │ ├── datasource_type.py │ ├── entity │ │ ├── __init__.py │ │ ├── _base.py │ │ ├── bar.py │ │ ├── ohlcv.py │ │ ├── order.py │ │ ├── portfolio.py │ │ ├── position.py │ │ ├── profit_target.py │ │ ├── risk.py │ │ ├── signal.py │ │ └── signal_risk.py │ ├── feed.py │ ├── indicator.py │ ├── individual.py │ ├── lookback.py │ ├── moving_average.py │ ├── optimizer.py │ ├── order_type.py │ ├── parameter.py │ ├── protocol_type.py │ ├── risk_type.py │ ├── side.py │ ├── smooth.py │ ├── source.py │ ├── strategy.py │ ├── strategy_ref.py │ ├── strategy_type.py │ ├── symbol.py │ ├── ta.py │ ├── timeframe.py │ ├── timeseries_ref.py │ ├── wasm_type.py │ └── wss_type.py ├── queries │ ├── __init__.py │ ├── _base.py │ ├── account.py │ ├── broker.py │ ├── copilot.py │ ├── factor.py │ ├── ohlcv.py │ ├── portfolio.py │ └── position.py ├── result.py └── tasks │ ├── __init__.py │ ├── _base.py │ └── feed.py ├── executor ├── __init__.py ├── _factory.py ├── _market_actor.py └── _paper_actor.py ├── factor ├── __init__.py ├── _actor.py ├── baseline │ ├── __init__.py │ ├── base.py │ └── ma.py ├── confirm │ ├── __init__.py │ ├── base.py │ ├── bb.py │ ├── braid.py │ ├── cc.py │ ├── cci.py │ ├── didi.py │ ├── dpo.py │ ├── dumb.py │ ├── eom.py │ ├── rsi_neutrality.py │ ├── rsi_signalline.py │ ├── stc.py │ └── wpr.py ├── generator │ ├── __init__.py │ └── _population.py ├── pulse │ ├── __init__.py │ ├── adx.py │ ├── base.py │ ├── chop.py │ ├── dumb.py │ ├── nvol.py │ ├── sqz.py │ ├── tdfi.py │ ├── vo.py │ ├── wae.py │ └── yz.py └── signal │ ├── __init__.py │ ├── base.py │ ├── bb │ ├── __init__.py │ ├── macd.py │ └── vwap.py │ ├── breakout │ ├── __init__.py │ └── dch_two_ma.py │ ├── colorswitch │ ├── __init__.py │ └── macd.py │ ├── contrarian │ ├── __init__.py │ ├── kch_a.py │ ├── kch_c.py │ ├── rsi_c.py │ ├── rsi_d.py │ ├── rsi_nt.py │ ├── rsi_u.py │ ├── rsi_v.py │ ├── snatr.py │ ├── stoch_e.py │ └── tii_v.py │ ├── flip │ ├── __init__.py │ ├── ce.py │ └── supertrend.py │ ├── ma │ ├── __init__.py │ ├── ma2_rsi.py │ ├── ma3_cross.py │ ├── ma_cross.py │ ├── ma_quadruple.py │ ├── ma_surpass.py │ ├── ma_testing_ground.py │ └── vwap_cross.py │ ├── neutrality │ ├── __init__.py │ ├── dso_cross.py │ ├── rsi_cross.py │ ├── rsi_pullback.py │ ├── rsi_rejection.py │ └── tii_cross.py │ ├── pattern │ ├── __init__.py │ ├── ao_saucer.py │ ├── candle_reversal.py │ ├── candle_trend.py │ ├── hl.py │ └── spread.py │ ├── pullback │ ├── __init__.py │ └── supertrend.py │ ├── signalline │ ├── __init__.py │ ├── di.py │ ├── dso.py │ ├── kst.py │ ├── macd.py │ ├── qstick.py │ ├── rsi.py │ ├── stoch.py │ ├── trix.py │ └── tsi.py │ ├── twolinescross │ ├── __init__.py │ ├── dmi.py │ └── vi.py │ └── zerocross │ ├── __init__.py │ ├── ao.py │ ├── bop.py │ ├── cc.py │ ├── cfo.py │ ├── di.py │ ├── macd.py │ ├── mad.py │ ├── qstick.py │ ├── roc.py │ ├── trix.py │ └── tsi.py ├── feed ├── __init__.py ├── _factory.py ├── _historical.py ├── _realtime.py └── streams │ ├── __init__.py │ ├── base │ ├── __init__.py │ ├── _historical.py │ └── _realtime.py │ └── strategy │ ├── __init__.py │ ├── _kline.py │ ├── _liquidation.py │ ├── _order.py │ ├── _order_book.py │ └── _position.py ├── infrastructure ├── __init__.py ├── config.py ├── estimator.py ├── event_dispatcher │ ├── __init__.py │ ├── event_dedup.py │ ├── event_dispatcher.py │ ├── event_handler.py │ ├── event_worker.py │ ├── load_balancer.py │ ├── pid_controller.py │ └── worker_pool.py ├── event_store │ ├── __init__.py │ ├── event_encoder.py │ └── event_store.py ├── logger.py ├── retry.py ├── shutdown.py └── telemetry │ ├── __init__.py │ └── throughput_monitor.py ├── market ├── __init__.py └── _actor.py ├── mypy.ini ├── notebooks ├── dna.ipynb ├── models │ ├── __init__.py │ └── autoencoder_v1.py ├── pipelines │ ├── ocean.ipynb │ ├── ocean_train.py │ ├── orca.ipynb │ └── remora.ipynb ├── train │ ├── __init__.py │ ├── checkpoint.py │ ├── common_trainer.py │ ├── early_stop.py │ ├── snapshot.py │ └── trainer.py └── utils.py ├── ocean ├── __init__.py ├── _actor.py └── _gsim.py ├── portfolio ├── __init__.py └── _actor.py ├── position ├── __init__.py ├── _actor.py ├── _factory.py └── _sm.py ├── pyproject.toml ├── quant.py ├── reef ├── __init__.py ├── _actor.py └── _order.py ├── risk ├── __init__.py ├── _actor.py └── _factory.py ├── ruff.toml ├── rust-toolchain.toml ├── service ├── __init__.py ├── _env_secret.py ├── _llm.py ├── _signal.py ├── _timeseries.py └── _wasm.py ├── sor ├── __init__.py ├── _router.py └── _twap.py ├── strategy ├── __init__.py ├── _actor.py └── _factory.py ├── system ├── __init__.py ├── backtest.py ├── context.py └── trading.py ├── ta_lib ├── Cargo.lock ├── Cargo.toml ├── benches │ ├── Cargo.toml │ ├── indicators.rs │ ├── patterns.rs │ └── prices.rs ├── core │ ├── Cargo.toml │ └── src │ │ ├── bitwise.rs │ │ ├── cmp.rs │ │ ├── constants.rs │ │ ├── cross.rs │ │ ├── extremum.rs │ │ ├── fmt.rs │ │ ├── from.rs │ │ ├── lib.rs │ │ ├── macros.rs │ │ ├── math.rs │ │ ├── ops.rs │ │ ├── series.rs │ │ ├── smoothing.rs │ │ ├── traits.rs │ │ └── types.rs ├── ffi │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── timeseries.rs ├── indicators │ ├── momentum │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── bop.rs │ │ │ ├── cc.rs │ │ │ ├── cci.rs │ │ │ ├── cfo.rs │ │ │ ├── cmo.rs │ │ │ ├── di.rs │ │ │ ├── dmi.rs │ │ │ ├── kst.rs │ │ │ ├── lib.rs │ │ │ ├── macd.rs │ │ │ ├── qstick.rs │ │ │ ├── rex.rs │ │ │ ├── roc.rs │ │ │ ├── rsi.rs │ │ │ ├── stc.rs │ │ │ ├── stochosc.rs │ │ │ ├── tdfi.rs │ │ │ ├── tii.rs │ │ │ ├── trix.rs │ │ │ ├── tsi.rs │ │ │ ├── uo.rs │ │ │ └── wpr.rs │ ├── trend │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── alma.rs │ │ │ ├── ast.rs │ │ │ ├── cama.rs │ │ │ ├── ce.rs │ │ │ ├── chop.rs │ │ │ ├── dema.rs │ │ │ ├── dpo.rs │ │ │ ├── ema.rs │ │ │ ├── frama.rs │ │ │ ├── gma.rs │ │ │ ├── hema.rs │ │ │ ├── hma.rs │ │ │ ├── kama.rs │ │ │ ├── lib.rs │ │ │ ├── lsma.rs │ │ │ ├── md.rs │ │ │ ├── midpoint.rs │ │ │ ├── pp.rs │ │ │ ├── rmsma.rs │ │ │ ├── sinwma.rs │ │ │ ├── slsma.rs │ │ │ ├── sma.rs │ │ │ ├── smma.rs │ │ │ ├── supertrend.rs │ │ │ ├── t3.rs │ │ │ ├── tema.rs │ │ │ ├── trima.rs │ │ │ ├── ults.rs │ │ │ ├── vi.rs │ │ │ ├── vidya.rs │ │ │ ├── vwema.rs │ │ │ ├── vwma.rs │ │ │ ├── wma.rs │ │ │ ├── zlema.rs │ │ │ ├── zlhma.rs │ │ │ ├── zlsma.rs │ │ │ └── zltema.rs │ ├── volatility │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── bb.rs │ │ │ ├── dch.rs │ │ │ ├── gkyz.rs │ │ │ ├── kb.rs │ │ │ ├── kch.rs │ │ │ ├── lib.rs │ │ │ ├── pk.rs │ │ │ ├── ppb.rs │ │ │ ├── rs.rs │ │ │ ├── tr.rs │ │ │ └── yz.rs │ └── volume │ │ ├── Cargo.toml │ │ └── src │ │ ├── cmf.rs │ │ ├── eom.rs │ │ ├── lib.rs │ │ ├── mfi.rs │ │ ├── nvol.rs │ │ ├── obv.rs │ │ └── vwap.rs ├── patterns │ ├── bands │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── macros.rs │ ├── candlestick │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── barrier.rs │ │ │ ├── blockade.rs │ │ │ ├── bottle.rs │ │ │ ├── breakaway.rs │ │ │ ├── counterattack.rs │ │ │ ├── doji.rs │ │ │ ├── doji_double.rs │ │ │ ├── doppelganger.rs │ │ │ ├── double_trouble.rs │ │ │ ├── engulfing.rs │ │ │ ├── euphoria.rs │ │ │ ├── euphoria_extreme.rs │ │ │ ├── golden.rs │ │ │ ├── h.rs │ │ │ ├── hammer.rs │ │ │ ├── harami_flexible.rs │ │ │ ├── harami_strict.rs │ │ │ ├── hexad.rs │ │ │ ├── hikkake.rs │ │ │ ├── kangaroo_tail.rs │ │ │ ├── lib.rs │ │ │ ├── marubozu.rs │ │ │ ├── master_candle.rs │ │ │ ├── on_neck.rs │ │ │ ├── piercing.rs │ │ │ ├── quintuplets.rs │ │ │ ├── r.rs │ │ │ ├── shrinking.rs │ │ │ ├── slingshot.rs │ │ │ ├── split.rs │ │ │ ├── tasuki.rs │ │ │ ├── three_candles.rs │ │ │ ├── three_methods.rs │ │ │ ├── three_one_two.rs │ │ │ └── tweezers.rs │ ├── channel │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── macros.rs │ ├── osc │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── macros.rs │ └── trail │ │ ├── Cargo.toml │ │ └── src │ │ ├── lib.rs │ │ └── macros.rs ├── price │ ├── Cargo.toml │ └── src │ │ ├── average.rs │ │ ├── lib.rs │ │ ├── median.rs │ │ ├── typical.rs │ │ └── wcl.rs ├── strategies │ ├── base │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── ffi.rs │ │ │ ├── lib.rs │ │ │ ├── source.rs │ │ │ ├── strategy.rs │ │ │ ├── traits.rs │ │ │ └── volatility.rs │ ├── baseline │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── ma.rs │ ├── confirm │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── bb.rs │ │ │ ├── braid.rs │ │ │ ├── cc.rs │ │ │ ├── cci.rs │ │ │ ├── didi.rs │ │ │ ├── dpo.rs │ │ │ ├── dumb.rs │ │ │ ├── eom.rs │ │ │ ├── lib.rs │ │ │ ├── rsi_neutrality.rs │ │ │ ├── rsi_signalline.rs │ │ │ ├── stc.rs │ │ │ └── wpr.rs │ ├── indicator │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── candle.rs │ │ │ ├── lib.rs │ │ │ └── ma.rs │ ├── pulse │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── adx.rs │ │ │ ├── chop.rs │ │ │ ├── dumb.rs │ │ │ ├── lib.rs │ │ │ ├── nvol.rs │ │ │ ├── sqz.rs │ │ │ ├── tdfi.rs │ │ │ ├── vo.rs │ │ │ ├── wae.rs │ │ │ └── yz.rs │ ├── signal │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── bb │ │ │ ├── macd.rs │ │ │ ├── mod.rs │ │ │ └── vwap.rs │ │ │ ├── breakout │ │ │ ├── dch_ma2.rs │ │ │ └── mod.rs │ │ │ ├── colorswitch │ │ │ ├── macd.rs │ │ │ └── mod.rs │ │ │ ├── contrarian │ │ │ ├── kch_a.rs │ │ │ ├── kch_c.rs │ │ │ ├── mod.rs │ │ │ ├── rsi_c.rs │ │ │ ├── rsi_d.rs │ │ │ ├── rsi_nt.rs │ │ │ ├── rsi_u.rs │ │ │ ├── rsi_v.rs │ │ │ ├── snatr.rs │ │ │ ├── stoch_e.rs │ │ │ └── tii_v.rs │ │ │ ├── flip │ │ │ ├── ce.rs │ │ │ ├── mod.rs │ │ │ └── supertrend.rs │ │ │ ├── lib.rs │ │ │ ├── ma │ │ │ ├── ma2_rsi.rs │ │ │ ├── ma3_cross.rs │ │ │ ├── ma_cross.rs │ │ │ ├── ma_quadruple.rs │ │ │ ├── ma_surpass.rs │ │ │ ├── ma_testing_ground.rs │ │ │ ├── mod.rs │ │ │ └── vwap_cross.rs │ │ │ ├── neutrality │ │ │ ├── dso_cross.rs │ │ │ ├── mod.rs │ │ │ ├── rsi_cross.rs │ │ │ ├── rsi_pullback.rs │ │ │ ├── rsi_rejection.rs │ │ │ └── tii_cross.rs │ │ │ ├── pattern │ │ │ ├── ao_saucer.rs │ │ │ ├── candlestick_reversal.rs │ │ │ ├── candlestick_trend.rs │ │ │ ├── hl.rs │ │ │ ├── mod.rs │ │ │ └── spread.rs │ │ │ ├── pullback │ │ │ ├── mod.rs │ │ │ └── supertrend.rs │ │ │ ├── signalline │ │ │ ├── di.rs │ │ │ ├── dso.rs │ │ │ ├── kst.rs │ │ │ ├── macd.rs │ │ │ ├── mod.rs │ │ │ ├── qstick.rs │ │ │ ├── rsi.rs │ │ │ ├── stoch.rs │ │ │ ├── trix.rs │ │ │ └── tsi.rs │ │ │ ├── twolinescross │ │ │ ├── dmi.rs │ │ │ ├── mod.rs │ │ │ └── vi.rs │ │ │ └── zerocross │ │ │ ├── ao.rs │ │ │ ├── bop.rs │ │ │ ├── cc.rs │ │ │ ├── cfo.rs │ │ │ ├── di.rs │ │ │ ├── macd.rs │ │ │ ├── mad.rs │ │ │ ├── mod.rs │ │ │ ├── qstick.rs │ │ │ ├── roc.rs │ │ │ ├── trix.rs │ │ │ └── tsi.rs │ └── trend_follow │ │ ├── Cargo.toml │ │ └── src │ │ ├── config │ │ ├── baseline_config.rs │ │ ├── confirm_config.rs │ │ ├── mod.rs │ │ ├── pulse_config.rs │ │ └── signal_config.rs │ │ ├── deserialize │ │ ├── candle_deserialize.rs │ │ ├── ma_deserialize.rs │ │ ├── mod.rs │ │ ├── smooth_deserialize.rs │ │ └── source_deserialize.rs │ │ ├── ffi.rs │ │ ├── lib.rs │ │ └── mapper │ │ ├── baseline_mapper.rs │ │ ├── confirm_mapper.rs │ │ ├── mod.rs │ │ ├── pulse_mapper.rs │ │ └── signal_mapper.rs └── timeseries │ ├── Cargo.toml │ └── src │ ├── lib.rs │ ├── model.rs │ ├── ohlcv.rs │ ├── ta.rs │ └── traits.rs ├── uv.lock └── wasm └── .empty /.env.example: -------------------------------------------------------------------------------- 1 | BYBIT_API_KEY= 2 | BYBIT_API_SECRET= 3 | BYBIT_WSS_PUBLIC= 4 | BYBIT_WSS_PRIVATE= 5 | BYBIT_WSS_ORDER= 6 | 7 | LOG_DIR= 8 | 9 | LOG_LEVEL=INFO 10 | WASM_FOLDER=wasm 11 | REGIME=default 12 | 13 | COPILOT_MODEL_PATH= 14 | OCEAN_EMB_PATH= 15 | 16 | MASTER_ADDR= 17 | MASTER_PORT= 18 | WORLD_SIZE=1 19 | RANK=0 -------------------------------------------------------------------------------- /.github/workflows/quant.yml: -------------------------------------------------------------------------------- 1 | name: QUANT CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Check out code 14 | uses: actions/checkout@v2 15 | 16 | - name: Test 17 | run: make test 18 | 19 | - name: Check 20 | run: make check 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | __pycache__ 3 | .ipynb_checkpoints 4 | .DS_Store 5 | .csv 6 | target 7 | .log 8 | *.wasm -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Systematic trading 2 | 3 | ### Research project for fun and profit 4 | 5 | > [!WARNING] 6 | > This implementation is intended for personal use only and is not designed for production environments. Additionally, this does not constitute financial advice. 7 | -------------------------------------------------------------------------------- /coral/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import DataSourceFactory 2 | 3 | __all__ = [DataSourceFactory] 4 | -------------------------------------------------------------------------------- /coral/exchange/__init__.py: -------------------------------------------------------------------------------- 1 | from .rest import RestDataSourceFactory as ExchangeRestDataSourceFactory 2 | from .ws import WSDataSourceFactory as ExchangeWSDataSourceFactory 3 | 4 | __all__ = [ExchangeWSDataSourceFactory, ExchangeRestDataSourceFactory] 5 | -------------------------------------------------------------------------------- /coral/exchange/rest/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import RestDataSourceFactory 2 | 3 | __all__ = [RestDataSourceFactory] 4 | -------------------------------------------------------------------------------- /coral/exchange/ws/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import WSDataSourceFactory 2 | 3 | __all__ = [WSDataSourceFactory] 4 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/__init__.py -------------------------------------------------------------------------------- /core/actors/__init__.py: -------------------------------------------------------------------------------- 1 | from ._base import BaseActor 2 | from ._feed import FeedActor 3 | from ._strategy import StrategyActor 4 | 5 | __all__ = [BaseActor, StrategyActor, FeedActor] 6 | -------------------------------------------------------------------------------- /core/actors/_strategy.py: -------------------------------------------------------------------------------- 1 | from core.models.symbol import Symbol 2 | from core.models.timeframe import Timeframe 3 | 4 | from ._base import BaseActor 5 | from .policy.strategy import StrategyPolicy 6 | 7 | 8 | class StrategyActor(BaseActor): 9 | def __init__(self, symbol: Symbol, timeframe: Timeframe): 10 | super().__init__() 11 | self._symbol = symbol 12 | self._timeframe = timeframe 13 | self._id = f"{self.symbol}_{self.timeframe}" 14 | 15 | @property 16 | def id(self) -> str: 17 | return self._id 18 | 19 | @property 20 | def symbol(self) -> "Symbol": 21 | return self._symbol 22 | 23 | @property 24 | def timeframe(self) -> "Timeframe": 25 | return self._timeframe 26 | 27 | def pre_receive(self, msg) -> bool: 28 | return StrategyPolicy.should_process(self, msg) 29 | -------------------------------------------------------------------------------- /core/actors/collector/__init__.py: -------------------------------------------------------------------------------- 1 | from ._data import DataCollector 2 | 3 | __all__ = [DataCollector] 4 | -------------------------------------------------------------------------------- /core/actors/decorators/__init__.py: -------------------------------------------------------------------------------- 1 | from ._collector import Consumer, Producer 2 | 3 | __all__ = [Producer, Consumer] 4 | -------------------------------------------------------------------------------- /core/actors/policy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/actors/policy/__init__.py -------------------------------------------------------------------------------- /core/actors/policy/event.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.events._base import Event 4 | from core.interfaces.abstract_actor import AbstractActor 5 | 6 | 7 | class EventPolicy(ABC): 8 | @abstractmethod 9 | def should_process(actor: AbstractActor, event: Event) -> bool: 10 | pass 11 | -------------------------------------------------------------------------------- /core/actors/policy/feed.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from core.tasks.feed import StartHistoricalFeed, StartRealtimeFeed 4 | 5 | from .event import EventPolicy 6 | 7 | FeedEvent = Union[StartHistoricalFeed, StartRealtimeFeed] 8 | 9 | 10 | class FeedPolicy(EventPolicy): 11 | @classmethod 12 | def should_process(cls, actor, event: FeedEvent) -> bool: 13 | return ( 14 | event.symbol == actor.symbol 15 | and event.timeframe == actor.timeframe 16 | and event.datasource == actor.datasource 17 | ) 18 | -------------------------------------------------------------------------------- /core/actors/policy/signal.py: -------------------------------------------------------------------------------- 1 | from core.events.market import NewMarketDataReceived 2 | 3 | from .event import EventPolicy 4 | 5 | 6 | class SignalPolicy(EventPolicy): 7 | @classmethod 8 | def should_process(cls, actor, event: NewMarketDataReceived) -> bool: 9 | return ( 10 | event.symbol == actor.symbol 11 | and event.timeframe == actor.timeframe 12 | and event.bar.closed 13 | ) 14 | -------------------------------------------------------------------------------- /core/actors/policy/strategy.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | from .event import EventPolicy 4 | 5 | 6 | class StrategyPolicy(EventPolicy): 7 | @classmethod 8 | def should_process(cls, actor, event) -> bool: 9 | symbol, timeframe = cls._get_event_key(event) 10 | return actor.symbol == symbol and actor.timeframe == timeframe 11 | 12 | @classmethod 13 | def _get_event_key(cls, event: Any): 14 | key = cls._extract_key(event) 15 | 16 | if not all(hasattr(key, attr) for attr in ("symbol", "timeframe")): 17 | raise AttributeError("Key does not have 'symbol' or 'timeframe' attributes") 18 | 19 | return key.symbol, key.timeframe 20 | 21 | @staticmethod 22 | def _extract_key(event: Any): 23 | if hasattr(event, "signal"): 24 | return event.signal 25 | elif hasattr(event, "position") and hasattr(event.position, "signal"): 26 | return event.position.signal 27 | 28 | return event 29 | -------------------------------------------------------------------------------- /core/actors/state/__init__.py: -------------------------------------------------------------------------------- 1 | from ._memory import InMemory 2 | 3 | __all__ = [InMemory] 4 | -------------------------------------------------------------------------------- /core/actors/state/_signal.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from typing import Any, Callable, List 3 | 4 | 5 | class Signal: 6 | def __init__(self): 7 | self._subscribers: List[Callable[..., Any]] = [] 8 | 9 | def connect(self, subscriber: Callable[..., Any]) -> None: 10 | self._subscribers.append(subscriber) 11 | 12 | def emit(self, *args, **kwargs) -> None: 13 | tasks = [] 14 | 15 | for subscriber in self._subscribers: 16 | if asyncio.iscoroutinefunction(subscriber): 17 | tasks.append(subscriber(*args, **kwargs)) 18 | else: 19 | subscriber(*args, **kwargs) 20 | 21 | if tasks: 22 | asyncio.create_task(self._run_async_subscribers(tasks)) 23 | 24 | @staticmethod 25 | async def _run_async_subscribers(tasks: List[asyncio.Future]) -> None: 26 | await asyncio.gather(*tasks) 27 | -------------------------------------------------------------------------------- /core/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/commands/__init__.py -------------------------------------------------------------------------------- /core/commands/account.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events._base import EventMeta 4 | from core.groups.command import CommandGroup 5 | 6 | from ._base import Command 7 | 8 | 9 | @dataclass(frozen=True) 10 | class AccountCommand(Command): 11 | meta: EventMeta = field( 12 | default_factory=lambda: EventMeta(priority=4, group=CommandGroup.account), 13 | init=False, 14 | ) 15 | 16 | 17 | @dataclass(frozen=True) 18 | class UpdateAccountSize(AccountCommand): 19 | amount: float 20 | -------------------------------------------------------------------------------- /core/commands/broker.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events._base import EventMeta 4 | from core.groups.command import CommandGroup 5 | from core.models.broker import MarginMode, PositionMode 6 | from core.models.datasource_type import DataSourceType 7 | from core.models.symbol import Symbol 8 | 9 | from ._base import Command 10 | 11 | 12 | @dataclass(frozen=True) 13 | class BrokerCommand(Command): 14 | meta: EventMeta = field( 15 | default_factory=lambda: EventMeta(priority=5, group=CommandGroup.broker), 16 | init=False, 17 | ) 18 | 19 | 20 | @dataclass(frozen=True) 21 | class UpdateSymbolSettings(BrokerCommand): 22 | datasource: DataSourceType 23 | symbol: Symbol 24 | leverage: int 25 | position_mode: PositionMode 26 | margin_mode: MarginMode 27 | -------------------------------------------------------------------------------- /core/commands/factor.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events._base import EventMeta 4 | from core.groups.command import CommandGroup 5 | from core.models.cap import CapType 6 | from core.models.datasource_type import DataSourceType 7 | 8 | from ._base import Command 9 | 10 | 11 | @dataclass(frozen=True) 12 | class FactorCommand(Command): 13 | meta: EventMeta = field( 14 | default_factory=lambda: EventMeta(priority=6, group=CommandGroup.factor), 15 | init=False, 16 | ) 17 | 18 | 19 | @dataclass(frozen=True) 20 | class InitGeneration(FactorCommand): 21 | datasource: DataSourceType 22 | cap: CapType 23 | 24 | 25 | @dataclass(frozen=True) 26 | class EnvolveGeneration(FactorCommand): 27 | datasource: DataSourceType 28 | cap: CapType 29 | -------------------------------------------------------------------------------- /core/commands/market.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.command import CommandGroup 5 | from core.models.datasource_type import DataSourceType 6 | from core.models.entity.bar import Bar 7 | from core.models.symbol import Symbol 8 | from core.models.timeframe import Timeframe 9 | 10 | from ._base import Command 11 | 12 | 13 | @dataclass(frozen=True) 14 | class MarketCommand(Command): 15 | symbol: Symbol 16 | timeframe: Timeframe 17 | datasource: DataSourceType 18 | meta: EventMeta = field( 19 | default_factory=lambda: EventMeta(priority=2, group=CommandGroup.market), 20 | init=False, 21 | ) 22 | 23 | 24 | @dataclass(frozen=True) 25 | class IngestMarketData(MarketCommand): 26 | bar: Bar 27 | -------------------------------------------------------------------------------- /core/commands/portfolio.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events._base import EventMeta 4 | from core.groups.command import CommandGroup 5 | 6 | from ._base import Command 7 | 8 | 9 | @dataclass(frozen=True) 10 | class PortfolioCommand(Command): 11 | meta: EventMeta = field( 12 | default_factory=lambda: EventMeta(priority=3, group=CommandGroup.portfolio), 13 | init=False, 14 | ) 15 | 16 | 17 | @dataclass(frozen=True) 18 | class PortfolioReset(PortfolioCommand): 19 | pass 20 | 21 | 22 | @dataclass(frozen=True) 23 | class StrategyReset(PortfolioCommand): 24 | pass 25 | -------------------------------------------------------------------------------- /core/commands/position.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events._base import EventMeta 4 | from core.groups.command import CommandGroup 5 | from core.models.entity.position import Position 6 | 7 | from ._base import Command 8 | 9 | 10 | @dataclass(frozen=True) 11 | class PositionCommand(Command): 12 | meta: EventMeta = field( 13 | default_factory=lambda: EventMeta(priority=1, group=CommandGroup.position), 14 | init=False, 15 | ) 16 | 17 | 18 | @dataclass(frozen=True) 19 | class OpenPosition(PositionCommand): 20 | position: Position 21 | 22 | 23 | @dataclass(frozen=True) 24 | class ClosePosition(PositionCommand): 25 | position: Position 26 | -------------------------------------------------------------------------------- /core/events/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/events/__init__.py -------------------------------------------------------------------------------- /core/events/_base.py: -------------------------------------------------------------------------------- 1 | from dataclasses import asdict, dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | 5 | 6 | @dataclass(frozen=True) 7 | class Event: 8 | meta: EventMeta 9 | 10 | def to_dict(self): 11 | res = asdict(self) 12 | res["meta"]["name"] = self.__class__.__name__ 13 | return res 14 | 15 | 16 | @dataclass(frozen=True) 17 | class EventEnded(Event): 18 | meta: EventMeta = field(default_factory=lambda: EventMeta(priority=1)) 19 | -------------------------------------------------------------------------------- /core/events/account.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.event import EventGroup 5 | 6 | from ._base import Event 7 | 8 | 9 | @dataclass(frozen=True) 10 | class AccountUpdated(Event): 11 | amount: float 12 | meta: EventMeta = field( 13 | default_factory=lambda: EventMeta(priority=7, group=EventGroup.account), 14 | init=False, 15 | ) 16 | 17 | 18 | @dataclass(frozen=True) 19 | class PortfolioAccountUpdated(AccountUpdated): 20 | pass 21 | 22 | 23 | @dataclass(frozen=True) 24 | class PositionAccountUpdated(AccountUpdated): 25 | pass 26 | -------------------------------------------------------------------------------- /core/events/backtest.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.event import EventGroup 5 | from core.models.strategy import Strategy 6 | from core.models.symbol import Symbol 7 | from core.models.timeframe import Timeframe 8 | 9 | from ._base import Event 10 | 11 | 12 | @dataclass(frozen=True) 13 | class BacktestEvent(Event): 14 | symbol: Symbol 15 | timeframe: Timeframe 16 | strategy: Strategy 17 | meta: EventMeta = field( 18 | default_factory=lambda: EventMeta(priority=6, group=EventGroup.backtest), 19 | init=False, 20 | ) 21 | 22 | 23 | @dataclass(frozen=True) 24 | class BacktestStarted(BacktestEvent): 25 | pass 26 | 27 | 28 | @dataclass(frozen=True) 29 | class BacktestEnded(BacktestEvent): 30 | pass 31 | -------------------------------------------------------------------------------- /core/events/meta.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from dataclasses import dataclass, field 3 | from datetime import datetime 4 | 5 | from core.groups.event import EventGroup 6 | 7 | 8 | @dataclass 9 | class EventMeta: 10 | key: str = field(default_factory=lambda: str(uuid.uuid4())) 11 | timestamp: int = field(default_factory=lambda: datetime.now().timestamp()) 12 | priority: int = field(default_factory=lambda: 0) 13 | version: int = field(default_factory=lambda: 1) 14 | group: EventGroup = field(default_factory=lambda: EventGroup.service) 15 | -------------------------------------------------------------------------------- /core/events/risk.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.event import EventGroup 5 | from core.models.entity.signal import Signal 6 | 7 | from ._base import Event 8 | 9 | 10 | @dataclass(frozen=True) 11 | class RiskEvent(Event): 12 | signal: Signal 13 | meta: EventMeta = field( 14 | default_factory=lambda: EventMeta(priority=1, group=EventGroup.risk), init=False 15 | ) 16 | 17 | def to_dict(self): 18 | parent_dict = super().to_dict() 19 | 20 | current_dict = { 21 | "signal": self.signal.to_dict(), 22 | } 23 | 24 | return {**parent_dict, **current_dict} 25 | 26 | 27 | @dataclass(frozen=True) 28 | class RiskLongThresholdBreached(RiskEvent): 29 | pass 30 | 31 | 32 | @dataclass(frozen=True) 33 | class RiskShortThresholdBreached(RiskEvent): 34 | pass 35 | -------------------------------------------------------------------------------- /core/events/system.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | from typing import List 3 | 4 | from core.events.meta import EventMeta 5 | from core.groups.event import EventGroup 6 | from core.models.strategy import Strategy 7 | 8 | from ._base import Event 9 | 10 | 11 | @dataclass(frozen=True) 12 | class SystemEvent(Event): 13 | meta: EventMeta = field( 14 | default_factory=lambda: EventMeta(priority=8, group=EventGroup.system), 15 | init=False, 16 | ) 17 | 18 | 19 | @dataclass(frozen=True) 20 | class DeployStrategy(SystemEvent): 21 | strategy: List[Strategy] 22 | -------------------------------------------------------------------------------- /core/events/trade.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.event import EventGroup 5 | from core.models.strategy import Strategy 6 | from core.models.symbol import Symbol 7 | from core.models.timeframe import Timeframe 8 | 9 | from ._base import Event 10 | 11 | 12 | @dataclass(frozen=True) 13 | class TradeEvent(Event): 14 | symbol: Symbol 15 | timeframe: Timeframe 16 | strategy: Strategy 17 | meta: EventMeta = field( 18 | default_factory=lambda: EventMeta(priority=6, group=EventGroup.backtest), 19 | init=False, 20 | ) 21 | 22 | 23 | @dataclass(frozen=True) 24 | class TradeStarted(TradeEvent): 25 | pass 26 | -------------------------------------------------------------------------------- /core/groups/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/groups/__init__.py -------------------------------------------------------------------------------- /core/groups/command.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class CommandGroup(Enum): 5 | account = auto() 6 | broker = auto() 7 | portfolio = auto() 8 | market = auto() 9 | position = auto() 10 | factor = auto() 11 | 12 | def __str__(self): 13 | return self.name 14 | -------------------------------------------------------------------------------- /core/groups/event.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class EventGroup(Enum): 5 | account = auto() 6 | backtest = auto() 7 | market = auto() 8 | portfolio = auto() 9 | position = auto() 10 | risk = auto() 11 | service = auto() 12 | signal = auto() 13 | system = auto() 14 | 15 | def __str__(self): 16 | return self.name 17 | -------------------------------------------------------------------------------- /core/groups/query.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class QueryGroup(Enum): 5 | account = auto() 6 | broker = auto() 7 | position = auto() 8 | portfolio = auto() 9 | copilot = auto() 10 | market = auto() 11 | ta = auto() 12 | factor = auto() 13 | 14 | def __str__(self): 15 | return self.name 16 | -------------------------------------------------------------------------------- /core/groups/tasks.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class TasksGroup(Enum): 5 | feed = auto() 6 | 7 | def __str__(self): 8 | return self.name 9 | -------------------------------------------------------------------------------- /core/interfaces/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/interfaces/__init__.py -------------------------------------------------------------------------------- /core/interfaces/abstract_config.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Dict, Union 3 | 4 | ConfigType = Dict[str, Union[str, float]] 5 | 6 | 7 | class AbstractConfig(ABC): 8 | @abstractmethod 9 | def load(self, path: str) -> None: 10 | pass 11 | 12 | @abstractmethod 13 | def get(self, prop: str) -> ConfigType: 14 | pass 15 | 16 | @abstractmethod 17 | def update(self, new_config: ConfigType) -> None: 18 | pass 19 | -------------------------------------------------------------------------------- /core/interfaces/abstract_datasource_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Any, Optional, Type, Union 3 | 4 | from .abstract_exchange import AbstractRestExchange, AbstractWSExchange 5 | 6 | DataSource = Union[AbstractRestExchange, AbstractWSExchange] 7 | 8 | 9 | class AbstractDataSourceFactory(ABC): 10 | @abstractmethod 11 | def register(self, source_type: Any, source_class: Optional[Type] = None) -> None: 12 | pass 13 | 14 | @abstractmethod 15 | def create(self, source_type: Any, **kwargs) -> DataSource: 16 | pass 17 | -------------------------------------------------------------------------------- /core/interfaces/abstract_event_manager.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | 3 | from core.event_decorators import eda 4 | 5 | 6 | @eda 7 | class AbstractEventManager(ABC): 8 | pass 9 | -------------------------------------------------------------------------------- /core/interfaces/abstract_executor_actor_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.interfaces.abstract_market_repository import AbstractMarketRepository 4 | from core.models.order_type import OrderType 5 | from core.models.symbol import Symbol 6 | from core.models.timeframe import Timeframe 7 | 8 | from .abstract_actor import AbstractActor 9 | 10 | 11 | class AbstractExecutorActorFactory(ABC): 12 | @abstractmethod 13 | def create_actor( 14 | self, 15 | type: OrderType, 16 | symbol: Symbol, 17 | timeframe: Timeframe, 18 | repository: AbstractMarketRepository, 19 | ) -> AbstractActor: 20 | pass 21 | -------------------------------------------------------------------------------- /core/interfaces/abstract_feed_actor_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.interfaces.abstract_actor import AbstractActor 4 | from core.models.datasource_type import DataSourceType 5 | from core.models.feed import FeedType 6 | from core.models.symbol import Symbol 7 | from core.models.timeframe import Timeframe 8 | 9 | 10 | class AbstractFeedActorFactory(ABC): 11 | @abstractmethod 12 | def create_actor( 13 | self, 14 | feed: FeedType, 15 | symbol: Symbol, 16 | timeframe: Timeframe, 17 | datasource: DataSourceType, 18 | ) -> AbstractActor: 19 | pass 20 | -------------------------------------------------------------------------------- /core/interfaces/abstract_llm_service.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class AbstractLLMService(ABC): 5 | @abstractmethod 6 | def call(self, system_prompt: str, user_prompt: str) -> str: 7 | pass 8 | -------------------------------------------------------------------------------- /core/interfaces/abstract_market_repository.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod 2 | 3 | from core.interfaces.abstract_event_manager import AbstractEventManager 4 | from core.models.entity.ohlcv import OHLCV 5 | from core.models.symbol import Symbol 6 | from core.models.timeframe import Timeframe 7 | 8 | 9 | class AbstractMarketRepository(AbstractEventManager): 10 | @abstractmethod 11 | def upsert(self, symbol: Symbol, timeframe: Timeframe, bar: OHLCV): 12 | pass 13 | 14 | @abstractmethod 15 | def find_next_bar(self, symbol: Symbol, timeframe: Timeframe, bar: OHLCV): 16 | pass 17 | 18 | @abstractmethod 19 | def ta(self, symbol: Symbol, timeframe: Timeframe, bar: OHLCV): 20 | pass 21 | -------------------------------------------------------------------------------- /core/interfaces/abstract_optimizer_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.interfaces.abstract_strategy_generator import AbstractStrategyGenerator 4 | from core.interfaces.abstract_strategy_optimization import AbstractStrategyOptimization 5 | from core.models.optimizer import Optimizer 6 | 7 | 8 | class AbstractStrategyOptimizerFactory(ABC): 9 | @abstractmethod 10 | def create( 11 | self, type: Optimizer, generator: AbstractStrategyGenerator 12 | ) -> AbstractStrategyOptimization: 13 | pass 14 | -------------------------------------------------------------------------------- /core/interfaces/abstract_order_size_strategy.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod 2 | 3 | from core.interfaces.abstract_event_manager import AbstractEventManager 4 | from core.models.entity.signal import Signal 5 | 6 | 7 | class AbstractOrderSizeStrategy(AbstractEventManager): 8 | @abstractmethod 9 | def calculate( 10 | self, 11 | signal: Signal, 12 | ) -> float: 13 | pass 14 | -------------------------------------------------------------------------------- /core/interfaces/abstract_position_actor_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.models.symbol import Symbol 4 | from core.models.timeframe import Timeframe 5 | 6 | from .abstract_actor import AbstractActor 7 | 8 | 9 | class AbstractPositionActorFactory(ABC): 10 | @abstractmethod 11 | def create_actor(self, symbol: Symbol, timeframe: Timeframe) -> AbstractActor: 12 | pass 13 | -------------------------------------------------------------------------------- /core/interfaces/abstract_position_manager.py: -------------------------------------------------------------------------------- 1 | from .abstract_event_manager import AbstractEventManager 2 | 3 | 4 | class AbstractPositionManager(AbstractEventManager): 5 | pass 6 | -------------------------------------------------------------------------------- /core/interfaces/abstract_position_risk_strategy.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import List, Tuple 3 | 4 | from core.models.entity.ohlcv import OHLCV 5 | from core.models.entity.signal import SignalSide 6 | 7 | 8 | class AbstractPositionRiskStrategy(ABC): 9 | @abstractmethod 10 | def next( 11 | self, 12 | side: SignalSide, 13 | entry_price: float, 14 | stop_loss_price: float, 15 | ohlcvs: List[Tuple[OHLCV]], 16 | ) -> float: 17 | pass 18 | -------------------------------------------------------------------------------- /core/interfaces/abstract_position_take_profit_strategy.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class AbstractPositionTakeProfitStrategy(ABC): 5 | @abstractmethod 6 | def next(self, entry_price: float, stop_loss_price: float) -> float: 7 | pass 8 | -------------------------------------------------------------------------------- /core/interfaces/abstract_risk_actor_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.models.symbol import Symbol 4 | from core.models.timeframe import Timeframe 5 | 6 | from .abstract_actor import AbstractActor 7 | 8 | 9 | class AbstractRiskActorFactory(ABC): 10 | @abstractmethod 11 | def create_actor(self, symbol: Symbol, timeframe: Timeframe) -> AbstractActor: 12 | pass 13 | -------------------------------------------------------------------------------- /core/interfaces/abstract_secret_service.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class AbstractSecretService(ABC): 5 | @abstractmethod 6 | def get_api_key(self, identifier: str) -> str: 7 | pass 8 | 9 | @abstractmethod 10 | def get_secret(self, identifier: str) -> str: 11 | pass 12 | 13 | @abstractmethod 14 | def get_wss_public(self, identifier: str, type) -> str: 15 | pass 16 | 17 | @abstractmethod 18 | def get_wss_private(self, identifier: str) -> str: 19 | pass 20 | 21 | @abstractmethod 22 | def get_wss_order(self, identifier: str) -> str: 23 | pass 24 | -------------------------------------------------------------------------------- /core/interfaces/abstract_signal_actor_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.models.strategy import Strategy 4 | from core.models.symbol import Symbol 5 | from core.models.timeframe import Timeframe 6 | 7 | from .abstract_actor import AbstractActor 8 | 9 | 10 | class AbstractSignalActorFactory(ABC): 11 | @abstractmethod 12 | def create_actor( 13 | self, symbol: Symbol, timeframe: Timeframe, strategy: Strategy 14 | ) -> AbstractActor: 15 | pass 16 | -------------------------------------------------------------------------------- /core/interfaces/abstract_signal_service.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.models.strategy import Strategy 4 | from core.models.strategy_ref import StrategyRef 5 | 6 | 7 | class AbstractSignalService(ABC): 8 | @abstractmethod 9 | def register(self, strategy: Strategy) -> StrategyRef: 10 | pass 11 | -------------------------------------------------------------------------------- /core/interfaces/abstract_strategy_generator.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | 3 | 4 | class AbstractStrategyGenerator(ABC): 5 | pass 6 | -------------------------------------------------------------------------------- /core/interfaces/abstract_strategy_generator_factory.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from core.interfaces.abstract_strategy_generator import AbstractStrategyGenerator 4 | from core.models.symbol import Symbol 5 | 6 | 7 | class AbstractStrategyGeneratorFactory(ABC): 8 | @abstractmethod 9 | def create(self, symbols: list[Symbol]) -> AbstractStrategyGenerator: 10 | pass 11 | -------------------------------------------------------------------------------- /core/interfaces/abstract_strategy_optimization.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod 2 | 3 | from core.interfaces.abstract_event_manager import AbstractEventManager 4 | 5 | 6 | class AbstractStrategyOptimization(AbstractEventManager): 7 | @abstractmethod 8 | def init(self): 9 | pass 10 | 11 | @abstractmethod 12 | def optimize(self): 13 | pass 14 | 15 | @property 16 | @abstractmethod 17 | def population(self): 18 | pass 19 | 20 | @property 21 | @abstractmethod 22 | def generation(self): 23 | pass 24 | 25 | @property 26 | @abstractmethod 27 | def done(self) -> bool: 28 | pass 29 | -------------------------------------------------------------------------------- /core/interfaces/abstract_stream_strategy.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Any 3 | 4 | from core.interfaces.abstract_exchange import AbstractWSExchange 5 | 6 | 7 | class AbstractStreamStrategy(ABC): 8 | @abstractmethod 9 | async def subscribe(self, ws: AbstractWSExchange): 10 | pass 11 | 12 | @abstractmethod 13 | async def unsubscribe(self, ws: AbstractWSExchange): 14 | pass 15 | 16 | @abstractmethod 17 | def next(self, ws: AbstractWSExchange) -> Any: 18 | pass 19 | -------------------------------------------------------------------------------- /core/interfaces/abstract_system.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod 2 | 3 | from .abstract_event_manager import AbstractEventManager 4 | 5 | 6 | class AbstractSystem(AbstractEventManager): 7 | @abstractmethod 8 | def start(self): 9 | pass 10 | 11 | @abstractmethod 12 | def stop(self): 13 | pass 14 | -------------------------------------------------------------------------------- /core/interfaces/abstract_wasm_manager.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Tuple 3 | 4 | from wasmtime import Instance, Store 5 | 6 | from core.models.wasm_type import WasmType 7 | 8 | 9 | class AbstractWasmManager(ABC): 10 | @abstractmethod 11 | def get_instance(self, wasm_type: WasmType) -> Tuple[Instance, Store]: 12 | pass 13 | -------------------------------------------------------------------------------- /core/mixins/__init__.py: -------------------------------------------------------------------------------- 1 | from ._event_handler import EventHandlerMixin 2 | 3 | __all__ = [EventHandlerMixin] 4 | -------------------------------------------------------------------------------- /core/mixins/_event_handler.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from typing import Any, Callable, Dict, Type 3 | 4 | 5 | class EventHandlerMixin: 6 | def __init__(self): 7 | self._handlers: Dict[Type[Any], Callable] = {} 8 | 9 | def register_handler(self, event_type: Type[Any], handler: Callable): 10 | self._handlers[event_type] = handler 11 | 12 | async def handle_event(self, event: Any) -> Any: 13 | handler = self._handlers.get(type(event)) 14 | 15 | if handler: 16 | if asyncio.iscoroutinefunction(handler): 17 | return await handler(event) 18 | else: 19 | return await asyncio.to_thread(handler, event) 20 | 21 | return None 22 | -------------------------------------------------------------------------------- /core/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/models/__init__.py -------------------------------------------------------------------------------- /core/models/action.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class Action(Enum): 5 | GO_LONG = 1 6 | GO_SHORT = 2 7 | DO_NOTHING = 0 8 | 9 | @classmethod 10 | def from_raw(cls, value: float): 11 | for action in cls: 12 | if action.value == value: 13 | return action 14 | 15 | raise ValueError(f"No matching Action for float value: {value}") 16 | 17 | def __str__(self): 18 | return self.name 19 | -------------------------------------------------------------------------------- /core/models/broker.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class MarginMode(Enum): 5 | ISOLATED = "isolated" 6 | CROSS = "cross" 7 | 8 | 9 | class PositionMode(Enum): 10 | ONE_WAY = "one way" 11 | HEDGED = "hedged" 12 | 13 | 14 | class BrokerType(Enum): 15 | FUTURES = auto() 16 | -------------------------------------------------------------------------------- /core/models/candle.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class CandleTrendType(Enum): 5 | BOTTLE = 1 6 | DOUBLE_TROUBLE = 2 7 | GOLDEN = 3 8 | H = 4 9 | HEXAD = 5 10 | HIKKAKE = 6 11 | MARUBOZU = 7 12 | MASTER_CANDLE = 8 13 | QUINTUPLETS = 9 14 | SLINGSHOT = 10 15 | THREE_CANDLES = 11 16 | THREE_METHODS = 12 17 | TASUKI = 13 18 | THREE_ONE_TWO = 14 19 | 20 | def __str__(self): 21 | return self.name.upper() 22 | 23 | 24 | class CandleReversalType(Enum): 25 | DOJI = 1 26 | ENGULFING = 2 27 | EUPHORIA = 3 28 | HAMMER = 4 29 | HARAMIF = 5 30 | HARAMIS = 6 31 | KANGAROO = 7 32 | R = 8 33 | SPLIT = 9 34 | TWEEZERS = 10 35 | 36 | def __str__(self): 37 | return self.name.upper() 38 | -------------------------------------------------------------------------------- /core/models/candle_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class CandleType(Enum): 5 | BULLISH = auto() 6 | BEARISH = auto() 7 | NEUTRAL = auto() 8 | 9 | def __str__(self): 10 | return self.name.upper() 11 | -------------------------------------------------------------------------------- /core/models/cap.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class CapType(Enum): 5 | A = auto() 6 | B = auto() 7 | C = auto() 8 | -------------------------------------------------------------------------------- /core/models/datasource_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class DataSourceType(Enum): 5 | BYBIT = auto() 6 | 7 | def __str__(self): 8 | return self.name.upper() 9 | -------------------------------------------------------------------------------- /core/models/entity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/models/entity/__init__.py -------------------------------------------------------------------------------- /core/models/entity/bar.py: -------------------------------------------------------------------------------- 1 | from ._base import Entity 2 | from .ohlcv import OHLCV 3 | 4 | 5 | @Entity 6 | class Bar: 7 | ohlcv: OHLCV 8 | closed: bool 9 | -------------------------------------------------------------------------------- /core/models/entity/signal_risk.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from core.models.risk_type import SignalRiskType 4 | 5 | from ._base import Entity 6 | 7 | 8 | @Entity 9 | class SignalRisk: 10 | type: SignalRiskType = SignalRiskType.NONE 11 | tp: Optional[float] = None 12 | sl: Optional[float] = None 13 | -------------------------------------------------------------------------------- /core/models/feed.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class FeedType(Enum): 5 | HISTORICAL = auto() 6 | REALTIME = auto() 7 | -------------------------------------------------------------------------------- /core/models/indicator.py: -------------------------------------------------------------------------------- 1 | from dataclasses import asdict, dataclass, fields 2 | from enum import Enum 3 | from typing import Any 4 | 5 | 6 | @dataclass(frozen=True) 7 | class Indicator: 8 | type: Any 9 | 10 | def to_dict(self) -> dict: 11 | d = asdict(self) 12 | 13 | for field in fields(self): 14 | name = field.name 15 | value = d[name] 16 | 17 | if isinstance(value, dict) and "_value" in value: 18 | v = value["_value"] 19 | 20 | if isinstance(v, Enum): 21 | d[name] = v.value 22 | else: 23 | d[name] = value["_value"] 24 | elif isinstance(value, Enum): 25 | d[name] = value.value 26 | 27 | return d 28 | -------------------------------------------------------------------------------- /core/models/individual.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from .strategy import Strategy 4 | from .symbol import Symbol 5 | from .timeframe import Timeframe 6 | 7 | 8 | @dataclass 9 | class Individual: 10 | symbol: Symbol 11 | timeframe: Timeframe 12 | strategy: Strategy 13 | fitness: float = 0.0 14 | 15 | def update_fitness(self, value): 16 | self.fitness = value 17 | 18 | def __hash__(self) -> int: 19 | return hash(f"{self.symbol}_{self.timeframe}{self.strategy}") 20 | 21 | def __str__(self): 22 | return f"{self.symbol}_{self.timeframe}{self.strategy}" 23 | -------------------------------------------------------------------------------- /core/models/moving_average.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class MovingAverageType(Enum): 5 | ALMA = 1 6 | CAMA = 2 7 | DEMA = 3 8 | EMA = 4 9 | FRAMA = 5 10 | GMA = 6 11 | HMA = 7 12 | HEMA = 8 13 | KAMA = 9 14 | KJS = 10 15 | LSMA = 11 16 | MD = 12 17 | RMSMA = 13 18 | SINWMA = 14 19 | SLSMA = 15 20 | SMA = 16 21 | SMMA = 17 22 | T3 = 18 23 | TEMA = 19 24 | TL = 20 25 | TRIMA = 21 26 | ULTS = 22 27 | VIDYA = 23 28 | VWMA = 24 29 | VWEMA = 25 30 | WMA = 26 31 | ZLEMA = 27 32 | ZLSMA = 28 33 | ZLTEMA = 29 34 | ZLHMA = 30 35 | 36 | def __str__(self): 37 | return self.name.upper() 38 | -------------------------------------------------------------------------------- /core/models/optimizer.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class Optimizer(Enum): 5 | GENETIC = auto() 6 | -------------------------------------------------------------------------------- /core/models/protocol_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class ProtocolType(Enum): 5 | REST = auto() 6 | WS = auto() 7 | -------------------------------------------------------------------------------- /core/models/side.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class PositionSide(Enum): 5 | LONG = auto() 6 | SHORT = auto() 7 | 8 | def __str__(self): 9 | return self.name.upper() 10 | 11 | 12 | class SignalSide(Enum): 13 | BUY = auto() 14 | SELL = auto() 15 | 16 | def __str__(self): 17 | return self.name.upper() 18 | -------------------------------------------------------------------------------- /core/models/smooth.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class Smooth(Enum): 5 | EMA = 1 6 | SMA = 2 7 | SMMA = 3 8 | KAMA = 4 9 | HMA = 5 10 | WMA = 6 11 | ZLEMA = 7 12 | LSMA = 8 13 | TEMA = 9 14 | DEMA = 10 15 | UTLS = 11 16 | 17 | def __str__(self): 18 | return self.name.upper() 19 | 20 | 21 | class SmoothATR(Enum): 22 | EMA = 1 23 | SMMA = 3 24 | UTLS = 11 25 | 26 | def __str__(self): 27 | return self.name.upper() 28 | -------------------------------------------------------------------------------- /core/models/source.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class SourceType(Enum): 5 | CLOSE = 1 6 | HL2 = 2 7 | HLC3 = 3 8 | HLCC4 = 4 9 | OHLC4 = 5 10 | 11 | def __str__(self): 12 | return self.name.upper() 13 | -------------------------------------------------------------------------------- /core/models/strategy_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class StrategyType(Enum): 5 | TREND_FOLLOW = "Trend Follow" 6 | CONTRARIAN = "Contrarian" 7 | 8 | def __str__(self): 9 | return self.value 10 | -------------------------------------------------------------------------------- /core/models/symbol.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | 4 | @dataclass(frozen=True) 5 | class Symbol: 6 | name: str 7 | taker_fee: float 8 | maker_fee: float 9 | min_position_size: float 10 | min_price_size: float 11 | position_precision: int 12 | price_precision: int 13 | max_leverage: float 14 | 15 | def __eq__(self, other) -> bool: 16 | if isinstance(other, Symbol): 17 | return self.name == other.name 18 | 19 | return False 20 | 21 | def __hash__(self) -> int: 22 | return hash(self.name) 23 | 24 | def __str__(self): 25 | return self.name 26 | 27 | def __repr__(self) -> str: 28 | return f"Symbol({self})" 29 | -------------------------------------------------------------------------------- /core/models/wasm_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class WasmType(Enum): 5 | TREND = auto() 6 | TIMESERIES = auto() 7 | -------------------------------------------------------------------------------- /core/models/wss_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class WSType(Enum): 5 | PUBLIC = auto() 6 | PRIVATE = auto() 7 | ORDER = auto() 8 | -------------------------------------------------------------------------------- /core/queries/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/queries/__init__.py -------------------------------------------------------------------------------- /core/queries/_base.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from dataclasses import dataclass, field 3 | from typing import Generic, TypeVar, Union 4 | 5 | from core.events._base import Event 6 | from core.events.meta import EventMeta 7 | from core.result import Result 8 | 9 | T = TypeVar("T") 10 | 11 | 12 | @dataclass(frozen=True) 13 | class Query(Generic[T], Event): 14 | _response_event: asyncio.Event = field(default_factory=asyncio.Event, init=False) 15 | _response: Result[Union[T, None], Union[Exception, None]] = field( 16 | default=None, init=False 17 | ) 18 | meta: EventMeta = field(default_factory=lambda: EventMeta(priority=1), init=False) 19 | 20 | def set_response(self, response: Result): 21 | object.__setattr__(self, "_response", response) 22 | self._response_event.set() 23 | 24 | async def wait_for_response(self) -> Result: 25 | await self._response_event.wait() 26 | return self._response 27 | -------------------------------------------------------------------------------- /core/queries/account.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.query import QueryGroup 5 | 6 | from ._base import Query 7 | 8 | 9 | @dataclass(frozen=True) 10 | class GetBalance(Query[float]): 11 | currency: str = "USDT" 12 | meta: EventMeta = field( 13 | default_factory=lambda: EventMeta(priority=4, group=QueryGroup.account), 14 | init=False, 15 | ) 16 | -------------------------------------------------------------------------------- /core/queries/broker.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | from typing import List, Optional 3 | 4 | from core.events._base import EventMeta 5 | from core.groups.query import QueryGroup 6 | from core.models.cap import CapType 7 | from core.models.datasource_type import DataSourceType 8 | from core.models.symbol import Symbol 9 | 10 | from ._base import Query 11 | 12 | 13 | @dataclass(frozen=True) 14 | class GetSymbols(Query[List[Symbol]]): 15 | datasource: DataSourceType 16 | cap: Optional[CapType] = None 17 | meta: EventMeta = field( 18 | default_factory=lambda: EventMeta(priority=3, group=QueryGroup.broker), 19 | init=False, 20 | ) 21 | 22 | 23 | @dataclass(frozen=True) 24 | class GetSimilarSymbols(Query[List[Symbol]]): 25 | symbol: Symbol 26 | datasource: DataSourceType 27 | meta: EventMeta = field( 28 | default_factory=lambda: EventMeta(priority=3, group=QueryGroup.broker), 29 | init=False, 30 | ) 31 | -------------------------------------------------------------------------------- /core/queries/factor.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | from typing import Tuple 3 | 4 | from core.events.meta import EventMeta 5 | from core.groups.query import QueryGroup 6 | 7 | from ._base import Query 8 | 9 | 10 | @dataclass(frozen=True) 11 | class GetGeneration(Query[Tuple[list, float]]): 12 | meta: EventMeta = field( 13 | default_factory=lambda: EventMeta(priority=6, group=QueryGroup.factor), 14 | init=False, 15 | ) 16 | -------------------------------------------------------------------------------- /core/queries/portfolio.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | from typing import List 3 | 4 | from core.events._base import EventMeta 5 | from core.groups.query import QueryGroup 6 | from core.models.entity.portfolio import Performance 7 | from core.models.strategy import Strategy 8 | from core.models.symbol import Symbol 9 | from core.models.timeframe import Timeframe 10 | 11 | from ._base import Query 12 | 13 | 14 | @dataclass(frozen=True) 15 | class GetPortfolioRank(Query[List[Strategy]]): 16 | meta: EventMeta = field( 17 | default_factory=lambda: EventMeta(priority=2, group=QueryGroup.portfolio), 18 | init=False, 19 | ) 20 | 21 | 22 | @dataclass(frozen=True) 23 | class GetPortfolioPerformance(Query[Performance]): 24 | symbol: Symbol 25 | timeframe: Timeframe 26 | strategy: Strategy 27 | meta: EventMeta = field( 28 | default_factory=lambda: EventMeta(priority=2, group=QueryGroup.portfolio), 29 | init=False, 30 | ) 31 | -------------------------------------------------------------------------------- /core/result.py: -------------------------------------------------------------------------------- 1 | from typing import Generic, TypeVar 2 | 3 | T = TypeVar("T") 4 | E = TypeVar("E") 5 | 6 | 7 | class Result(Generic[T, E]): 8 | def __init__(self, ok: T = None, err: E = None): 9 | self.ok = ok 10 | self.err = err 11 | 12 | @classmethod 13 | def Ok(cls, value: T) -> "Result[T, E]": 14 | return cls(ok=value) 15 | 16 | @classmethod 17 | def Err(cls, error: E) -> "Result[T, E]": 18 | return cls(err=error) 19 | 20 | def is_ok(self) -> bool: 21 | return self.err is None 22 | 23 | def is_err(self) -> bool: 24 | return self.ok is None 25 | 26 | def unwrap(self) -> T: 27 | if self.is_err(): 28 | raise ValueError(f"Called unwrap on an Err value: {self.err}") 29 | return self.ok 30 | 31 | def unwrap_err(self) -> E: 32 | if self.is_ok(): 33 | raise ValueError(f"Called unwrap_err on an Ok value: {self.ok}") 34 | return self.err 35 | -------------------------------------------------------------------------------- /core/tasks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/core/tasks/__init__.py -------------------------------------------------------------------------------- /core/tasks/feed.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | 3 | from core.events.meta import EventMeta 4 | from core.groups.tasks import TasksGroup 5 | from core.models.datasource_type import DataSourceType 6 | from core.models.lookback import Lookback 7 | from core.models.symbol import Symbol 8 | from core.models.timeframe import Timeframe 9 | 10 | from ._base import Task 11 | 12 | 13 | @dataclass(frozen=True) 14 | class FeedTask(Task): 15 | symbol: Symbol 16 | timeframe: Timeframe 17 | datasource: DataSourceType 18 | meta: EventMeta = field( 19 | default_factory=lambda: EventMeta(priority=2, group=TasksGroup.feed), 20 | init=False, 21 | ) 22 | 23 | 24 | @dataclass(frozen=True) 25 | class StartHistoricalFeed(FeedTask): 26 | in_sample: Lookback 27 | out_sample: Lookback | None 28 | 29 | 30 | @dataclass(frozen=True) 31 | class StartRealtimeFeed(FeedTask): 32 | pass 33 | -------------------------------------------------------------------------------- /executor/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import OrderExecutorActorFactory 2 | 3 | __all__ = [OrderExecutorActorFactory] 4 | -------------------------------------------------------------------------------- /factor/__init__.py: -------------------------------------------------------------------------------- 1 | from ._actor import FactorActor 2 | 3 | __all__ = [FactorActor] 4 | -------------------------------------------------------------------------------- /factor/baseline/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/baseline/__init__.py -------------------------------------------------------------------------------- /factor/baseline/base.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from enum import Enum 3 | 4 | from core.models.indicator import Indicator 5 | 6 | 7 | class BaseLineType(Enum): 8 | Ma = "Ma" 9 | 10 | def __str__(self): 11 | return self.value.upper() 12 | 13 | 14 | @dataclass(frozen=True) 15 | class BaseLine(Indicator): 16 | type: BaseLineType 17 | -------------------------------------------------------------------------------- /factor/baseline/ma.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.moving_average import MovingAverageType 4 | from core.models.parameter import ( 5 | CategoricalParameter, 6 | Parameter, 7 | RandomParameter, 8 | StaticParameter, 9 | ) 10 | from core.models.source import SourceType 11 | 12 | from .base import BaseLine, BaseLineType 13 | 14 | 15 | @dataclass(frozen=True) 16 | class MaBaseLine(BaseLine): 17 | type: BaseLineType = BaseLineType.Ma 18 | source: Parameter = StaticParameter(SourceType.CLOSE) 19 | ma: Parameter = CategoricalParameter(MovingAverageType) 20 | period: Parameter = RandomParameter(12.0, 16.0) 21 | -------------------------------------------------------------------------------- /factor/confirm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/confirm/__init__.py -------------------------------------------------------------------------------- /factor/confirm/base.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from enum import Enum 3 | 4 | from core.models.indicator import Indicator 5 | 6 | 7 | class ConfirmType(Enum): 8 | BbC = "BbC" 9 | Braid = "Braid" 10 | Dumb = "Dumb" 11 | Dpo = "Dpo" 12 | Cci = "Cci" 13 | Cc = "Cc" 14 | Eom = "Eom" 15 | RsiSignalLine = "RsiSignalLine" 16 | RsiNeutrality = "RsiNeutrality" 17 | Stc = "Stc" 18 | Wpr = "Wpr" 19 | Didi = "Didi" 20 | 21 | def __str__(self): 22 | return self.value.upper() 23 | 24 | 25 | @dataclass(frozen=True) 26 | class Confirm(Indicator): 27 | type: ConfirmType 28 | -------------------------------------------------------------------------------- /factor/confirm/bb.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class BbConfirm(Confirm): 12 | type: Confirm = ConfirmType.BbC 13 | source: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth: Parameter = StaticParameter(Smooth.SMA) 15 | period: Parameter = StaticParameter(20.0) 16 | factor: Parameter = StaticParameter(2.0) 17 | -------------------------------------------------------------------------------- /factor/confirm/braid.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | CategoricalParameter, 5 | Parameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth, SmoothATR 9 | 10 | from .base import Confirm, ConfirmType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class BraidConfirm(Confirm): 15 | type: Confirm = ConfirmType.Braid 16 | smooth_type: Parameter = StaticParameter(Smooth.DEMA) 17 | fast_period: Parameter = StaticParameter(3.0) 18 | slow_period: Parameter = StaticParameter(14.0) 19 | open_period: Parameter = StaticParameter(7.0) 20 | strength: Parameter = StaticParameter(40.0) 21 | smooth_atr: Parameter = CategoricalParameter(SmoothATR) 22 | period_atr: Parameter = StaticParameter(14.0) 23 | -------------------------------------------------------------------------------- /factor/confirm/cc.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class CcConfirm(Confirm): 12 | type: Confirm = ConfirmType.Cc 13 | source: Parameter = StaticParameter(SourceType.CLOSE) 14 | period_fast: Parameter = StaticParameter(14.0) 15 | period_slow: Parameter = StaticParameter(28.0) 16 | smooth: Parameter = StaticParameter(Smooth.WMA) 17 | period_smooth: Parameter = StaticParameter(14.0) 18 | smooth_signal: Parameter = StaticParameter(Smooth.SMA) 19 | period_signal: Parameter = StaticParameter(14.0) 20 | -------------------------------------------------------------------------------- /factor/confirm/cci.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class CciConfirm(Confirm): 12 | type: Confirm = ConfirmType.Cci 13 | source: Parameter = StaticParameter(SourceType.HLC3) 14 | period: Parameter = StaticParameter(100.0) 15 | factor: Parameter = StaticParameter(0.015) 16 | smooth: Parameter = StaticParameter(Smooth.EMA) 17 | period_smooth: Parameter = StaticParameter(14.0) 18 | -------------------------------------------------------------------------------- /factor/confirm/didi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class DidiConfirm(Confirm): 12 | type: Confirm = ConfirmType.Didi 13 | source: Parameter = StaticParameter(SourceType.HL2) 14 | smooth: Parameter = StaticParameter(Smooth.SMA) 15 | period_medium: Parameter = StaticParameter(8.0) 16 | period_slow: Parameter = StaticParameter(40.0) 17 | smooth_signal: Parameter = StaticParameter(Smooth.EMA) 18 | period_signal: Parameter = StaticParameter(3.0) 19 | -------------------------------------------------------------------------------- /factor/confirm/dpo.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class DpoConfirm(Confirm): 12 | type: Confirm = ConfirmType.Dpo 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 15 | period: Parameter = StaticParameter(27.0) 16 | -------------------------------------------------------------------------------- /factor/confirm/dumb.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | 5 | from .base import Confirm, ConfirmType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class DumbConfirm(Confirm): 10 | type: ConfirmType = ConfirmType.Dumb 11 | period: Parameter = StaticParameter(10.0) 12 | -------------------------------------------------------------------------------- /factor/confirm/eom.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class EomConfirm(Confirm): 12 | type: ConfirmType = ConfirmType.Eom 13 | source_type: Parameter = StaticParameter(SourceType.HL2) 14 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 15 | period: Parameter = StaticParameter(16.0) 16 | -------------------------------------------------------------------------------- /factor/confirm/rsi_neutrality.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, RandomParameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class RsiNeutralityConfirm(Confirm): 12 | type: Confirm = ConfirmType.RsiNeutrality 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 15 | period: Parameter = StaticParameter(28.0) 16 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 17 | -------------------------------------------------------------------------------- /factor/confirm/rsi_signalline.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, RandomParameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class RsiSignalLineConfirm(Confirm): 12 | type: Confirm = ConfirmType.RsiSignalLine 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 15 | period: Parameter = StaticParameter(18.0) 16 | smooth_signal: Parameter = StaticParameter(Smooth.HMA) 17 | smooth_period: Parameter = StaticParameter(10.0) 18 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 19 | -------------------------------------------------------------------------------- /factor/confirm/stc.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class StcConfirm(Confirm): 12 | type: Confirm = ConfirmType.Stc 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 15 | fast_period: Parameter = StaticParameter(25.0) 16 | slow_period: Parameter = StaticParameter(50.0) 17 | cycle: Parameter = StaticParameter(10.0) 18 | d_first: Parameter = StaticParameter(3.0) 19 | d_second: Parameter = StaticParameter(3.0) 20 | -------------------------------------------------------------------------------- /factor/confirm/wpr.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Confirm, ConfirmType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class WprConfirm(Confirm): 12 | type: Confirm = ConfirmType.Wpr 13 | source: Parameter = StaticParameter(SourceType.CLOSE) 14 | period: Parameter = StaticParameter(28.0) 15 | smooth_signal: Parameter = StaticParameter(Smooth.SMA) 16 | period_signal: Parameter = StaticParameter(14.0) 17 | -------------------------------------------------------------------------------- /factor/generator/__init__.py: -------------------------------------------------------------------------------- 1 | from ._population import PopulationGenerator 2 | 3 | __all__ = [PopulationGenerator] 4 | -------------------------------------------------------------------------------- /factor/pulse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/pulse/__init__.py -------------------------------------------------------------------------------- /factor/pulse/adx.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, RandomParameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | 6 | from .base import Pulse, PulseType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class AdxPulse(Pulse): 11 | type: PulseType = PulseType.Adx 12 | smooth: Parameter = StaticParameter(Smooth.SMMA) 13 | period: Parameter = StaticParameter(15.0) 14 | period_di: Parameter = StaticParameter(15.0) 15 | threshold: Parameter = RandomParameter(0.0, 5.0, 1.0) 16 | -------------------------------------------------------------------------------- /factor/pulse/base.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from enum import Enum 3 | 4 | from core.models.indicator import Indicator 5 | 6 | 7 | class PulseType(Enum): 8 | Adx = "Adx" 9 | Dumb = "Dumb" 10 | Chop = "Chop" 11 | Nvol = "Nvol" 12 | Vo = "Vo" 13 | Tdfi = "Tdfi" 14 | Wae = "Wae" 15 | Yz = "Yz" 16 | Sqz = "Sqz" 17 | 18 | def __str__(self): 19 | return self.value.upper() 20 | 21 | 22 | @dataclass(frozen=True) 23 | class Pulse(Indicator): 24 | type: PulseType 25 | -------------------------------------------------------------------------------- /factor/pulse/chop.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | CategoricalParameter, 5 | Parameter, 6 | RandomParameter, 7 | StaticParameter, 8 | ) 9 | from core.models.smooth import SmoothATR 10 | 11 | from .base import Pulse, PulseType 12 | 13 | 14 | @dataclass(frozen=True) 15 | class ChopPulse(Pulse): 16 | type: PulseType = PulseType.Chop 17 | period: Parameter = StaticParameter(9.0) 18 | smooth_atr: Parameter = CategoricalParameter(SmoothATR) 19 | period_atr: Parameter = StaticParameter(1.0) 20 | threshold: Parameter = RandomParameter(0.0, 5.0, 1.0) 21 | -------------------------------------------------------------------------------- /factor/pulse/dumb.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | 5 | from .base import Pulse, PulseType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class DumbPulse(Pulse): 10 | type: PulseType = PulseType.Dumb 11 | period: Parameter = StaticParameter(10.0) 12 | -------------------------------------------------------------------------------- /factor/pulse/nvol.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import CategoricalParameter, Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | 6 | from .base import Pulse, PulseType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class NvolPulse(Pulse): 11 | type: PulseType = PulseType.Nvol 12 | smooth: Parameter = CategoricalParameter(Smooth) 13 | period: Parameter = StaticParameter(14.0) 14 | -------------------------------------------------------------------------------- /factor/pulse/sqz.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import CategoricalParameter, Parameter, StaticParameter 4 | from core.models.smooth import Smooth, SmoothATR 5 | from core.models.source import SourceType 6 | 7 | from .base import Pulse, PulseType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class SqzPulse(Pulse): 12 | type: PulseType = PulseType.Sqz 13 | source: Parameter = CategoricalParameter(SourceType) 14 | smooth: Parameter = StaticParameter(Smooth.SMA) 15 | period: Parameter = StaticParameter(20.0) 16 | smooth_atr: Parameter = CategoricalParameter(SmoothATR) 17 | period_atr: Parameter = StaticParameter(20.0) 18 | factor_bb: Parameter = StaticParameter(2.0) 19 | factor_kch: Parameter = StaticParameter(1.2) 20 | -------------------------------------------------------------------------------- /factor/pulse/tdfi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import CategoricalParameter, Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Pulse, PulseType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class TdfiPulse(Pulse): 12 | type: PulseType = PulseType.Tdfi 13 | source: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth: Parameter = CategoricalParameter(Smooth) 15 | period: Parameter = StaticParameter(8.0) 16 | n: Parameter = StaticParameter(3.0) 17 | -------------------------------------------------------------------------------- /factor/pulse/vo.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import CategoricalParameter, Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | 6 | from .base import Pulse, PulseType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class VoPulse(Pulse): 11 | type: PulseType = PulseType.Vo 12 | smooth: Parameter = CategoricalParameter(Smooth) 13 | period_fast: Parameter = StaticParameter(7.0) 14 | period_slow: Parameter = StaticParameter(13.0) 15 | -------------------------------------------------------------------------------- /factor/pulse/wae.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import CategoricalParameter, Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | 7 | from .base import Pulse, PulseType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class WaePulse(Pulse): 12 | type: PulseType = PulseType.Wae 13 | source: Parameter = StaticParameter(SourceType.CLOSE) 14 | smooth: Parameter = CategoricalParameter(Smooth) 15 | period_fast: Parameter = StaticParameter(10.0) 16 | period_slow: Parameter = StaticParameter(29.0) 17 | smooth_bb: Parameter = CategoricalParameter(Smooth) 18 | period_bb: Parameter = StaticParameter(13.0) 19 | factor: Parameter = StaticParameter(1.2) 20 | strength: Parameter = StaticParameter(69.0) 21 | -------------------------------------------------------------------------------- /factor/pulse/yz.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | 6 | from .base import Pulse, PulseType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class YzPulse(Pulse): 11 | type: PulseType = PulseType.Yz 12 | period: Parameter = StaticParameter(60.0) 13 | smooth_signal: Parameter = StaticParameter(Smooth.HMA) 14 | period_signal: Parameter = StaticParameter(12.0) 15 | -------------------------------------------------------------------------------- /factor/signal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/__init__.py -------------------------------------------------------------------------------- /factor/signal/bb/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/bb/__init__.py -------------------------------------------------------------------------------- /factor/signal/bb/macd.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class MacdBbSignal(Signal): 14 | type: SignalType = SignalType.MacdBb 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 17 | fast_period: Parameter = StaticParameter(8.0) 18 | slow_period: Parameter = StaticParameter(26.0) 19 | signal_period: Parameter = StaticParameter(9.0) 20 | bb_smooth: Parameter = StaticParameter(Smooth.SMA) 21 | bb_period: Parameter = StaticParameter(9.0) 22 | factor: Parameter = StaticParameter(0.6) 23 | -------------------------------------------------------------------------------- /factor/signal/bb/vwap.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class VwapBbSignal(Signal): 11 | type: SignalType = SignalType.VwapBb 12 | source_type: Parameter = StaticParameter(SourceType.HLC3) 13 | period: Parameter = StaticParameter(100.0) 14 | bb_smooth: Parameter = StaticParameter(Smooth.SMA) 15 | bb_period: Parameter = StaticParameter(50.0) 16 | factor: Parameter = StaticParameter(2.0) 17 | -------------------------------------------------------------------------------- /factor/signal/breakout/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/breakout/__init__.py -------------------------------------------------------------------------------- /factor/signal/breakout/dch_two_ma.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.moving_average import MovingAverageType 4 | from core.models.parameter import ( 5 | CategoricalParameter, 6 | Parameter, 7 | RandomParameter, 8 | StaticParameter, 9 | ) 10 | from core.models.source import SourceType 11 | from factor.signal.base import Signal, SignalType 12 | 13 | 14 | @dataclass(frozen=True) 15 | class DchMa2BreakoutSignal(Signal): 16 | type: SignalType = SignalType.DchMa2Breakout 17 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 18 | dch_period: Parameter = StaticParameter(20.0) 19 | ma: Parameter = CategoricalParameter(MovingAverageType) 20 | fast_period: Parameter = RandomParameter(10.0, 50.0, 10.0) 21 | slow_period: Parameter = RandomParameter(40.0, 60.0, 10.0) 22 | -------------------------------------------------------------------------------- /factor/signal/colorswitch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/colorswitch/__init__.py -------------------------------------------------------------------------------- /factor/signal/colorswitch/macd.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class MacdColorSwitchSignal(Signal): 14 | type: SignalType = SignalType.MacdColorSwitch 15 | source_type: Parameter = StaticParameter(SourceType.HLC3) 16 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 17 | fast_period: Parameter = StaticParameter(12.0) 18 | slow_period: Parameter = StaticParameter(26.0) 19 | signal_period: Parameter = StaticParameter(9.0) 20 | -------------------------------------------------------------------------------- /factor/signal/contrarian/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/contrarian/__init__.py -------------------------------------------------------------------------------- /factor/signal/contrarian/kch_a.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, RandomParameter, StaticParameter 4 | from core.models.smooth import Smooth, SmoothATR 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class KchASignal(Signal): 11 | type: SignalType = SignalType.KchA 12 | source: Parameter = StaticParameter(SourceType.CLOSE) 13 | smooth: Parameter = StaticParameter(Smooth.UTLS) 14 | period: Parameter = RandomParameter(20.0, 60.0, 10.0) 15 | smooth_atr: Parameter = StaticParameter(SmoothATR.UTLS) 16 | period_atr: Parameter = RandomParameter(20.0, 80.0, 10.0) 17 | factor: Parameter = RandomParameter(0.3, 2.0, 0.1) 18 | -------------------------------------------------------------------------------- /factor/signal/contrarian/kch_c.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth, SmoothATR 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class KchCSignal(Signal): 11 | type: SignalType = SignalType.KchC 12 | source: Parameter = StaticParameter(SourceType.HLC3) 13 | smooth: Parameter = StaticParameter(Smooth.EMA) 14 | period: Parameter = StaticParameter(20.0) 15 | smooth_atr: Parameter = StaticParameter(SmoothATR.SMMA) 16 | period_atr: Parameter = StaticParameter(20.0) 17 | factor: Parameter = StaticParameter(1.0) 18 | -------------------------------------------------------------------------------- /factor/signal/contrarian/rsi_c.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiCSignal(Signal): 15 | type: SignalType = SignalType.RsiC 16 | source: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth: Parameter = StaticParameter(Smooth.SMMA) 18 | period: Parameter = StaticParameter(14.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/contrarian/rsi_d.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiDSignal(Signal): 15 | type: SignalType = SignalType.RsiD 16 | source: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth: Parameter = StaticParameter(Smooth.SMMA) 18 | period: Parameter = StaticParameter(8.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/contrarian/rsi_nt.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiNtSignal(Signal): 15 | type: SignalType = SignalType.RsiNt 16 | source: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth: Parameter = StaticParameter(Smooth.SMMA) 18 | period: Parameter = StaticParameter(8.0) 19 | threshold: Parameter = RandomParameter(0.0, 1.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/contrarian/rsi_u.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiUSignal(Signal): 15 | type: SignalType = SignalType.RsiU 16 | source: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth: Parameter = StaticParameter(Smooth.SMMA) 18 | period: Parameter = StaticParameter(8.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/contrarian/rsi_v.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiVSignal(Signal): 15 | type: SignalType = SignalType.RsiV 16 | source: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth: Parameter = StaticParameter(Smooth.SMMA) 18 | period: Parameter = StaticParameter(8.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/contrarian/snatr.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, RandomParameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from factor.signal.base import Signal, SignalType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class SnatrSignal(Signal): 10 | type: SignalType = SignalType.Snatr 11 | smooth_type: Parameter = StaticParameter(Smooth.WMA) 12 | atr_period: Parameter = StaticParameter(60.0) 13 | atr_smooth_period: Parameter = StaticParameter(13.0) 14 | threshold: Parameter = RandomParameter(0.0, 0.2, 0.1) 15 | -------------------------------------------------------------------------------- /factor/signal/contrarian/stoch_e.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class StochESignal(Signal): 15 | type: SignalType = SignalType.StochE 16 | source: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth: Parameter = StaticParameter(Smooth.SMA) 18 | period: Parameter = StaticParameter(34.0) 19 | period_k: Parameter = StaticParameter(5.0) 20 | period_d: Parameter = StaticParameter(3.0) 21 | threshold: Parameter = RandomParameter(0.0, 1.0, 1.0) 22 | -------------------------------------------------------------------------------- /factor/signal/contrarian/tii_v.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class TiiVSignal(Signal): 11 | type: SignalType = SignalType.TiiV 12 | source: Parameter = StaticParameter(SourceType.CLOSE) 13 | smooth: Parameter = StaticParameter(Smooth.SMA) 14 | major_period: Parameter = StaticParameter(8.0) 15 | minor_period: Parameter = StaticParameter(2.0) 16 | -------------------------------------------------------------------------------- /factor/signal/flip/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/flip/__init__.py -------------------------------------------------------------------------------- /factor/signal/flip/ce.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import SmoothATR 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class CeFlipSignal(Signal): 14 | type: SignalType = SignalType.CeFlip 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | period: Parameter = StaticParameter(22.0) 17 | smooth_atr: Parameter = StaticParameter(SmoothATR.SMMA) 18 | period_atr: Parameter = StaticParameter(22.0) 19 | factor: Parameter = StaticParameter(3.0) 20 | -------------------------------------------------------------------------------- /factor/signal/flip/supertrend.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import SmoothATR 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class SupertrendFlipSignal(Signal): 11 | type: SignalType = SignalType.SupFlip 12 | source_type: Parameter = StaticParameter(SourceType.HL2) 13 | smooth_atr: Parameter = StaticParameter(SmoothATR.SMMA) 14 | period_atr: Parameter = StaticParameter(8.0) 15 | factor: Parameter = StaticParameter(0.86) 16 | -------------------------------------------------------------------------------- /factor/signal/ma/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/ma/__init__.py -------------------------------------------------------------------------------- /factor/signal/ma/ma2_rsi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.moving_average import MovingAverageType 4 | from core.models.parameter import ( 5 | CategoricalParameter, 6 | Parameter, 7 | RandomParameter, 8 | StaticParameter, 9 | ) 10 | from core.models.smooth import Smooth 11 | from core.models.source import SourceType 12 | from factor.signal.base import Signal, SignalType 13 | 14 | 15 | @dataclass(frozen=True) 16 | class Ma2RsiSignal(Signal): 17 | type: SignalType = SignalType.Ma2Rsi 18 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 19 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 20 | rsi_period: Parameter = StaticParameter(2.0) 21 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 22 | ma: Parameter = CategoricalParameter(MovingAverageType) 23 | fast_period: Parameter = RandomParameter(20.0, 50.0, 5.0) 24 | slow_period: Parameter = RandomParameter(30.0, 50.0, 5.0) 25 | -------------------------------------------------------------------------------- /factor/signal/ma/ma3_cross.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.moving_average import MovingAverageType 4 | from core.models.parameter import ( 5 | CategoricalParameter, 6 | Parameter, 7 | RandomParameter, 8 | StaticParameter, 9 | ) 10 | from core.models.source import SourceType 11 | from factor.signal.base import Signal, SignalType 12 | 13 | 14 | @dataclass(frozen=True) 15 | class Ma3CrossSignal(Signal): 16 | type: SignalType = SignalType.Ma3Cross 17 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 18 | ma: Parameter = CategoricalParameter(MovingAverageType) 19 | fast_period: Parameter = RandomParameter(5.0, 20.0, 5.0) 20 | medium_period: Parameter = RandomParameter(25.0, 80.0, 5.0) 21 | slow_period: Parameter = RandomParameter(85.0, 200.0, 5.0) 22 | -------------------------------------------------------------------------------- /factor/signal/ma/ma_cross.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from inspect import Parameter 3 | 4 | from core.models.moving_average import MovingAverageType 5 | from core.models.parameter import CategoricalParameter, RandomParameter, StaticParameter 6 | from core.models.source import SourceType 7 | from factor.signal.base import Signal, SignalType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class MaCrossSignal(Signal): 12 | type: SignalType = SignalType.MaCross 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | ma: Parameter = CategoricalParameter(MovingAverageType) 15 | period: Parameter = RandomParameter(10.0, 20.0, 5.0) 16 | -------------------------------------------------------------------------------- /factor/signal/ma/ma_quadruple.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from inspect import Parameter 3 | 4 | from core.models.moving_average import MovingAverageType 5 | from core.models.parameter import CategoricalParameter, RandomParameter, StaticParameter 6 | from core.models.source import SourceType 7 | from factor.signal.base import Signal, SignalType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class MaQuadrupleSignal(Signal): 12 | type: SignalType = SignalType.MaQuadruple 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | ma: Parameter = CategoricalParameter(MovingAverageType) 15 | period: Parameter = RandomParameter(40.0, 60.0, 10.0) 16 | -------------------------------------------------------------------------------- /factor/signal/ma/ma_surpass.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from inspect import Parameter 3 | 4 | from core.models.moving_average import MovingAverageType 5 | from core.models.parameter import CategoricalParameter, RandomParameter, StaticParameter 6 | from core.models.source import SourceType 7 | from factor.signal.base import Signal, SignalType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class MaSurpassSignal(Signal): 12 | type: SignalType = SignalType.MaSurpass 13 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 14 | ma: Parameter = CategoricalParameter(MovingAverageType) 15 | period: Parameter = RandomParameter(10.0, 60.0, 5.0) 16 | -------------------------------------------------------------------------------- /factor/signal/ma/ma_testing_ground.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.moving_average import MovingAverageType 4 | from core.models.parameter import ( 5 | CategoricalParameter, 6 | Parameter, 7 | RandomParameter, 8 | StaticParameter, 9 | ) 10 | from core.models.source import SourceType 11 | from factor.signal.base import Signal, SignalType 12 | 13 | 14 | @dataclass(frozen=True) 15 | class MaTestingGroundSignal(Signal): 16 | type: SignalType = SignalType.MaTestingGround 17 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 18 | ma: Parameter = CategoricalParameter(MovingAverageType) 19 | period: Parameter = RandomParameter(10.0, 60.0, 5.0) 20 | -------------------------------------------------------------------------------- /factor/signal/ma/vwap_cross.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.source import SourceType 5 | from factor.signal.base import Signal, SignalType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class VwapCrossSignal(Signal): 10 | type: SignalType = SignalType.VwapCross 11 | source_type: Parameter = StaticParameter(SourceType.HLC3) 12 | period: Parameter = StaticParameter(100.0) 13 | -------------------------------------------------------------------------------- /factor/signal/neutrality/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/neutrality/__init__.py -------------------------------------------------------------------------------- /factor/signal/neutrality/dso_cross.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class DsoNeutralityCrossSignal(Signal): 11 | type: Signal = SignalType.DsoNeutralityCross 12 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 13 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 14 | smooth_period: Parameter = StaticParameter(13.0) 15 | k_period: Parameter = StaticParameter(8.0) 16 | d_period: Parameter = StaticParameter(9.0) 17 | -------------------------------------------------------------------------------- /factor/signal/neutrality/rsi_cross.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiNeutralityCrossSignal(Signal): 15 | type: SignalType = SignalType.RsiNeutralityCross 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 18 | rsi_period: Parameter = StaticParameter(14.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/neutrality/rsi_pullback.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiNeutralityPullbackSignal(Signal): 15 | type: SignalType = SignalType.RsiNeutralityPullback 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 18 | rsi_period: Parameter = StaticParameter(14.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/neutrality/rsi_rejection.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiNeutralityRejectionSignal(Signal): 15 | type: SignalType = SignalType.RsiNeutralityRejection 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 18 | rsi_period: Parameter = StaticParameter(14.0) 19 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/neutrality/tii_cross.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class TiiNeutralityCrossSignal(Signal): 11 | type: SignalType = SignalType.TiiNeutralityCross 12 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 13 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 14 | major_period: Parameter = StaticParameter(40.0) 15 | minor_period: Parameter = StaticParameter(20.0) 16 | -------------------------------------------------------------------------------- /factor/signal/pattern/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/pattern/__init__.py -------------------------------------------------------------------------------- /factor/signal/pattern/ao_saucer.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class AoSaucerSignal(Signal): 14 | type: SignalType = SignalType.AoSaucer 15 | source_type: Parameter = StaticParameter(SourceType.HL2) 16 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 17 | fast_period: Parameter = StaticParameter(5.0) 18 | slow_period: Parameter = StaticParameter(34.0) 19 | -------------------------------------------------------------------------------- /factor/signal/pattern/candle_reversal.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.candle import CandleReversalType 4 | from core.models.parameter import CategoricalParameter, Parameter 5 | from factor.signal.base import Signal, SignalType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class CandlestickReversalSignal(Signal): 10 | type: SignalType = SignalType.CandlestickReversal 11 | candle: Parameter = CategoricalParameter(CandleReversalType) 12 | -------------------------------------------------------------------------------- /factor/signal/pattern/candle_trend.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.candle import CandleTrendType 4 | from core.models.parameter import CategoricalParameter, Parameter 5 | from factor.signal.base import Signal, SignalType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class CandlestickTrendSignal(Signal): 10 | type: SignalType = SignalType.CandlestickTrend 11 | candle: Parameter = CategoricalParameter(CandleTrendType) 12 | -------------------------------------------------------------------------------- /factor/signal/pattern/hl.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from factor.signal.base import Signal, SignalType 8 | 9 | 10 | @dataclass(frozen=True) 11 | class HighLowSignal(Signal): 12 | type: SignalType = SignalType.HighLow 13 | period: Parameter = StaticParameter(3.0) 14 | -------------------------------------------------------------------------------- /factor/signal/pattern/spread.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class SpreadSignal(Signal): 14 | type: SignalType = SignalType.Spread 15 | source: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth: Parameter = StaticParameter(Smooth.EMA) 17 | period_fast: Parameter = StaticParameter(6.0) 18 | period_slow: Parameter = StaticParameter(8.0) 19 | -------------------------------------------------------------------------------- /factor/signal/pullback/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/pullback/__init__.py -------------------------------------------------------------------------------- /factor/signal/pullback/supertrend.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import SmoothATR 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class SupertrendPullbackSignal(Signal): 11 | type: SignalType = SignalType.SupPullback 12 | source: Parameter = StaticParameter(SourceType.HL2) 13 | smooth_atr: Parameter = StaticParameter(SmoothATR.SMMA) 14 | period_atr: Parameter = StaticParameter(8.0) 15 | factor: Parameter = StaticParameter(0.86) 16 | -------------------------------------------------------------------------------- /factor/signal/signalline/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/signalline/__init__.py -------------------------------------------------------------------------------- /factor/signal/signalline/di.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class DiSignalLineSignal(Signal): 15 | type: SignalType = SignalType.DiSignalLine 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = StaticParameter(Smooth.WMA) 18 | period: Parameter = RandomParameter(10.0, 15.0, 1.0) 19 | signal_period: Parameter = RandomParameter(4.0, 8.0, 1.0) 20 | -------------------------------------------------------------------------------- /factor/signal/signalline/dso.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from core.models.source import SourceType 6 | from factor.signal.base import Signal, SignalType 7 | 8 | 9 | @dataclass(frozen=True) 10 | class DsoSignalLineSignal(Signal): 11 | type: Signal = SignalType.DsoSignalLine 12 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 13 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 14 | smooth_period: Parameter = StaticParameter(13.0) 15 | k_period: Parameter = StaticParameter(8.0) 16 | d_period: Parameter = StaticParameter(9.0) 17 | -------------------------------------------------------------------------------- /factor/signal/signalline/macd.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | CategoricalParameter, 5 | Parameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class MacdSignalLineSignal(Signal): 15 | type: SignalType = SignalType.MacdSignalLine 16 | source_type: Parameter = CategoricalParameter(SourceType) 17 | smooth_type: Parameter = CategoricalParameter(Smooth) 18 | fast_period: Parameter = StaticParameter(12.0) 19 | slow_period: Parameter = StaticParameter(26.0) 20 | signal_period: Parameter = StaticParameter(9.0) 21 | -------------------------------------------------------------------------------- /factor/signal/signalline/qstick.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class QstickSignalLineSignal(Signal): 14 | type: SignalType = SignalType.QstickSignalLine 15 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 16 | period: Parameter = RandomParameter(10.0, 15.0, 1.0) 17 | signal_period: Parameter = RandomParameter(4.0, 8.0, 1.0) 18 | -------------------------------------------------------------------------------- /factor/signal/signalline/rsi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class RsiSignalLineSignal(Signal): 15 | type: SignalType = SignalType.RsiSignalLine 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 18 | rsi_period: Parameter = RandomParameter(12.0, 15.0, 1.0) 19 | smooth_signal: Parameter = StaticParameter(Smooth.EMA) 20 | smooth_period: Parameter = RandomParameter(7.0, 10.0, 1.0) 21 | threshold: Parameter = RandomParameter(0.0, 3.0, 1.0) 22 | -------------------------------------------------------------------------------- /factor/signal/signalline/stoch.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, RandomParameter, StaticParameter 4 | from core.models.smooth import Smooth 5 | from factor.signal.base import Signal, SignalType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class StochSignalLineSignal(Signal): 10 | type: SignalType = SignalType.StochSignalLine 11 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 12 | period: Parameter = RandomParameter(13.0, 16.0, 1.0) 13 | k_period: Parameter = RandomParameter(1.0, 5.0, 1.0) 14 | d_period: Parameter = RandomParameter(3.0, 5.0, 1.0) 15 | -------------------------------------------------------------------------------- /factor/signal/signalline/trix.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class TrixSignalLineSignal(Signal): 14 | type: SignalType = SignalType.TrixSignalLine 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 17 | period: Parameter = StaticParameter(7.0) 18 | signal_period: Parameter = StaticParameter(9.0) 19 | -------------------------------------------------------------------------------- /factor/signal/signalline/tsi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class TsiSignalLineSignal(Signal): 14 | type: SignalType = SignalType.TsiSignalLine 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 17 | fast_period: Parameter = StaticParameter(13.0) 18 | slow_period: Parameter = StaticParameter(25.0) 19 | signal_period: Parameter = StaticParameter(13.0) 20 | -------------------------------------------------------------------------------- /factor/signal/twolinescross/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/twolinescross/__init__.py -------------------------------------------------------------------------------- /factor/signal/twolinescross/dmi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from factor.signal.base import Signal, SignalType 9 | 10 | 11 | @dataclass(frozen=True) 12 | class Dmi2LinesCrossSignal(Signal): 13 | type: SignalType = SignalType.Dmi2LinesCross 14 | smooth_type: Parameter = StaticParameter(Smooth.SMMA) 15 | adx_period: Parameter = StaticParameter(8.0) 16 | di_period: Parameter = StaticParameter(8.0) 17 | -------------------------------------------------------------------------------- /factor/signal/twolinescross/vi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import Parameter, StaticParameter 4 | from core.models.smooth import SmoothATR 5 | from factor.signal.base import Signal, SignalType 6 | 7 | 8 | @dataclass(frozen=True) 9 | class Vi2LinesCrossSignal(Signal): 10 | type: SignalType = SignalType.Vi2LinesCross 11 | period: Parameter = StaticParameter(6.0) 12 | smooth_atr: Parameter = StaticParameter(SmoothATR.UTLS) 13 | period_atr: Parameter = StaticParameter(1.0) 14 | -------------------------------------------------------------------------------- /factor/signal/zerocross/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/factor/signal/zerocross/__init__.py -------------------------------------------------------------------------------- /factor/signal/zerocross/ao.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class AoZeroCrossSignal(Signal): 14 | type: SignalType = SignalType.AoZeroCross 15 | source_type: Parameter = StaticParameter(SourceType.HL2) 16 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 17 | fast_period: Parameter = StaticParameter(5.0) 18 | slow_period: Parameter = StaticParameter(34.0) 19 | -------------------------------------------------------------------------------- /factor/signal/zerocross/bop.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from factor.signal.base import Signal, SignalType 9 | 10 | 11 | @dataclass(frozen=True) 12 | class BopZeroCrossSignal(Signal): 13 | type: SignalType = SignalType.BopZeroCross 14 | smooth_type: Parameter = StaticParameter(Smooth.SMA) 15 | smooth_period: Parameter = StaticParameter(14.0) 16 | -------------------------------------------------------------------------------- /factor/signal/zerocross/cc.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class CcZeroCrossSignal(Signal): 14 | type: SignalType = SignalType.CcZeroCross 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | fast_period: Parameter = StaticParameter(11.0) 17 | slow_period: Parameter = StaticParameter(14.0) 18 | smooth_type: Parameter = StaticParameter(Smooth.WMA) 19 | smooth_period: Parameter = StaticParameter(20.0) 20 | -------------------------------------------------------------------------------- /factor/signal/zerocross/cfo.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.source import SourceType 8 | from factor.signal.base import Signal, SignalType 9 | 10 | 11 | @dataclass(frozen=True) 12 | class CfoZeroCrossSignal(Signal): 13 | type: SignalType = SignalType.CfoZeroCross 14 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 15 | period: Parameter = StaticParameter(14.0) 16 | -------------------------------------------------------------------------------- /factor/signal/zerocross/di.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class DiZeroCrossSignal(Signal): 15 | type: SignalType = SignalType.DiZeroCross 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = StaticParameter(Smooth.WMA) 18 | period: Parameter = RandomParameter(10.0, 15.0, 1.0) 19 | -------------------------------------------------------------------------------- /factor/signal/zerocross/macd.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | CategoricalParameter, 5 | Parameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from core.models.source import SourceType 10 | from factor.signal.base import Signal, SignalType 11 | 12 | 13 | @dataclass(frozen=True) 14 | class MacdZeroCrossSignal(Signal): 15 | type: SignalType = SignalType.MacdZeroCross 16 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 17 | smooth_type: Parameter = CategoricalParameter(Smooth) 18 | fast_period: Parameter = StaticParameter(12.0) 19 | slow_period: Parameter = StaticParameter(26.0) 20 | signal_period: Parameter = StaticParameter(9.0) 21 | -------------------------------------------------------------------------------- /factor/signal/zerocross/mad.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class MadZeroCrossSignal(Signal): 14 | type: SignalType = SignalType.MadZeroCross 15 | source: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth: Parameter = StaticParameter(Smooth.SMA) 17 | period_fast: Parameter = StaticParameter(8.0) 18 | period_slow: Parameter = StaticParameter(23.0) 19 | -------------------------------------------------------------------------------- /factor/signal/zerocross/qstick.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | RandomParameter, 6 | StaticParameter, 7 | ) 8 | from core.models.smooth import Smooth 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class QstickZeroCrossSignal(Signal): 14 | type: SignalType = SignalType.QstickZeroCross 15 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 16 | period: Parameter = RandomParameter(10.0, 15.0, 1.0) 17 | -------------------------------------------------------------------------------- /factor/signal/zerocross/roc.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.source import SourceType 8 | from factor.signal.base import Signal, SignalType 9 | 10 | 11 | @dataclass(frozen=True) 12 | class RocZeroCrossSignal(Signal): 13 | type: SignalType = SignalType.RocZeroCross 14 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 15 | period: Parameter = StaticParameter(9.0) 16 | -------------------------------------------------------------------------------- /factor/signal/zerocross/trix.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class TrixZeroCrossSignal(Signal): 14 | type: SignalType = SignalType.TrixZeroCross 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 17 | period: Parameter = StaticParameter(7.0) 18 | -------------------------------------------------------------------------------- /factor/signal/zerocross/tsi.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.models.parameter import ( 4 | Parameter, 5 | StaticParameter, 6 | ) 7 | from core.models.smooth import Smooth 8 | from core.models.source import SourceType 9 | from factor.signal.base import Signal, SignalType 10 | 11 | 12 | @dataclass(frozen=True) 13 | class TsiZeroCrossSignal(Signal): 14 | type: SignalType = SignalType.TsiZeroCross 15 | source_type: Parameter = StaticParameter(SourceType.CLOSE) 16 | smooth_type: Parameter = StaticParameter(Smooth.EMA) 17 | fast_period: Parameter = StaticParameter(13.0) 18 | slow_period: Parameter = StaticParameter(25.0) 19 | -------------------------------------------------------------------------------- /feed/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import FeedActorFactory 2 | 3 | __all__ = [FeedActorFactory] 4 | -------------------------------------------------------------------------------- /feed/streams/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/feed/streams/__init__.py -------------------------------------------------------------------------------- /feed/streams/base/__init__.py: -------------------------------------------------------------------------------- 1 | from ._historical import AsyncHistoricalData 2 | from ._realtime import AsyncRealTimeData 3 | 4 | __all__ = [AsyncHistoricalData, AsyncRealTimeData] 5 | -------------------------------------------------------------------------------- /feed/streams/strategy/__init__.py: -------------------------------------------------------------------------------- 1 | from ._kline import KlineStreamStrategy 2 | from ._liquidation import LiquidationStreamStrategy 3 | from ._order import OrderStreamStrategy 4 | from ._order_book import OrderBookStreamStrategy 5 | from ._position import PositionStreamStrategy 6 | 7 | __all__ = [ 8 | KlineStreamStrategy, 9 | OrderBookStreamStrategy, 10 | LiquidationStreamStrategy, 11 | OrderStreamStrategy, 12 | PositionStreamStrategy, 13 | ] 14 | -------------------------------------------------------------------------------- /feed/streams/strategy/_liquidation.py: -------------------------------------------------------------------------------- 1 | from core.interfaces.abstract_exchange import AbstractWSExchange 2 | from core.interfaces.abstract_stream_strategy import AbstractStreamStrategy 3 | from core.models.symbol import Symbol 4 | 5 | 6 | class LiquidationStreamStrategy(AbstractStreamStrategy): 7 | def __init__(self, symbol: Symbol): 8 | super().__init__() 9 | self.symbol = symbol 10 | self.topic = None 11 | 12 | async def subscribe(self, ws: AbstractWSExchange): 13 | self.topic = ws.liquidation_topic(self.symbol) 14 | await ws.subscribe(self.topic) 15 | 16 | async def unsubscribe(self, ws: AbstractWSExchange): 17 | if self.topic: 18 | await ws.unsubscribe(self.topic) 19 | self.topic = None 20 | 21 | async def next(self, ws: AbstractWSExchange): 22 | if not self.topic: 23 | return [] 24 | 25 | message = await ws.get_message(self.topic) 26 | 27 | return [message] 28 | -------------------------------------------------------------------------------- /infrastructure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/infrastructure/__init__.py -------------------------------------------------------------------------------- /infrastructure/event_dispatcher/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/infrastructure/event_dispatcher/__init__.py -------------------------------------------------------------------------------- /infrastructure/event_store/__init__.py: -------------------------------------------------------------------------------- 1 | from .event_store import EventStore 2 | 3 | __all__ = [EventStore] 4 | -------------------------------------------------------------------------------- /infrastructure/event_store/event_encoder.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | from abc import ABC 4 | from enum import Enum 5 | from typing import Any 6 | 7 | import numpy as np 8 | 9 | from core.events._base import Event 10 | from core.models.indicator import Indicator 11 | 12 | 13 | class Encoder(json.JSONEncoder): 14 | def default(self, obj): 15 | if isinstance(obj, Enum): 16 | return obj.value 17 | if isinstance(obj, ABC): 18 | return obj.__class__.__name__ 19 | if isinstance(obj, np.ndarray): 20 | return obj.tolist() 21 | if isinstance(obj, Event): 22 | return obj.to_dict() 23 | if isinstance(obj, Indicator): 24 | return obj.to_dict() 25 | if isinstance(obj, type(Any)): 26 | return "Any" 27 | if isinstance(obj, asyncio.Future): 28 | return None 29 | 30 | return str(obj) 31 | -------------------------------------------------------------------------------- /infrastructure/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | 4 | def configure_logging(level: str): 5 | levels = { 6 | "CRITICAL": logging.CRITICAL, 7 | "ERROR": logging.ERROR, 8 | "WARNING": logging.WARNING, 9 | "INFO": logging.INFO, 10 | "DEBUG": logging.DEBUG, 11 | "NOTSET": logging.NOTSET, 12 | } 13 | 14 | log_level = levels.get(level, logging.INFO) 15 | 16 | logging.basicConfig(level=log_level) 17 | 18 | logging.getLogger("urllib3").setLevel(logging.WARNING) 19 | logging.getLogger("ccxt").setLevel(logging.WARNING) 20 | logging.getLogger("websockets").setLevel(logging.WARNING) 21 | -------------------------------------------------------------------------------- /infrastructure/shutdown.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | class GracefulShutdown: 5 | def __init__(self): 6 | self.exit_event = asyncio.Event() 7 | 8 | async def wait_for_exit_signal(self): 9 | await self.exit_event.wait() 10 | 11 | def exit(self, _signal, _frame): 12 | self.exit_event.set() 13 | -------------------------------------------------------------------------------- /infrastructure/telemetry/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/infrastructure/telemetry/__init__.py -------------------------------------------------------------------------------- /infrastructure/telemetry/throughput_monitor.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import time 3 | 4 | logger = logging.getLogger(__name__) 5 | 6 | 7 | class ThroughputMonitor: 8 | def __init__(self, events_to_log: int = 100): 9 | self.events_to_log = events_to_log 10 | self.start_time = time.monotonic() 11 | self.num_events = 0 12 | 13 | def event_processed(self): 14 | self.num_events += 1 15 | if self.num_events % self.events_to_log == 0: 16 | self._log_throughput() 17 | 18 | def _log_throughput(self): 19 | elapsed_time = time.monotonic() - self.start_time 20 | throughput = self.num_events / elapsed_time 21 | 22 | logger.debug(f"Throughput = {throughput:.2f} events/sec") 23 | 24 | self.num_events = 0 25 | self.start_time = time.monotonic() 26 | -------------------------------------------------------------------------------- /market/__init__.py: -------------------------------------------------------------------------------- 1 | from ._actor import MarketActor 2 | 3 | __all__ = [MarketActor] 4 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | strict = True 3 | warn_unused_configs = True -------------------------------------------------------------------------------- /notebooks/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .autoencoder_v1 import AutoEncoder 2 | 3 | __all__ = [AutoEncoder] 4 | -------------------------------------------------------------------------------- /notebooks/train/__init__.py: -------------------------------------------------------------------------------- 1 | from .checkpoint import CheckPoint 2 | from .common_trainer import CommonTrainer 3 | from .early_stop import EarlyStop 4 | from .snapshot import SnapshotManager 5 | from .trainer import Trainer 6 | 7 | __all__ = [Trainer, SnapshotManager, EarlyStop, CheckPoint, CommonTrainer] 8 | -------------------------------------------------------------------------------- /notebooks/train/checkpoint.py: -------------------------------------------------------------------------------- 1 | class CheckPoint: 2 | def __init__(self, snapshot_manager, snapshot_interval=5): 3 | self.snapshot_manager = snapshot_manager 4 | self.snapshot_interval = snapshot_interval 5 | 6 | def load_latest(self): 7 | self.snapshot_manager.load_latest() 8 | 9 | def check_and_save(self, epoch: int, improved=False): 10 | self.snapshot_manager.save(epoch, improved=improved) 11 | 12 | def periodic_save(self, epoch: int): 13 | if (epoch + 1) % self.snapshot_interval == 0: 14 | self.snapshot_manager.save(epoch, improved=False) 15 | -------------------------------------------------------------------------------- /notebooks/train/early_stop.py: -------------------------------------------------------------------------------- 1 | class EarlyStop: 2 | def __init__(self, patience=5): 3 | self.patience = patience 4 | self.best_loss = float("inf") 5 | self.epochs_without_improvement = 0 6 | 7 | def check(self, current_loss: float): 8 | if current_loss < self.best_loss: 9 | self.best_loss = current_loss 10 | self.epochs_without_improvement = 0 11 | 12 | return False 13 | else: 14 | self.epochs_without_improvement += 1 15 | 16 | if self.epochs_without_improvement >= self.patience: 17 | print("Early stopping triggered!") 18 | return True 19 | 20 | return False 21 | -------------------------------------------------------------------------------- /ocean/__init__.py: -------------------------------------------------------------------------------- 1 | from ._actor import OceanActor 2 | from ._gsim import SIM 3 | 4 | __all__ = [OceanActor, SIM] 5 | -------------------------------------------------------------------------------- /portfolio/__init__.py: -------------------------------------------------------------------------------- 1 | from ._actor import PortfolioActor 2 | 3 | __all__ = [PortfolioActor] 4 | -------------------------------------------------------------------------------- /position/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import PositionActorFactory 2 | 3 | __all__ = [PositionActorFactory] 4 | -------------------------------------------------------------------------------- /position/_factory.py: -------------------------------------------------------------------------------- 1 | from core.interfaces.abstract_position_actor_factory import AbstractPositionActorFactory 2 | from core.models.symbol import Symbol 3 | from core.models.timeframe import Timeframe 4 | 5 | from ._actor import PositionActor 6 | 7 | 8 | class PositionActorFactory(AbstractPositionActorFactory): 9 | def __init__(self): 10 | super().__init__() 11 | 12 | def create_actor(self, symbol: Symbol, timeframe: Timeframe): 13 | actor = PositionActor(symbol, timeframe) 14 | actor.start() 15 | return actor 16 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "quant" 3 | version = "0.1.0" 4 | description = "backtesting & trading" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "black>=24.8.0", 9 | "cachetools>=5.5.0", 10 | "ccxt>=4.4.7", 11 | "imbalanced-learn>=0.12.4", 12 | "ipykernel>=6.29.5", 13 | "lime>=0.2.0.1", 14 | "llama-cpp-python>=0.2.90", 15 | "matplotlib>=3.9.2", 16 | "mypy>=1.11.2", 17 | "networkx>=3.3", 18 | "numpy>=2.1.1", 19 | "orjson>=3.10.7", 20 | "pandas>=2.2.3", 21 | "python-dotenv>=1.0.1", 22 | "ruff>=0.6.7", 23 | "scikit-learn>=1.5.2", 24 | "scikit-optimize>=0.10.2", 25 | "scipy>=1.14.1", 26 | "seaborn>=0.13.2", 27 | "statsmodels>=0.14.4", 28 | "torch-geometric>=2.6.1", 29 | "torch>=2.4.1", 30 | "uuid>=1.30", 31 | "uvloop>=0.20.0", 32 | "wasmtime>=25.0.0", 33 | "websockets>=13.1", 34 | ] 35 | -------------------------------------------------------------------------------- /reef/__init__.py: -------------------------------------------------------------------------------- 1 | from ._actor import ReefActor 2 | 3 | __all__ = [ReefActor] 4 | -------------------------------------------------------------------------------- /reef/_order.py: -------------------------------------------------------------------------------- 1 | import time 2 | from dataclasses import dataclass, field, replace 3 | 4 | import numpy as np 5 | 6 | from core.models.datasource_type import DataSourceType 7 | from core.models.symbol import Symbol 8 | 9 | 10 | @dataclass(order=True, frozen=True, slots=True) 11 | class PQOrder: 12 | order_id: str = field(compare=False) 13 | symbol: Symbol = field(compare=False) 14 | datasource: DataSourceType = field(compare=False) 15 | timestamp: float = field(default_factory=lambda: time.time(), compare=True) 16 | ttl: float = field( 17 | default_factory=lambda: np.mean(np.random.exponential(3, size=1000)), 18 | compare=False, 19 | ) 20 | 21 | @property 22 | def is_expired(self) -> bool: 23 | return time.time() - self.timestamp > self.ttl 24 | 25 | def copy(self) -> "PQOrder": 26 | return replace(self, ttl=np.mean(np.random.exponential(3, size=1000))) 27 | -------------------------------------------------------------------------------- /risk/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import RiskActorFactory 2 | 3 | __all__ = [RiskActorFactory] 4 | -------------------------------------------------------------------------------- /risk/_factory.py: -------------------------------------------------------------------------------- 1 | from core.interfaces.abstract_config import AbstractConfig 2 | from core.interfaces.abstract_risk_actor_factory import AbstractRiskActorFactory 3 | from core.models.symbol import Symbol 4 | from core.models.timeframe import Timeframe 5 | 6 | from ._actor import RiskActor 7 | 8 | 9 | class RiskActorFactory(AbstractRiskActorFactory): 10 | def __init__(self, config_service: AbstractConfig): 11 | self.config_service = config_service 12 | 13 | def create_actor(self, symbol: Symbol, timeframe: Timeframe): 14 | actor = RiskActor( 15 | symbol, 16 | timeframe, 17 | self.config_service, 18 | ) 19 | actor.start() 20 | return actor 21 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | lint.ignore = ["E501", "C901", "B024"] 2 | lint.select = ["E","W","F","I", "B", "C4", "TCH", "TID"] -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.81.0" 3 | targets = ["wasm32-wasi"] -------------------------------------------------------------------------------- /service/__init__.py: -------------------------------------------------------------------------------- 1 | from ._env_secret import EnvironmentSecretService 2 | from ._llm import LLMService 3 | from ._signal import SignalService 4 | from ._timeseries import TimeSeriesService 5 | from ._wasm import WasmManager 6 | 7 | __all__ = [ 8 | EnvironmentSecretService, 9 | SignalService, 10 | LLMService, 11 | WasmManager, 12 | TimeSeriesService, 13 | ] 14 | -------------------------------------------------------------------------------- /sor/__init__.py: -------------------------------------------------------------------------------- 1 | from ._router import SmartRouter 2 | 3 | __all__ = [SmartRouter] 4 | -------------------------------------------------------------------------------- /strategy/__init__.py: -------------------------------------------------------------------------------- 1 | from ._factory import SignalActorFactory 2 | 3 | __all__ = [SignalActorFactory] 4 | -------------------------------------------------------------------------------- /strategy/_factory.py: -------------------------------------------------------------------------------- 1 | from core.interfaces.abstract_signal_actor_factory import AbstractSignalActorFactory 2 | from core.interfaces.abstract_signal_service import AbstractSignalService 3 | 4 | from ._actor import SignalActor 5 | 6 | 7 | class SignalActorFactory(AbstractSignalActorFactory): 8 | def __init__(self, service: AbstractSignalService): 9 | super().__init__() 10 | self.signal_service = service 11 | 12 | def create_actor(self, symbol, timeframe, strategy): 13 | actor = SignalActor(symbol, timeframe, strategy, self.signal_service) 14 | actor.start() 15 | return actor 16 | -------------------------------------------------------------------------------- /system/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/system/__init__.py -------------------------------------------------------------------------------- /system/context.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from core.interfaces.abstract_executor_actor_factory import AbstractExecutorActorFactory 4 | from core.interfaces.abstract_feed_actor_factory import AbstractFeedActorFactory 5 | from core.interfaces.abstract_position_actor_factory import AbstractPositionActorFactory 6 | from core.interfaces.abstract_risk_actor_factory import AbstractRiskActorFactory 7 | from core.interfaces.abstract_signal_actor_factory import AbstractSignalActorFactory 8 | from core.models.datasource_type import DataSourceType 9 | from infrastructure.config import ConfigService 10 | 11 | 12 | @dataclass(frozen=True) 13 | class SystemContext: 14 | signal_factory: AbstractSignalActorFactory 15 | position_factory: AbstractPositionActorFactory 16 | risk_factory: AbstractRiskActorFactory 17 | executor_factory: AbstractExecutorActorFactory 18 | feed_factory: AbstractFeedActorFactory 19 | datasource: DataSourceType 20 | config_service: ConfigService 21 | -------------------------------------------------------------------------------- /ta_lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | 4 | members = [ 5 | "benches", 6 | "core", 7 | "timeseries", 8 | "ffi", 9 | "indicators/momentum", 10 | "indicators/trend", 11 | "indicators/volatility", 12 | "indicators/volume", 13 | "patterns/candlestick", 14 | "patterns/osc", 15 | "patterns/bands", 16 | "patterns/channel", 17 | "patterns/trail", 18 | "price", 19 | "strategies/base", 20 | "strategies/trend_follow", 21 | "strategies/signal", 22 | "strategies/confirm", 23 | "strategies/pulse", 24 | "strategies/baseline", 25 | "strategies/indicator", 26 | "timeseries", 27 | "ffi", 28 | "patterns/osc", 29 | ] 30 | 31 | [workspace.package] 32 | authors = ["Melnik "] 33 | edition = "2021" 34 | license = "MIT" 35 | readme = "README.md" 36 | repository = "https://github.com/YieldLabs/quant" 37 | version = "0.1.0" 38 | 39 | [profile.release] 40 | opt-level = 3 41 | lto = true 42 | panic = "abort" -------------------------------------------------------------------------------- /ta_lib/benches/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "benches" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [[bench]] 13 | name = "indicators" 14 | harness = false 15 | path = "indicators.rs" 16 | 17 | [[bench]] 18 | name = "prices" 19 | harness = false 20 | path = "prices.rs" 21 | 22 | [[bench]] 23 | name = "patterns" 24 | harness = false 25 | path = "patterns.rs" 26 | 27 | [dependencies] 28 | core = { path = "../core" } 29 | candlestick = { path = "../patterns/candlestick" } 30 | momentum = { path = "../indicators/momentum" } 31 | price = { path = "../price" } 32 | trend = { path = "../indicators/trend" } 33 | volatility = { path = "../indicators/volatility" } 34 | volume = { path = "../indicators/volume" } 35 | base = { path = "../strategies/base" } 36 | 37 | [dev-dependencies] 38 | criterion = { version = "0.5" } -------------------------------------------------------------------------------- /ta_lib/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "core" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /ta_lib/core/src/constants.rs: -------------------------------------------------------------------------------- 1 | use crate::types::Scalar; 2 | 3 | pub const SCALE: Scalar = 100.; 4 | pub const NEUTRALITY: Scalar = 50.; 5 | pub const ZERO: Scalar = 0.; 6 | pub const ONE: Scalar = 1.; 7 | pub const HALF: Scalar = 0.5; 8 | pub const MINUS_ONE: Scalar = -1.; 9 | pub const NAN: Scalar = Scalar::NAN; 10 | pub const PI: Scalar = std::f32::consts::PI; 11 | -------------------------------------------------------------------------------- /ta_lib/core/src/fmt.rs: -------------------------------------------------------------------------------- 1 | use crate::series::Series; 2 | use std::fmt; 3 | 4 | impl fmt::Display for Series { 5 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 6 | write!(f, "[")?; 7 | for (i, item) in self.iter().enumerate() { 8 | if i > 0 { 9 | write!(f, ", ")?; 10 | } 11 | match item { 12 | Some(value) => write!(f, "{}", value)?, 13 | None => write!(f, "None")?, 14 | } 15 | } 16 | write!(f, "]") 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ta_lib/core/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod bitwise; 2 | mod cmp; 3 | mod constants; 4 | mod cross; 5 | mod extremum; 6 | mod fmt; 7 | mod from; 8 | mod macros; 9 | mod math; 10 | mod ops; 11 | mod series; 12 | mod smoothing; 13 | mod traits; 14 | mod types; 15 | 16 | pub mod prelude { 17 | pub use crate::constants::*; 18 | pub use crate::series::Series; 19 | pub use crate::smoothing::Smooth; 20 | pub use crate::traits::*; 21 | pub use crate::types::*; 22 | pub use crate::{iff, nz}; 23 | } 24 | 25 | pub use prelude::*; 26 | -------------------------------------------------------------------------------- /ta_lib/core/src/types.rs: -------------------------------------------------------------------------------- 1 | use crate::series::Series; 2 | 3 | pub type Scalar = f32; 4 | pub type Price = Series; 5 | pub type Rule = Series; 6 | pub type Period = usize; 7 | -------------------------------------------------------------------------------- /ta_lib/ffi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ffi" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | readme.workspace = true 7 | repository.workspace = true 8 | version.workspace = true 9 | 10 | [lib] 11 | crate-type = ["cdylib"] 12 | 13 | [dependencies] 14 | timeseries = { path = "../timeseries" } 15 | serde = { version = "1.0", default-features = false, features = ["derive"] } 16 | serde_json = { version = "1.0", default-features = false, features = ["alloc"] } 17 | once_cell = "1.19" -------------------------------------------------------------------------------- /ta_lib/ffi/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod timeseries; 2 | 3 | pub use timeseries::*; 4 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "momentum" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | price = { path = "../../price" } 15 | volatility = { path = "../volatility" } 16 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/cc.rs: -------------------------------------------------------------------------------- 1 | use crate::roc; 2 | use core::prelude::*; 3 | 4 | pub fn cc( 5 | source: &Price, 6 | period_fast: Period, 7 | period_slow: Period, 8 | smooth: Smooth, 9 | period_smooth: Period, 10 | ) -> Price { 11 | (roc(source, period_fast) + roc(source, period_slow)).smooth(smooth, period_smooth) 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn test_cc() { 20 | let close = Series::from([19.299, 19.305, 19.310, 19.316, 19.347, 19.355, 19.386]); 21 | let expected = vec![0.0, 0.0, 0.0, 0.0, 0.0, 0.52320945, 0.6957161]; 22 | 23 | let result: Vec = cc(&close, 3, 5, Smooth::WMA, 2).into(); 24 | 25 | assert_eq!(result, expected); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/cci.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn cci(source: &Price, period: Period, factor: Scalar) -> Price { 4 | source.smooth_dst(Smooth::SMA, period) / (factor * source.mad(period)) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | use price::prelude::*; 11 | 12 | #[test] 13 | fn test_cci() { 14 | let high = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 15 | let low = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 16 | let close = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 17 | let hlc3 = typical_price(&high, &low, &close); 18 | let expected = vec![0.0, 66.66667, 100.0, 100.0, 100.0]; 19 | 20 | let result: Vec = cci(&hlc3, 3, 0.015).into(); 21 | 22 | assert_eq!(result, expected); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/cfo.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn cfo(source: &Price, period: Period) -> Price { 4 | SCALE * (source - source.smooth(Smooth::LSMA, period)) / source 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_cfo() { 13 | let source = Series::from([ 14 | 2.0846, 2.0881, 2.0889, 2.0896, 2.0875, 2.0904, 2.0909, 2.0936, 15 | ]); 16 | let expected = vec![ 17 | 0.0, 18 | 0.0, 19 | -0.021537453, 20 | -0.0008100937, 21 | -0.022374226, 22 | 0.039839078, 23 | -0.019179303, 24 | 0.017605804, 25 | ]; 26 | 27 | let result: Vec = cfo(&source, 3).into(); 28 | 29 | assert_eq!(result, expected); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/cmo.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn cmo(source: &Price, period: Period) -> Price { 4 | let mom = source.change(1); 5 | let zero = Series::zero(source.len()); 6 | 7 | let hcls = iff!(mom.sgte(&ZERO), mom, zero); 8 | let lcls = iff!(mom.slt(&ZERO), mom.negate(), zero); 9 | 10 | let hsum = hcls.sum(period); 11 | let lsum = lcls.sum(period); 12 | 13 | SCALE * (&hsum - &lsum) / (&hsum + &lsum) 14 | } 15 | 16 | #[cfg(test)] 17 | mod tests { 18 | use super::*; 19 | 20 | #[test] 21 | fn test_cmo() { 22 | let close = Series::from([19.571, 19.606, 19.594, 19.575, 19.612, 19.631, 19.634]); 23 | let expected = vec![0.0, 100.0, 48.934788, 6.062883, 8.821632, 49.33496, 100.0]; 24 | 25 | let result: Vec = cmo(&close, 3).into(); 26 | 27 | assert_eq!(result, expected); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod bop; 2 | mod cc; 3 | mod cci; 4 | mod cfo; 5 | mod cmo; 6 | mod di; 7 | mod dmi; 8 | mod kst; 9 | mod macd; 10 | mod qstick; 11 | mod rex; 12 | mod roc; 13 | mod rsi; 14 | mod stc; 15 | mod stochosc; 16 | mod tdfi; 17 | mod tii; 18 | mod trix; 19 | mod tsi; 20 | mod uo; 21 | mod wpr; 22 | 23 | pub use bop::bop; 24 | pub use cc::cc; 25 | pub use cci::cci; 26 | pub use cfo::cfo; 27 | pub use cmo::cmo; 28 | pub use di::di; 29 | pub use dmi::dmi; 30 | pub use kst::kst; 31 | pub use macd::macd; 32 | pub use qstick::qstick; 33 | pub use rex::rex; 34 | pub use roc::roc; 35 | pub use rsi::rsi; 36 | pub use stc::stc; 37 | pub use stochosc::{dso, sso, stochosc}; 38 | pub use tdfi::tdfi; 39 | pub use tii::tii; 40 | pub use trix::trix; 41 | pub use tsi::tsi; 42 | pub use uo::uo; 43 | pub use wpr::wpr; 44 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/qstick.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn qstick(open: &Price, close: &Price, smooth: Smooth, period: Period) -> Price { 4 | (close - open).smooth(smooth, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_qstick() { 13 | let open = Series::from([19.310, 19.316, 19.347, 19.355, 19.386]); 14 | let close = Series::from([6.8445, 6.8560, 6.8565, 6.8590, 6.8530]); 15 | let period = 3; 16 | let expected = vec![-12.4655, -12.4627495, -12.4766245, -12.486312, -12.509655]; 17 | 18 | let result: Vec = qstick(&open, &close, Smooth::EMA, period).into(); 19 | 20 | assert_eq!(result, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/roc.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn roc(source: &Price, period: Period) -> Price { 4 | SCALE * source.change(period) / source.shift(period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_roc() { 13 | let source = Series::from([19.310, 19.316, 19.347, 19.355, 19.386]); 14 | let period = 3; 15 | let expected = vec![0.0, 0.0, 0.0, 0.23304027, 0.36239228]; 16 | 17 | let result: Vec = roc(&source, period).into(); 18 | 19 | assert_eq!(result, expected); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ta_lib/indicators/momentum/src/wpr.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn wpr(source: &Price, high: &Price, low: &Price, period: Period) -> Price { 4 | let hh = high.highest(period); 5 | let ll = low.lowest(period); 6 | 7 | SCALE * (source - &hh) / (hh - ll) 8 | } 9 | 10 | #[cfg(test)] 11 | mod tests { 12 | use super::*; 13 | 14 | #[test] 15 | fn test_wpr() { 16 | let high = Series::from([6.748, 6.838, 6.804, 6.782, 6.786]); 17 | let low = Series::from([6.655, 6.728, 6.729, 6.718, 6.732]); 18 | let source = Series::from([6.738, 6.780, 6.751, 6.766, 6.735]); 19 | let period = 3; 20 | 21 | let expected = vec![-10.752942, -31.693844, -47.541027, -60.00008, -80.23232]; 22 | 23 | let result: Vec = wpr(&source, &high, &low, period).into(); 24 | 25 | assert_eq!(result, expected); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trend" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | price = { path = "../../price" } 15 | volatility = { path = "../volatility" } 16 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/dema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn dema(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::DEMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_dema() { 13 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 14 | let expected = vec![1.0, 1.75, 2.75, 3.8125, 4.875]; 15 | 16 | let result: Vec = dema(&source, 3).into(); 17 | 18 | assert_eq!(result, expected); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/dpo.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn dpo(source: &Price, smooth: Smooth, period: Period) -> Price { 4 | let k = period / 2 + 1; 5 | 6 | source - source.smooth(smooth, period).shift(k) 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | use super::*; 12 | 13 | #[test] 14 | fn test_dpo() { 15 | let source = Series::from([2.0846, 2.0881, 2.0889, 2.0896, 2.0875, 2.0904, 2.0909]); 16 | let period = 3; 17 | let expected = vec![ 18 | 0.0, 19 | 0.0, 20 | 0.0043001175, 21 | 0.003250122, 22 | 0.000300169, 23 | 0.0015332699, 24 | 0.0022332668, 25 | ]; 26 | 27 | let result: Vec = dpo(&source, Smooth::SMA, period).into(); 28 | 29 | assert_eq!(result, expected); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/ema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn ema(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::EMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_ema() { 13 | let source = Series::from([ 14 | 6.5232, 6.5474, 6.5541, 6.5942, 6.5348, 6.4950, 6.5298, 6.5616, 6.5223, 6.5300, 6.5452, 15 | 6.5254, 6.5038, 6.4614, 6.4854, 6.4966, 16 | ]); 17 | let expected = vec![ 18 | 6.5232, 6.5353003, 6.5447, 6.5694504, 6.552125, 6.5235624, 6.526681, 6.544141, 19 | 6.5332203, 6.5316105, 6.5384054, 6.531903, 6.5178514, 6.489626, 6.487513, 6.492057, 20 | ]; 21 | 22 | let result: Vec = ema(&source, 3).into(); 23 | 24 | assert_eq!(result, expected); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/gma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn gma(source: &Price, period: Period) -> Price { 4 | source.log().smooth(Smooth::SMA, period).exp() 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_gma() { 13 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 14 | let expected = vec![ 15 | 1.0, 16 | std::f32::consts::SQRT_2, 17 | 1.8171206, 18 | 2.8844993, 19 | 3.9148676, 20 | ]; 21 | 22 | let result: Vec = gma(&source, 3).into(); 23 | 24 | assert_eq!(result, expected); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/hema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn hema(source: &Price, period: Period) -> Price { 4 | let period = (period as Scalar / 2.) as Period; 5 | 6 | 3. * source.smooth(Smooth::WMA, period) - 2. * source.smooth(Smooth::EMA, period) 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | use super::*; 12 | 13 | #[test] 14 | fn test_hema() { 15 | let source = Series::from([19.099, 19.079, 19.074, 19.139, 19.191]); 16 | let expected = vec![19.099003, 19.08567, 19.07122, 19.114738, 19.18724]; 17 | let period = 4; 18 | 19 | let result: Vec = hema(&source, period).into(); 20 | 21 | assert_eq!(result, expected); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/hma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn hma(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::HMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_hma() { 13 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 14 | let expected = vec![1.0, 2.3333335, 3.6666667, 4.666667, 5.6666665]; 15 | 16 | let result: Vec = hma(&source, 3).into(); 17 | 18 | assert_eq!(result, expected); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/kama.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn kama(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::KAMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_kama() { 13 | let source = Series::from([ 14 | 5.0788, 5.0897, 5.0958, 5.1023, 5.0998, 5.1046, 5.1014, 5.1141, 5.1355, 5.1477, 5.1675, 15 | 5.2000, 5.2169, 16 | ]); 17 | let expected = vec![ 18 | 5.0788, 5.0788455, 5.078916, 5.0892878, 5.0915785, 5.0941925, 5.09429, 5.0988545, 19 | 5.110461, 5.1269784, 5.144952, 5.1693687, 5.190451, 20 | ]; 21 | 22 | let result: Vec = kama(&source, 3).into(); 23 | 24 | assert_eq!(result, expected); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/lsma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn lsma(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::LSMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_lsma() { 13 | let source = Series::from([ 14 | 12.529, 12.504, 12.517, 12.542, 12.547, 12.577, 12.539, 12.577, 12.490, 12.490, 15 | ]); 16 | let expected = vec![ 17 | 12.529, 12.504, 12.510668, 12.54, 12.550336, 12.572831, 12.550328, 12.564322, 18 | 12.510831, 12.475489, 19 | ]; 20 | 21 | let result: Vec = lsma(&source, 3).into(); 22 | 23 | assert_eq!(result, expected); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/midpoint.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn midpoint(high: &Price, low: &Price, period: Period) -> Price { 4 | HALF * (high.highest(period) + low.lowest(period)) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_midpoint() { 13 | let high = Series::from([2.0859, 2.0881, 2.0889, 2.0896, 2.0896, 2.0907]); 14 | let low = Series::from([2.0846, 2.0846, 2.0881, 2.0886, 2.0865, 2.0875]); 15 | let expected = vec![2.08525, 2.08635, 2.08675, 2.0871, 2.08805, 2.0886]; 16 | 17 | let result: Vec = midpoint(&high, &low, 3).into(); 18 | 19 | assert_eq!(result, expected); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/rmsma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn rmsma(source: &Price, period: Period) -> Price { 4 | (source * source).smooth(Smooth::SMA, period).sqrt() 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_rmsma() { 13 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 14 | let expected = vec![1.0, 1.5811388, 2.1602468, 3.1091263, 4.082483]; 15 | 16 | let result: Vec = rmsma(&source, 3).into(); 17 | 18 | assert_eq!(result, expected); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/sinwma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn sinwma(source: &Price, period: Period) -> Price { 4 | let weights = (0..period) 5 | .rev() 6 | .map(|i| ((i as Scalar + 1.) * PI / (period + 1) as Scalar).sin()) 7 | .collect::>(); 8 | 9 | source.wg(&weights) 10 | } 11 | 12 | #[cfg(test)] 13 | mod tests { 14 | use super::*; 15 | 16 | #[test] 17 | fn test_sinwma() { 18 | let source = Series::from([ 19 | 0.01707, 0.01706, 0.01707, 0.01705, 0.01710, 0.01705, 0.01704, 0.01709, 20 | ]); 21 | let expected = [ 22 | 0.01707, 23 | 0.017064141, 24 | 0.017065858, 25 | 0.017061211, 26 | 0.017070502, 27 | 0.01707071, 28 | 0.017061714, 29 | 0.017057573, 30 | ]; 31 | 32 | let result: Vec = sinwma(&source, 3).into(); 33 | 34 | assert_eq!(result, expected); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/slsma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn slsma(source: &Price, period: Period) -> Price { 4 | let lsma = source.smooth(Smooth::LSMA, period); 5 | 6 | &lsma - (&lsma - lsma.smooth(Smooth::LSMA, period)) 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | use super::*; 12 | 13 | #[test] 14 | fn test_slsma() { 15 | let source = Series::from([ 16 | 12.529, 12.504, 12.517, 12.542, 12.547, 12.577, 12.539, 12.577, 12.490, 12.490, 17 | ]); 18 | let expected = vec![ 19 | 12.529, 12.504, 12.50539, 12.536224, 12.553506, 12.570806, 12.557826, 12.558236, 20 | 12.522075, 12.472454, 21 | ]; 22 | 23 | let result: Vec = slsma(&source, 3).into(); 24 | 25 | assert_eq!(result, expected); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/sma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn sma(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::SMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_sma() { 13 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 14 | let expected = vec![1.0, 1.5, 2.0, 3.0, 4.0]; 15 | 16 | let result: Vec = sma(&source, 3).into(); 17 | 18 | assert_eq!(result, expected); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/smma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn smma(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::SMMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_smma() { 13 | let source = Series::from([ 14 | 6.8575, 6.855, 6.858, 6.86, 6.8480, 6.8575, 6.864, 6.8565, 6.8455, 6.8450, 6.8365, 15 | 6.8310, 6.8355, 6.8360, 6.8345, 6.8285, 6.8395, 16 | ]); 17 | let expected = [ 18 | 6.8574996, 6.8566666, 6.857111, 6.8580737, 6.8547153, 6.8556433, 6.8584285, 6.857785, 19 | 6.85369, 6.8507934, 6.846029, 6.8410187, 6.839179, 6.8381195, 6.8369126, 6.8341084, 20 | 6.835905, 21 | ]; 22 | 23 | let result: Vec = smma(&source, 3).into(); 24 | 25 | assert_eq!(result, expected) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/tema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn tema(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::TEMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_tema() { 13 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 14 | let expected = vec![1.0, 1.875, 2.9375, 4.0, 5.03125]; 15 | 16 | let result: Vec = tema(&source, 3).into(); 17 | 18 | assert_eq!(result, expected); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/trima.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn trima(source: &Price, period: Period) -> Price { 4 | let period_half = HALF * period as Scalar; 5 | 6 | let n = period_half.ceil() as Period; 7 | let m = (period_half.floor() + 1.) as Period; 8 | 9 | source.smooth(Smooth::SMA, n).smooth(Smooth::SMA, m) 10 | } 11 | 12 | #[cfg(test)] 13 | mod tests { 14 | use super::*; 15 | 16 | #[test] 17 | fn test_trima() { 18 | let source = Series::from([1.0, 2.0, 3.0, 4.0, 5.0]); 19 | let expected = vec![1.0, 1.25, 2.0, 3.0, 4.0]; 20 | 21 | let result: Vec = trima(&source, 3).into(); 22 | 23 | assert_eq!(result, expected); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/ults.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn ults(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::ULTS, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_ults() { 13 | let source = Series::from([18.898, 18.838, 18.881, 18.925, 18.846]); 14 | let period = 3; 15 | let expected = vec![18.898, 18.85439, 18.853537, 18.922752, 18.880928]; 16 | 17 | let result: Vec = ults(&source, period).into(); 18 | 19 | assert_eq!(result, expected); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/vidya.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn vidya(source: &Price, period_fast: Period, period_slow: Period) -> Price { 4 | let k = source.std(period_fast) / source.std(period_slow); 5 | let alpha = 2. / ((period_fast + 1) as Scalar) * k.nz(Some(ZERO)); 6 | 7 | source.ew(&alpha, source) 8 | } 9 | 10 | #[cfg(test)] 11 | mod tests { 12 | use super::*; 13 | 14 | #[test] 15 | fn test_vidya() { 16 | let source = Series::from([100.0, 105.0, 116.25, 123.125, 129.0625]); 17 | let fast_period = 2; 18 | let slow_period = 3; 19 | let expected = vec![100.0, 103.33333, 110.46114, 114.34566, 119.90917]; 20 | 21 | let result: Vec = vidya(&source, fast_period, slow_period).into(); 22 | 23 | assert_eq!(result, expected); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/vwema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn vwema(source: &Price, volume: &Price, period: Period) -> Price { 4 | (source * volume).smooth(Smooth::EMA, period) / volume.smooth(Smooth::EMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_vwema() { 13 | let source = Series::from([100.0, 105.0, 116.25, 123.125, 129.0625]); 14 | let volume = Series::from([40.0, 50.0, 110.25, 90.33, 100.00]); 15 | let period = 3; 16 | let expected = vec![100.0, 102.77778, 112.34501, 118.14274, 124.07811]; 17 | 18 | let result: Vec = vwema(&source, &volume, period).into(); 19 | 20 | assert_eq!(result, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/vwma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn vwma(source: &Price, volume: &Price, period: Period) -> Price { 4 | (source * volume).smooth(Smooth::SMA, period) / volume.smooth(Smooth::SMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_vwma() { 13 | let source = Series::from([100.0, 105.0, 116.25, 123.125, 129.0625]); 14 | let volume = Series::from([40.0, 50.0, 110.25, 90.33, 100.00]); 15 | let period = 3; 16 | let expected = vec![100.0, 102.77778, 110.19507, 116.483536, 122.57867]; 17 | 18 | let result: Vec = vwma(&source, &volume, period).into(); 19 | 20 | assert_eq!(result, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/wma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn wma(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::WMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_wma() { 13 | let source = Series::from([ 14 | 6.5232, 6.5474, 6.5541, 6.5942, 6.5348, 6.4950, 6.5298, 6.5616, 6.5223, 6.5300, 6.5452, 15 | 6.5254, 6.5038, 6.4614, 6.4854, 6.4966, 6.5117, 6.5270, 6.5527, 6.5316, 16 | ]); 17 | let period = 3; 18 | let expected = [ 19 | 6.5231996, 6.5393333, 6.5467167, 6.573034, 6.557817, 6.5248, 6.5190334, 6.5399, 20 | 6.5366497, 6.5326996, 6.5363164, 6.5327663, 6.5179005, 6.4862, 6.4804664, 6.487, 21 | 6.5022836, 6.516834, 6.5373, 6.5378666, 22 | ]; 23 | 24 | let result: Vec = wma(&source, period).into(); 25 | 26 | assert_eq!(result, expected); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/zlema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn zlema(source: &Price, period: Period) -> Price { 4 | source.smooth(Smooth::ZLEMA, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_zlema() { 13 | let source = Series::from([18.898, 18.838, 18.881, 18.925, 18.846]); 14 | let period = 3; 15 | let expected = vec![18.898, 18.838, 18.881, 18.925, 18.846]; 16 | 17 | let result: Vec = zlema(&source, period).into(); 18 | 19 | assert_eq!(result, expected); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/zlsma.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn zlsma(source: &Price, period: Period) -> Price { 4 | let lsma = source.smooth(Smooth::LSMA, period); 5 | 6 | 2. * &lsma - lsma.smooth(Smooth::LSMA, period) 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | use super::*; 12 | 13 | #[test] 14 | fn test_lsma() { 15 | let source = Series::from([ 16 | 12.529, 12.504, 12.517, 12.542, 12.547, 12.577, 12.539, 12.577, 12.490, 12.490, 17 | ]); 18 | let expected = vec![ 19 | 12.529, 12.504, 12.515945, 12.543776, 12.547166, 12.574857, 12.54283, 12.570409, 20 | 12.499587, 12.478523, 21 | ]; 22 | 23 | let result: Vec = zlsma(&source, 3).into(); 24 | 25 | assert_eq!(result, expected); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/indicators/trend/src/zltema.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn zltema(source: &Price, period: Period) -> Price { 4 | source 5 | .smooth(Smooth::TEMA, period) 6 | .smooth(Smooth::TEMA, period) 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | use super::*; 12 | 13 | #[test] 14 | fn test_zltema() { 15 | let source = Series::from([18.898, 18.838, 18.881, 18.925, 18.846]); 16 | let period = 3; 17 | let expected = vec![18.898, 18.852058, 18.865294, 18.910984, 18.869732]; 18 | 19 | let result: Vec = zltema(&source, period).into(); 20 | 21 | assert_eq!(result, expected); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ta_lib/indicators/volatility/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "volatility" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | price = { path = "../../price" } 15 | -------------------------------------------------------------------------------- /ta_lib/indicators/volatility/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod bb; 2 | mod dch; 3 | mod gkyz; 4 | mod kb; 5 | mod kch; 6 | mod pk; 7 | mod ppb; 8 | mod rs; 9 | mod tr; 10 | mod yz; 11 | 12 | pub use bb::{bb, bbp, bbw}; 13 | pub use dch::{dch, dchw}; 14 | pub use gkyz::gkyz; 15 | pub use kb::{kb, kbp, kbw}; 16 | pub use kch::{kch, kchp, kchw}; 17 | pub use pk::pk; 18 | pub use ppb::{ppb, ppbp, ppbw}; 19 | pub use rs::rs; 20 | pub use tr::{atr, snatr, tr, wtr}; 21 | pub use yz::yz; 22 | -------------------------------------------------------------------------------- /ta_lib/indicators/volatility/src/pk.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn pk(high: &Price, low: &Price, period: Period) -> Price { 4 | let hll = (high / low).log(); 5 | 6 | let factor = 1. / (4.0 * period as Scalar * 2.0_f32.ln()); 7 | 8 | let hls = factor * hll.pow(2).sum(period); 9 | 10 | hls.sqrt() 11 | } 12 | 13 | #[cfg(test)] 14 | mod tests { 15 | use super::*; 16 | 17 | #[test] 18 | fn test_parkinson() { 19 | let high = Series::from([1.0, 2.0, 3.0, 2.0, 5.0]); 20 | let low = Series::from([3.0, 2.0, 3.0, 4.0, 5.0]); 21 | let period = 3; 22 | 23 | let expected = vec![0.38092643, 0.38092643, 0.38092643, 0.24033782, 0.24033782]; 24 | 25 | let result: Vec = pk(&high, &low, period).into(); 26 | 27 | assert_eq!(result, expected); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ta_lib/indicators/volume/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "volume" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | price = { path = "../../price" } 15 | -------------------------------------------------------------------------------- /ta_lib/indicators/volume/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod cmf; 2 | mod eom; 3 | mod mfi; 4 | mod nvol; 5 | mod obv; 6 | mod vwap; 7 | 8 | pub use cmf::cmf; 9 | pub use eom::eom; 10 | pub use mfi::mfi; 11 | pub use nvol::nvol; 12 | pub use obv::obv; 13 | pub use vwap::vwap; 14 | -------------------------------------------------------------------------------- /ta_lib/indicators/volume/src/nvol.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn nvol(volume: &Price, smooth: Smooth, period: Period) -> Price { 4 | SCALE * volume / volume.smooth(smooth, period) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_nvol() { 13 | let volume = Series::from([528.0, 69.0, 136.0, 78.0, 353.0, 59.0]); 14 | let period = 2; 15 | 16 | let expected = [100.0, 23.115578, 132.68292, 72.897194, 163.8051, 28.640778]; 17 | 18 | let result: Vec = nvol(&volume, Smooth::SMA, period).into(); 19 | 20 | assert_eq!(result, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ta_lib/indicators/volume/src/obv.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn obv(source: &Price, volume: &Price) -> Price { 4 | (source.change(1).nz(Some(ZERO)).sign() * volume).cumsum() 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_obv() { 13 | let close = Series::from([ 14 | 7.7975, 7.8065, 7.817, 7.831, 7.82, 7.826, 7.837, 7.844, 7.8655, 15 | ]); 16 | 17 | let volume = Series::from([ 18 | 3798.0, 5415.0, 7110.0, 2172.0, 7382.0, 2755.0, 2130.0, 21988.0, 9441.0, 19 | ]); 20 | 21 | let expected = [ 22 | 3798.0, 9213.0, 16323.0, 18495.0, 11113.0, 13868.0, 15998.0, 37986.0, 47427.0, 23 | ]; 24 | 25 | let result: Vec = obv(&close, &volume).into(); 26 | 27 | assert_eq!(result, expected); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ta_lib/patterns/bands/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bands" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | repository.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /ta_lib/patterns/bands/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod macros; 2 | -------------------------------------------------------------------------------- /ta_lib/patterns/candlestick/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "candlestick" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | volatility = { path = "../../indicators/volatility" } 15 | -------------------------------------------------------------------------------- /ta_lib/patterns/candlestick/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod barrier; 2 | pub mod blockade; 3 | pub mod bottle; 4 | pub mod breakaway; 5 | pub mod counterattack; 6 | pub mod doji; 7 | pub mod doji_double; 8 | pub mod doppelganger; 9 | pub mod double_trouble; 10 | pub mod engulfing; 11 | pub mod euphoria; 12 | pub mod euphoria_extreme; 13 | pub mod golden; 14 | pub mod h; 15 | pub mod hammer; 16 | pub mod harami_flexible; 17 | pub mod harami_strict; 18 | pub mod hexad; 19 | pub mod hikkake; 20 | pub mod kangaroo_tail; 21 | pub mod marubozu; 22 | pub mod master_candle; 23 | pub mod on_neck; 24 | pub mod piercing; 25 | pub mod quintuplets; 26 | pub mod r; 27 | pub mod shrinking; 28 | pub mod slingshot; 29 | pub mod split; 30 | pub mod tasuki; 31 | pub mod three_candles; 32 | pub mod three_methods; 33 | pub mod three_one_two; 34 | pub mod tweezers; 35 | -------------------------------------------------------------------------------- /ta_lib/patterns/channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "channel" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | repository.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /ta_lib/patterns/channel/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod macros; 2 | -------------------------------------------------------------------------------- /ta_lib/patterns/channel/src/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! a { 3 | ($source:expr, $upper_channel:expr, $lower_channel:expr) => {{ 4 | let prev_source = $source.shift(1); 5 | 6 | ( 7 | $source.sgt(&$lower_channel) & prev_source.slt(&$lower_channel.shift(1)), 8 | $source.slt(&$upper_channel) & prev_source.sgt(&$upper_channel.shift(1)), 9 | ) 10 | }}; 11 | } 12 | 13 | #[macro_export] 14 | macro_rules! c { 15 | ($low:expr, $high:expr, $upper_channel:expr, $lower_channel:expr) => {{ 16 | let prev_lwch = $lower_channel.shift(1); 17 | let prev_upch = $upper_channel.shift(1); 18 | 19 | ( 20 | $low.slt(&prev_lwch) & $low.shift(1).sgt(&prev_lwch), 21 | $high.sgt(&prev_upch) & $high.shift(1).slt(&prev_upch), 22 | ) 23 | }}; 24 | } 25 | -------------------------------------------------------------------------------- /ta_lib/patterns/osc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "osc" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | repository.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /ta_lib/patterns/osc/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod macros; 2 | -------------------------------------------------------------------------------- /ta_lib/patterns/trail/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trail" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | repository.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } -------------------------------------------------------------------------------- /ta_lib/patterns/trail/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod macros; 2 | -------------------------------------------------------------------------------- /ta_lib/patterns/trail/src/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! f { 3 | ($direction:expr) => {{ 4 | ($direction.cross_over(&ZERO), $direction.cross_under(&ZERO)) 5 | }}; 6 | } 7 | 8 | #[macro_export] 9 | macro_rules! p { 10 | ($trend:expr, $high:expr, $low:expr, $close:expr) => {{ 11 | let prev_trend = $trend.shift(1); 12 | 13 | ( 14 | $low.shift(1).cross_under(&prev_trend) & $close.sgt(&$trend), 15 | $high.shift(1).cross_over(&prev_trend) & $close.slt(&$trend), 16 | ) 17 | }}; 18 | } 19 | -------------------------------------------------------------------------------- /ta_lib/price/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "price" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../core" } 14 | -------------------------------------------------------------------------------- /ta_lib/price/src/average.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn average_price(open: &Price, high: &Price, low: &Price, close: &Price) -> Price { 4 | (open + high + low + close) / 4. 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_average_price() { 13 | let open = Series::from([1.5, 3.0, 4.5]); 14 | let high = Series::from([2.0, 4.0, 6.0]); 15 | let low = Series::from([1.0, 2.0, 3.0]); 16 | let close = Series::from([1.75, 3.5, 5.25]); 17 | 18 | let expected = vec![1.5625, 3.125, 4.6875]; 19 | 20 | let result: Vec = average_price(&open, &high, &low, &close).into(); 21 | 22 | assert_eq!(result, expected); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ta_lib/price/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod average; 2 | mod median; 3 | mod typical; 4 | mod wcl; 5 | 6 | pub mod prelude { 7 | pub use crate::average::average_price; 8 | pub use crate::median::median_price; 9 | pub use crate::typical::typical_price; 10 | pub use crate::wcl::wcl; 11 | } 12 | 13 | pub use prelude::*; 14 | -------------------------------------------------------------------------------- /ta_lib/price/src/median.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn median_price(high: &Price, low: &Price) -> Price { 4 | HALF * (high + low) 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_median_price() { 13 | let high = Series::from([1.0, 2.0, 3.0]); 14 | let low = Series::from([0.5, 1.0, 2.0]); 15 | 16 | let expected = vec![0.75, 1.5, 2.5]; 17 | 18 | let result: Vec = median_price(&high, &low).into(); 19 | 20 | assert_eq!(result, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ta_lib/price/src/typical.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn typical_price(high: &Price, low: &Price, close: &Price) -> Price { 4 | (high + low + close) / 3. 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_typical_price() { 13 | let high = Series::from([1.0, 2.0, 3.0]); 14 | let low = Series::from([0.5, 1.0, 1.5]); 15 | let close = Series::from([0.75, 1.5, 2.25]); 16 | 17 | let expected = vec![0.75, 1.5, 2.25]; 18 | 19 | let result: Vec = typical_price(&high, &low, &close).into(); 20 | 21 | assert_eq!(result, expected); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ta_lib/price/src/wcl.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub fn wcl(high: &Price, low: &Price, close: &Price) -> Price { 4 | (high + low + (close * 2.)) / 4. 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_weighted_close_price() { 13 | let high = Series::from([1.0, 2.0, 3.0]); 14 | let low = Series::from([0.5, 1.0, 1.5]); 15 | let close = Series::from([0.75, 1.5, 2.25]); 16 | 17 | let expected = vec![0.75, 1.5, 2.25]; 18 | 19 | let result: Vec = wcl(&high, &low, &close).into(); 20 | 21 | assert_eq!(result, expected); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ta_lib/strategies/base/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "base" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | once_cell = "1.19" 14 | core = { path = "../../core" } 15 | timeseries = { path = "../../timeseries" } 16 | price = { path = "../../price" } 17 | volatility = { path = "../../indicators/volatility" } 18 | -------------------------------------------------------------------------------- /ta_lib/strategies/base/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate alloc; 2 | 3 | mod ffi; 4 | mod source; 5 | mod strategy; 6 | mod traits; 7 | mod volatility; 8 | 9 | pub mod prelude { 10 | pub use crate::ffi::*; 11 | pub use crate::source::*; 12 | pub use crate::strategy::{BaseStrategy, TradeAction}; 13 | pub use crate::traits::*; 14 | pub use crate::volatility::*; 15 | } 16 | 17 | pub use prelude::*; 18 | -------------------------------------------------------------------------------- /ta_lib/strategies/base/src/source.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | use price::prelude::*; 3 | use timeseries::prelude::*; 4 | 5 | #[derive(Copy, Clone)] 6 | pub enum SourceType { 7 | CLOSE, 8 | HL2, 9 | HLC3, 10 | HLCC4, 11 | OHLC4, 12 | } 13 | 14 | pub trait Source { 15 | fn source(&self, source_type: SourceType) -> Price; 16 | } 17 | 18 | impl Source for OHLCVSeries { 19 | #[inline] 20 | fn source(&self, source_type: SourceType) -> Price { 21 | match source_type { 22 | SourceType::CLOSE => self.close().clone(), 23 | SourceType::HL2 => median_price(self.high(), self.low()), 24 | SourceType::HLC3 => typical_price(self.high(), self.low(), self.close()), 25 | SourceType::HLCC4 => wcl(self.high(), self.low(), self.close()), 26 | SourceType::OHLC4 => average_price(self.open(), self.high(), self.low(), self.close()), 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ta_lib/strategies/base/src/traits.rs: -------------------------------------------------------------------------------- 1 | use crate::TradeAction; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | 5 | pub trait Signal: Send + Sync { 6 | fn lookback(&self) -> usize; 7 | fn trigger(&self, data: &OHLCVSeries) -> (Rule, Rule); 8 | } 9 | 10 | pub trait Confirm: Send + Sync { 11 | fn lookback(&self) -> usize; 12 | fn filter(&self, data: &OHLCVSeries) -> (Rule, Rule); 13 | } 14 | 15 | pub trait Pulse: Send + Sync { 16 | fn lookback(&self) -> usize; 17 | fn assess(&self, data: &OHLCVSeries) -> (Rule, Rule); 18 | } 19 | 20 | pub trait BaseLine: Send + Sync { 21 | fn lookback(&self) -> usize; 22 | fn filter(&self, data: &OHLCVSeries) -> (Rule, Rule); 23 | fn close(&self, data: &OHLCVSeries) -> (Rule, Rule); 24 | } 25 | 26 | pub trait Strategy { 27 | fn next(&mut self, bar: &OHLCV) -> TradeAction; 28 | } 29 | -------------------------------------------------------------------------------- /ta_lib/strategies/base/src/volatility.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | use timeseries::prelude::*; 3 | use volatility::{tr, wtr}; 4 | 5 | pub trait Volatility { 6 | fn atr(&self, smooth: Smooth, period: usize) -> Price; 7 | fn tr(&self) -> Price; 8 | fn wtr(&self) -> Price; 9 | } 10 | 11 | impl Volatility for OHLCVSeries { 12 | #[inline] 13 | fn atr(&self, smooth: Smooth, period: usize) -> Price { 14 | self.tr().smooth(smooth, period) 15 | } 16 | 17 | #[inline] 18 | fn tr(&self) -> Price { 19 | tr(self.high(), self.low(), self.close()) 20 | } 21 | 22 | #[inline] 23 | fn wtr(&self) -> Price { 24 | wtr(self.high(), self.low(), self.close()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ta_lib/strategies/baseline/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "baseline" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | 13 | [dependencies] 14 | base = { path = "../base" } 15 | core = { path = "../../core" } 16 | trend = { path = "../../indicators/trend" } 17 | signal = { path = "../signal" } 18 | indicator = { path = "../indicator" } 19 | timeseries = { path = "../../timeseries" } -------------------------------------------------------------------------------- /ta_lib/strategies/baseline/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod ma; 2 | 3 | pub use ma::MaBaseLine; 4 | -------------------------------------------------------------------------------- /ta_lib/strategies/confirm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "confirm" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | base = { path = "../base" } 14 | core = { path = "../../core" } 15 | timeseries = { path = "../../timeseries" } 16 | momentum = { path = "../../indicators/momentum" } 17 | trend = { path = "../../indicators/trend" } 18 | volume = { path = "../../indicators/volume" } 19 | volatility = { path = "../../indicators/volatility" } -------------------------------------------------------------------------------- /ta_lib/strategies/confirm/src/dpo.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | use trend::dpo; 5 | 6 | const DPO_UPPER_BARRIER: f32 = 0.005; 7 | const DPO_LOWER_BARRIER: f32 = -0.005; 8 | 9 | pub struct DpoConfirm { 10 | source: SourceType, 11 | smooth: Smooth, 12 | period: usize, 13 | } 14 | 15 | impl DpoConfirm { 16 | pub fn new(source: SourceType, smooth: Smooth, period: f32) -> Self { 17 | Self { 18 | source, 19 | smooth, 20 | period: period as usize, 21 | } 22 | } 23 | } 24 | 25 | impl Confirm for DpoConfirm { 26 | fn lookback(&self) -> usize { 27 | self.period 28 | } 29 | 30 | fn filter(&self, data: &OHLCVSeries) -> (Series, Series) { 31 | let dpo = dpo(&data.source(self.source), self.smooth, self.period); 32 | 33 | (dpo.sgt(&DPO_UPPER_BARRIER), dpo.slt(&DPO_LOWER_BARRIER)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ta_lib/strategies/confirm/src/dumb.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | 5 | pub struct DumbConfirm { 6 | period: usize, 7 | } 8 | 9 | impl DumbConfirm { 10 | pub fn new(period: f32) -> Self { 11 | Self { 12 | period: period as usize, 13 | } 14 | } 15 | } 16 | 17 | impl Confirm for DumbConfirm { 18 | fn lookback(&self) -> usize { 19 | self.period 20 | } 21 | 22 | fn filter(&self, data: &OHLCVSeries) -> (Series, Series) { 23 | let len = data.len(); 24 | 25 | (Series::one(len).into(), Series::one(len).into()) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/strategies/confirm/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod bb; 2 | mod braid; 3 | mod cc; 4 | mod cci; 5 | mod didi; 6 | mod dpo; 7 | mod dumb; 8 | mod eom; 9 | mod rsi_neutrality; 10 | mod rsi_signalline; 11 | mod stc; 12 | mod wpr; 13 | 14 | pub use bb::BbConfirm; 15 | pub use braid::BraidConfirm; 16 | pub use cc::CcConfirm; 17 | pub use cci::CciConfirm; 18 | pub use didi::DidiConfirm; 19 | pub use dpo::DpoConfirm; 20 | pub use dumb::DumbConfirm; 21 | pub use eom::EomConfirm; 22 | pub use rsi_neutrality::RsiNeutralityConfirm; 23 | pub use rsi_signalline::RsiSignalLineConfirm; 24 | pub use stc::StcConfirm; 25 | pub use wpr::WprConfirm; 26 | -------------------------------------------------------------------------------- /ta_lib/strategies/indicator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "indicator" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | base = { path = "../base" } 15 | candlestick = { path = "../../patterns/candlestick" } 16 | trend = { path = "../../indicators/trend" } 17 | timeseries = { path = "../../timeseries" } -------------------------------------------------------------------------------- /ta_lib/strategies/indicator/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod candle; 2 | mod ma; 3 | 4 | pub use candle::*; 5 | pub use ma::*; 6 | -------------------------------------------------------------------------------- /ta_lib/strategies/pulse/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pulse" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | 13 | [dependencies] 14 | base = { path = "../base" } 15 | core = { path = "../../core" } 16 | volume = { path = "../../indicators/volume" } 17 | trend = { path = "../../indicators/trend" } 18 | momentum = { path = "../../indicators/momentum" } 19 | volatility = { path = "../../indicators/volatility" } 20 | timeseries = { path = "../../timeseries" } -------------------------------------------------------------------------------- /ta_lib/strategies/pulse/src/dumb.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | 5 | pub struct DumbPulse { 6 | period: usize, 7 | } 8 | 9 | impl DumbPulse { 10 | pub fn new(period: f32) -> Self { 11 | Self { 12 | period: period as usize, 13 | } 14 | } 15 | } 16 | 17 | impl Pulse for DumbPulse { 18 | fn lookback(&self) -> usize { 19 | self.period 20 | } 21 | 22 | fn assess(&self, data: &OHLCVSeries) -> (Series, Series) { 23 | let len = data.len(); 24 | 25 | (Series::one(len).into(), Series::one(len).into()) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta_lib/strategies/pulse/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod adx; 2 | mod chop; 3 | mod dumb; 4 | mod nvol; 5 | mod sqz; 6 | mod tdfi; 7 | mod vo; 8 | mod wae; 9 | mod yz; 10 | 11 | pub use adx::AdxPulse; 12 | pub use chop::ChopPulse; 13 | pub use dumb::DumbPulse; 14 | pub use nvol::NvolPulse; 15 | pub use sqz::SqzPulse; 16 | pub use tdfi::TdfiPulse; 17 | pub use vo::VoPulse; 18 | pub use wae::WaePulse; 19 | pub use yz::YzPulse; 20 | -------------------------------------------------------------------------------- /ta_lib/strategies/pulse/src/nvol.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | use volume::nvol; 5 | 6 | const NVOL_LINE: f32 = 100.0; 7 | 8 | pub struct NvolPulse { 9 | smooth: Smooth, 10 | period: usize, 11 | } 12 | 13 | impl NvolPulse { 14 | pub fn new(smooth: Smooth, period: f32) -> Self { 15 | Self { 16 | smooth, 17 | period: period as usize, 18 | } 19 | } 20 | } 21 | 22 | impl Pulse for NvolPulse { 23 | fn lookback(&self) -> usize { 24 | self.period 25 | } 26 | 27 | fn assess(&self, data: &OHLCVSeries) -> (Series, Series) { 28 | let nvol = nvol(data.volume(), self.smooth, self.period); 29 | 30 | (nvol.sgt(&NVOL_LINE), nvol.sgt(&NVOL_LINE)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ta_lib/strategies/pulse/src/vo.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | 5 | pub struct VoPulse { 6 | smooth: Smooth, 7 | period_fast: usize, 8 | period_slow: usize, 9 | } 10 | 11 | impl VoPulse { 12 | pub fn new(smooth: Smooth, period_fast: f32, period_slow: f32) -> Self { 13 | Self { 14 | smooth, 15 | period_fast: period_fast as usize, 16 | period_slow: period_slow as usize, 17 | } 18 | } 19 | } 20 | 21 | impl Pulse for VoPulse { 22 | fn lookback(&self) -> usize { 23 | std::cmp::max(self.period_fast, self.period_slow) 24 | } 25 | 26 | fn assess(&self, data: &OHLCVSeries) -> (Series, Series) { 27 | let vo = data 28 | .volume() 29 | .spread_pct(self.smooth, self.period_fast, self.period_slow); 30 | 31 | (vo.sgt(&ZERO), vo.sgt(&ZERO)) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | 13 | [dependencies] 14 | core = { path = "../../core" } 15 | base = { path = "../base" } 16 | indicator = { path = "../indicator" } 17 | trend = { path = "../../indicators/trend" } 18 | momentum = { path = "../../indicators/momentum" } 19 | volatility = { path = "../../indicators/volatility" } 20 | volume = { path = "../../indicators/volume" } 21 | candlestick = { path = "../../patterns/candlestick" } 22 | osc = { path = "../../patterns/osc" } 23 | channel = { path = "../../patterns/channel" } 24 | bands = { path = "../../patterns/bands" } 25 | trail = { path = "../../patterns/trail" } 26 | timeseries = { path = "../../timeseries" } -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/bb/mod.rs: -------------------------------------------------------------------------------- 1 | mod macd; 2 | mod vwap; 3 | 4 | pub use macd::MacdBbSignal; 5 | pub use vwap::VwapBbSignal; 6 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/breakout/mod.rs: -------------------------------------------------------------------------------- 1 | mod dch_ma2; 2 | 3 | pub use dch_ma2::DchMa2BreakoutSignal; 4 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/colorswitch/mod.rs: -------------------------------------------------------------------------------- 1 | mod macd; 2 | 3 | pub use macd::MacdColorSwitchSignal; 4 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/contrarian/mod.rs: -------------------------------------------------------------------------------- 1 | mod kch_a; 2 | mod kch_c; 3 | mod rsi_c; 4 | mod rsi_d; 5 | mod rsi_nt; 6 | mod rsi_u; 7 | mod rsi_v; 8 | mod snatr; 9 | mod stoch_e; 10 | mod tii_v; 11 | 12 | pub use kch_a::KchASignal; 13 | pub use kch_c::KchCSignal; 14 | pub use rsi_c::RsiCSignal; 15 | pub use rsi_d::RsiDSignal; 16 | pub use rsi_nt::RsiNtSignal; 17 | pub use rsi_u::RsiUSignal; 18 | pub use rsi_v::RsiVSignal; 19 | pub use snatr::SnatrSignal; 20 | pub use stoch_e::StochESignal; 21 | pub use tii_v::TiiVSignal; 22 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/flip/mod.rs: -------------------------------------------------------------------------------- 1 | mod ce; 2 | mod supertrend; 3 | 4 | pub use ce::CeFlipSignal; 5 | pub use supertrend::SupertrendFlipSignal; 6 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod bb; 2 | mod breakout; 3 | mod colorswitch; 4 | mod contrarian; 5 | mod flip; 6 | mod ma; 7 | mod neutrality; 8 | mod pattern; 9 | mod pullback; 10 | mod signalline; 11 | mod twolinescross; 12 | mod zerocross; 13 | 14 | pub use bb::*; 15 | pub use breakout::*; 16 | pub use colorswitch::*; 17 | pub use contrarian::*; 18 | pub use flip::*; 19 | pub use ma::*; 20 | pub use neutrality::*; 21 | pub use pattern::*; 22 | pub use pullback::*; 23 | pub use signalline::*; 24 | pub use twolinescross::*; 25 | pub use zerocross::*; 26 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/ma/ma_cross.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use indicator::{ma_indicator, MovingAverageType}; 4 | use timeseries::prelude::*; 5 | 6 | pub struct MaCrossSignal { 7 | source_type: SourceType, 8 | ma: MovingAverageType, 9 | period: usize, 10 | } 11 | 12 | impl MaCrossSignal { 13 | pub fn new(source_type: SourceType, ma: MovingAverageType, period: f32) -> Self { 14 | Self { 15 | source_type, 16 | ma, 17 | period: period as usize, 18 | } 19 | } 20 | } 21 | 22 | impl Signal for MaCrossSignal { 23 | fn lookback(&self) -> usize { 24 | self.period 25 | } 26 | 27 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 28 | let ma = ma_indicator(&self.ma, data, self.source_type, self.period); 29 | 30 | (data.close().cross_over(&ma), data.close().cross_under(&ma)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/ma/mod.rs: -------------------------------------------------------------------------------- 1 | mod ma2_rsi; 2 | mod ma3_cross; 3 | mod ma_cross; 4 | mod ma_quadruple; 5 | mod ma_surpass; 6 | mod ma_testing_ground; 7 | mod vwap_cross; 8 | 9 | pub use ma2_rsi::Ma2RsiSignal; 10 | pub use ma3_cross::Ma3CrossSignal; 11 | pub use ma_cross::MaCrossSignal; 12 | pub use ma_quadruple::MaQuadrupleSignal; 13 | pub use ma_surpass::MaSurpassSignal; 14 | pub use ma_testing_ground::MaTestingGroundSignal; 15 | pub use vwap_cross::VwapCrossSignal; 16 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/ma/vwap_cross.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | use volume::vwap; 5 | 6 | pub struct VwapCrossSignal { 7 | source_type: SourceType, 8 | period: usize, 9 | } 10 | 11 | impl VwapCrossSignal { 12 | pub fn new(source_type: SourceType, period: f32) -> Self { 13 | Self { 14 | source_type, 15 | period: period as usize, 16 | } 17 | } 18 | } 19 | 20 | impl Signal for VwapCrossSignal { 21 | fn lookback(&self) -> usize { 22 | self.period 23 | } 24 | 25 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 26 | let vwap = vwap(&data.source(self.source_type), data.volume()); 27 | 28 | ( 29 | data.close().cross_over(&vwap), 30 | data.close().cross_under(&vwap), 31 | ) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/neutrality/mod.rs: -------------------------------------------------------------------------------- 1 | mod dso_cross; 2 | mod rsi_cross; 3 | mod rsi_pullback; 4 | mod rsi_rejection; 5 | mod tii_cross; 6 | 7 | pub use dso_cross::DsoNeutralityCrossSignal; 8 | pub use rsi_cross::RsiNeutralityCrossSignal; 9 | pub use rsi_pullback::RsiNeutralityPullbackSignal; 10 | pub use rsi_rejection::RsiNeutralityRejectionSignal; 11 | pub use tii_cross::TiiNeutralityCrossSignal; 12 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/pattern/candlestick_reversal.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use indicator::{candlestick_reversal_indicator, CandleReversalType}; 4 | use timeseries::prelude::*; 5 | 6 | const DEFAULT_LOOKBACK: usize = 200; 7 | 8 | pub struct CandlestickReversalSignal { 9 | candle: CandleReversalType, 10 | } 11 | 12 | impl CandlestickReversalSignal { 13 | pub fn new(candle: CandleReversalType) -> Self { 14 | Self { candle } 15 | } 16 | } 17 | 18 | impl Signal for CandlestickReversalSignal { 19 | fn lookback(&self) -> usize { 20 | DEFAULT_LOOKBACK 21 | } 22 | 23 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 24 | candlestick_reversal_indicator(&self.candle, data) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/pattern/candlestick_trend.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use indicator::{candlestick_trend_indicator, CandleTrendType}; 4 | use timeseries::prelude::*; 5 | 6 | const DEFAULT_LOOKBACK: usize = 13; 7 | 8 | pub struct CandlestickTrendSignal { 9 | candle: CandleTrendType, 10 | } 11 | 12 | impl CandlestickTrendSignal { 13 | pub fn new(candle: CandleTrendType) -> Self { 14 | Self { candle } 15 | } 16 | } 17 | 18 | impl Signal for CandlestickTrendSignal { 19 | fn lookback(&self) -> usize { 20 | DEFAULT_LOOKBACK 21 | } 22 | 23 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 24 | candlestick_trend_indicator(&self.candle, data) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/pattern/hl.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use timeseries::prelude::*; 4 | 5 | pub struct HighLowSignal { 6 | period: usize, 7 | } 8 | 9 | impl HighLowSignal { 10 | pub fn new(period: f32) -> Self { 11 | Self { 12 | period: period as usize, 13 | } 14 | } 15 | } 16 | 17 | impl Signal for HighLowSignal { 18 | fn lookback(&self) -> usize { 19 | self.period 20 | } 21 | 22 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 23 | ( 24 | data.low().seq(&data.low().shift(1)), 25 | data.high().seq(&data.high().shift(1)), 26 | ) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/pattern/mod.rs: -------------------------------------------------------------------------------- 1 | mod ao_saucer; 2 | mod candlestick_reversal; 3 | mod candlestick_trend; 4 | mod hl; 5 | mod spread; 6 | 7 | pub use ao_saucer::AoSaucerSignal; 8 | pub use candlestick_reversal::CandlestickReversalSignal; 9 | pub use candlestick_trend::CandlestickTrendSignal; 10 | pub use hl::HighLowSignal; 11 | pub use spread::SpreadSignal; 12 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/pullback/mod.rs: -------------------------------------------------------------------------------- 1 | mod supertrend; 2 | 3 | pub use supertrend::SupertrendPullbackSignal; 4 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/signalline/mod.rs: -------------------------------------------------------------------------------- 1 | mod di; 2 | mod dso; 3 | mod kst; 4 | mod macd; 5 | mod qstick; 6 | mod rsi; 7 | mod stoch; 8 | mod trix; 9 | mod tsi; 10 | 11 | pub use di::DiSignalLineSignal; 12 | pub use dso::DsoSignalLineSignal; 13 | pub use kst::KstSignalLineSignal; 14 | pub use macd::MacdSignalLineSignal; 15 | pub use qstick::QstickSignalLineSignal; 16 | pub use rsi::RsiSignalLineSignal; 17 | pub use stoch::StochSignalLineSignal; 18 | pub use trix::TrixSignalLineSignal; 19 | pub use tsi::TsiSignalLineSignal; 20 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/twolinescross/mod.rs: -------------------------------------------------------------------------------- 1 | mod dmi; 2 | mod vi; 3 | 4 | pub use dmi::Dmi2LinesCrossSignal; 5 | pub use vi::Vi2LinesCrossSignal; 6 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/zerocross/cfo.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use momentum::cfo; 4 | use timeseries::prelude::*; 5 | 6 | pub struct CfoZeroCrossSignal { 7 | source_type: SourceType, 8 | period: usize, 9 | } 10 | 11 | impl CfoZeroCrossSignal { 12 | pub fn new(source_type: SourceType, period: f32) -> Self { 13 | Self { 14 | source_type, 15 | period: period as usize, 16 | } 17 | } 18 | } 19 | 20 | impl Signal for CfoZeroCrossSignal { 21 | fn lookback(&self) -> usize { 22 | self.period 23 | } 24 | 25 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 26 | let cfo = cfo(&data.source(self.source_type), self.period); 27 | 28 | (cfo.cross_over(&ZERO), cfo.cross_under(&ZERO)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/zerocross/di.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use momentum::di; 4 | use timeseries::prelude::*; 5 | 6 | pub struct DiZeroCrossSignal { 7 | source_type: SourceType, 8 | smooth_type: Smooth, 9 | period: usize, 10 | } 11 | 12 | impl DiZeroCrossSignal { 13 | pub fn new(source_type: SourceType, smooth_type: Smooth, period: f32) -> Self { 14 | Self { 15 | source_type, 16 | smooth_type, 17 | period: period as usize, 18 | } 19 | } 20 | } 21 | 22 | impl Signal for DiZeroCrossSignal { 23 | fn lookback(&self) -> usize { 24 | self.period 25 | } 26 | 27 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 28 | let di = di( 29 | &data.source(self.source_type), 30 | self.smooth_type, 31 | self.period, 32 | ); 33 | 34 | (di.cross_over(&ZERO), di.cross_under(&ZERO)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/zerocross/mod.rs: -------------------------------------------------------------------------------- 1 | mod ao; 2 | mod bop; 3 | mod cc; 4 | mod cfo; 5 | mod di; 6 | mod macd; 7 | mod mad; 8 | mod qstick; 9 | mod roc; 10 | mod trix; 11 | mod tsi; 12 | 13 | pub use ao::AoZeroCrossSignal; 14 | pub use bop::BopZeroCrossSignal; 15 | pub use cc::CcZeroCrossSignal; 16 | pub use cfo::CfoZeroCrossSignal; 17 | pub use di::DiZeroCrossSignal; 18 | pub use macd::MacdZeroCrossSignal; 19 | pub use mad::MadZeroCrossSignal; 20 | pub use qstick::QstickZeroCrossSignal; 21 | pub use roc::RocZeroCrossSignal; 22 | pub use trix::TrixZeroCrossSignal; 23 | pub use tsi::TsiZeroCrossSignal; 24 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/zerocross/qstick.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use momentum::qstick; 4 | use timeseries::prelude::*; 5 | 6 | pub struct QstickZeroCrossSignal { 7 | smooth_type: Smooth, 8 | period: usize, 9 | } 10 | 11 | impl QstickZeroCrossSignal { 12 | pub fn new(smooth_type: Smooth, period: f32) -> Self { 13 | Self { 14 | smooth_type, 15 | period: period as usize, 16 | } 17 | } 18 | } 19 | 20 | impl Signal for QstickZeroCrossSignal { 21 | fn lookback(&self) -> usize { 22 | self.period 23 | } 24 | 25 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 26 | let qstick = qstick(data.open(), data.close(), self.smooth_type, self.period); 27 | 28 | (qstick.cross_over(&ZERO), qstick.cross_under(&ZERO)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/zerocross/roc.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use momentum::roc; 4 | use timeseries::prelude::*; 5 | 6 | pub struct RocZeroCrossSignal { 7 | source: SourceType, 8 | period: usize, 9 | } 10 | 11 | impl RocZeroCrossSignal { 12 | pub fn new(source: SourceType, period: f32) -> Self { 13 | Self { 14 | source, 15 | period: period as usize, 16 | } 17 | } 18 | } 19 | 20 | impl Signal for RocZeroCrossSignal { 21 | fn lookback(&self) -> usize { 22 | self.period 23 | } 24 | 25 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 26 | let roc = roc(&data.source(self.source), self.period); 27 | 28 | (roc.cross_over(&ZERO), roc.cross_under(&ZERO)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ta_lib/strategies/signal/src/zerocross/trix.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | use core::prelude::*; 3 | use momentum::trix; 4 | use timeseries::prelude::*; 5 | 6 | pub struct TrixZeroCrossSignal { 7 | source: SourceType, 8 | smooth: Smooth, 9 | period: usize, 10 | } 11 | 12 | impl TrixZeroCrossSignal { 13 | pub fn new(source: SourceType, smooth: Smooth, period: f32) -> Self { 14 | Self { 15 | source, 16 | smooth, 17 | period: period as usize, 18 | } 19 | } 20 | } 21 | 22 | impl Signal for TrixZeroCrossSignal { 23 | fn lookback(&self) -> usize { 24 | self.period 25 | } 26 | 27 | fn trigger(&self, data: &OHLCVSeries) -> (Series, Series) { 28 | let trix = trix(&data.source(self.source), self.smooth, self.period); 29 | 30 | (trix.cross_over(&ZERO), trix.cross_under(&ZERO)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trend_follow" 3 | resolver = "2" 4 | 5 | authors.workspace = true 6 | version.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | core = { path = "../../core" } 14 | timeseries = { path = "../../timeseries" } 15 | base = { path = "../base" } 16 | signal = { path = "../signal" } 17 | confirm = { path = "../confirm" } 18 | pulse = { path = "../pulse" } 19 | baseline = { path = "../baseline" } 20 | indicator = { path = "../indicator" } 21 | serde = { version = "1.0", default-features = false, features = ["derive"] } 22 | serde_json = { version = "1.0", default-features = false, features = ["alloc"] } 23 | 24 | [lib] 25 | crate-type = ["cdylib"] 26 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/config/baseline_config.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Deserialize)] 4 | #[serde(tag = "type")] 5 | pub enum BaseLineConfig { 6 | Ma { source: f32, ma: f32, period: f32 }, 7 | } 8 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/config/mod.rs: -------------------------------------------------------------------------------- 1 | mod baseline_config; 2 | mod confirm_config; 3 | mod pulse_config; 4 | mod signal_config; 5 | 6 | pub use baseline_config::BaseLineConfig; 7 | pub use confirm_config::ConfirmConfig; 8 | pub use pulse_config::PulseConfig; 9 | pub use signal_config::SignalConfig; 10 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/deserialize/mod.rs: -------------------------------------------------------------------------------- 1 | mod candle_deserialize; 2 | mod ma_deserialize; 3 | mod smooth_deserialize; 4 | mod source_deserialize; 5 | 6 | pub use candle_deserialize::{candlereversal_deserialize, candletrend_deserialize}; 7 | pub use ma_deserialize::ma_deserialize; 8 | pub use smooth_deserialize::smooth_deserialize; 9 | pub use source_deserialize::source_deserialize; 10 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/deserialize/smooth_deserialize.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | #[inline] 4 | pub fn smooth_deserialize(smooth: usize) -> Smooth { 5 | match smooth { 6 | 1 => Smooth::EMA, 7 | 2 => Smooth::SMA, 8 | 3 => Smooth::SMMA, 9 | 4 => Smooth::KAMA, 10 | 5 => Smooth::HMA, 11 | 6 => Smooth::WMA, 12 | 7 => Smooth::ZLEMA, 13 | 8 => Smooth::LSMA, 14 | 9 => Smooth::TEMA, 15 | 10 => Smooth::DEMA, 16 | 11 => Smooth::ULTS, 17 | _ => Smooth::EMA, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/deserialize/source_deserialize.rs: -------------------------------------------------------------------------------- 1 | use base::prelude::*; 2 | 3 | #[inline] 4 | pub fn source_deserialize(source: usize) -> SourceType { 5 | match source { 6 | 1 => SourceType::CLOSE, 7 | 2 => SourceType::HL2, 8 | 3 => SourceType::HLC3, 9 | 4 => SourceType::HLCC4, 10 | 5 => SourceType::OHLC4, 11 | _ => SourceType::CLOSE, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod config; 2 | mod deserialize; 3 | mod ffi; 4 | mod mapper; 5 | 6 | pub use ffi::*; 7 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/mapper/baseline_mapper.rs: -------------------------------------------------------------------------------- 1 | use crate::config::BaseLineConfig; 2 | use crate::deserialize::{ma_deserialize, source_deserialize}; 3 | use base::prelude::*; 4 | use baseline::*; 5 | 6 | #[inline] 7 | pub fn map_to_baseline(config: BaseLineConfig) -> Box { 8 | match config { 9 | BaseLineConfig::Ma { source, ma, period } => Box::new(MaBaseLine::new( 10 | source_deserialize(source as usize), 11 | ma_deserialize(ma as usize), 12 | period, 13 | )), 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ta_lib/strategies/trend_follow/src/mapper/mod.rs: -------------------------------------------------------------------------------- 1 | mod baseline_mapper; 2 | mod confirm_mapper; 3 | mod pulse_mapper; 4 | mod signal_mapper; 5 | 6 | pub use baseline_mapper::map_to_baseline; 7 | pub use confirm_mapper::map_to_confirm; 8 | pub use pulse_mapper::map_to_pulse; 9 | pub use signal_mapper::map_to_signal; 10 | -------------------------------------------------------------------------------- /ta_lib/timeseries/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "timeseries" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | readme.workspace = true 7 | repository.workspace = true 8 | version.workspace = true 9 | 10 | 11 | [dependencies] 12 | core = { path = "../core" } 13 | momentum = { path = "../indicators/momentum" } 14 | volume = { path = "../indicators/volume" } 15 | trend = { path = "../indicators/trend" } 16 | price = { path = "../price" } 17 | volatility = { path = "../indicators/volatility" } 18 | serde = { version = "1.0", default-features = false, features = ["derive"] } -------------------------------------------------------------------------------- /ta_lib/timeseries/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod model; 2 | mod ohlcv; 3 | mod ta; 4 | mod traits; 5 | 6 | pub mod prelude { 7 | pub use crate::model::BaseTimeSeries; 8 | pub use crate::ohlcv::{OHLCVSeries, OHLCV}; 9 | pub use crate::ta::TechAnalysis; 10 | pub use crate::traits::*; 11 | } 12 | 13 | pub use prelude::*; 14 | -------------------------------------------------------------------------------- /ta_lib/timeseries/src/ta.rs: -------------------------------------------------------------------------------- 1 | use serde::Serialize; 2 | 3 | #[derive(Debug, Serialize)] 4 | pub struct TechAnalysis { 5 | pub frsi: Vec, 6 | pub srsi: Vec, 7 | pub fma: Vec, 8 | pub sma: Vec, 9 | pub froc: Vec, 10 | pub sroc: Vec, 11 | pub macd: Vec, 12 | pub ppo: Vec, 13 | pub cci: Vec, 14 | pub obv: Vec, 15 | pub vo: Vec, 16 | pub nvol: Vec, 17 | pub mfi: Vec, 18 | pub tr: Vec, 19 | pub gkyz: Vec, 20 | pub yz: Vec, 21 | pub upb: Vec, 22 | pub lwb: Vec, 23 | pub ebb: Vec, 24 | pub ekch: Vec, 25 | pub k: Vec, 26 | pub d: Vec, 27 | pub hh: Vec, 28 | pub ll: Vec, 29 | pub support: Vec, 30 | pub resistance: Vec, 31 | pub dmi: Vec, 32 | pub vwap: Vec, 33 | pub close: Vec, 34 | pub hlc3: Vec, 35 | pub hlcc4: Vec, 36 | } 37 | -------------------------------------------------------------------------------- /ta_lib/timeseries/src/traits.rs: -------------------------------------------------------------------------------- 1 | use crate::{OHLCVSeries, TechAnalysis, OHLCV}; 2 | 3 | pub trait TimeSeries: Send + Sync { 4 | fn add(&mut self, bar: &OHLCV); 5 | fn next_bar(&self, bar: &OHLCV) -> Option; 6 | fn prev_bar(&self, bar: &OHLCV) -> Option; 7 | fn back_n_bars(&self, bar: &OHLCV, n: usize) -> Vec; 8 | fn ohlcv(&self, size: usize) -> OHLCVSeries; 9 | fn ta(&self, bar: &OHLCV) -> TechAnalysis; 10 | fn len(&self) -> usize; 11 | } 12 | -------------------------------------------------------------------------------- /wasm/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YieldXLabs/quant/1f5f09bb4e072fde1ceef913e2e1086521631638/wasm/.empty --------------------------------------------------------------------------------