amv-dev / yata

Yet Another Technical Analysis library [for Rust]
Apache License 2.0
329 stars 52 forks source link

Allow to access indicator instance #17

Closed dgoulet closed 2 years ago

dgoulet commented 3 years ago

There might be some Rust knowledge I don't have that fixes this problem and if so, I apologize but a bit of help would be great.

I was trying to create an Historyobject that would store various indicators for specific timeframes (1min, 5min, ..). And at each trade event I would get from the exchange feed, I could simply update the candle of the specific timeframes I'm tracking and for each timeframe, update the indicator accordingly with the next() method (a bit of a "rolling indicator" idea where the indicator is always with the latest data).

However, it appears that one must .init() the indicator with a first candle in order to get an indicator instance object (which is not publicly available, deriving the IndicatorInstance trait).

And so this is a problem because it means that every time I want to compute let say the RSI of a specific timeframe, I need all 14 historical candle and next() them all which is a bit of a waste considering an indicator in the first place can just keep the rolling value.

Would it be possible to have something like:

pub struct History {
  rsi: RelativeStrengthIndexInstance,
}

and so one can simply update the rsi has trade events occur taken from the exchange feed. Or even better, simply having the RSI objectbe able to initialize itself at the first next() ?

Note that I tried to use rsi: Box<dyn IndicatorInstance<Config = RSI>> but that fail to build due to a trait requirement (Sized).

Wondering your thought here or if I'm missing something. Thanks!

amv-dev commented 3 years ago

Hello! If I understood correctly, you need to save intermediate state of IndicatorInstance. Well for now it is actually possible only for indicators without dynamically selected methods. They simply implement Clone. I have some ideas about general solving your issue, but I need some time for check.

Note that I tried to use rsi: Box<dyn IndicatorInstance> but that fail to build due to a trait requirement (Sized).

I don't understand how DST can help you, but you can try to use prelude::dd traits for dynamic indicators.

dgoulet commented 3 years ago

Hello! If I understood correctly, you need to save intermediate state of IndicatorInstance. Well for now it is actually possible only for indicators without dynamically selected methods. They simply implement Clone.

Maybe? :)

Basically, if I take this crate as an example: https://github.com/greyblake/ta-rs/blob/master/src/indicators/relative_strength_index.rs#L74

One can simply instantiate the RSI object and over the course of the application lifetime, simply update it with market data values.

In the case or yata, one needs to keep all historical candles that are needed for the computation of the RSI, start with a init and then iterate over the candles (well object implementing OHLCV trait).

I have some ideas about general solving your issue, but I need some time for check.

Awesome. Thanks!

amv-dev commented 3 years ago

I think there is some kind of mistake in your description. You can't simply instantiate RSI at any time because every indicator/method must be evaluated over historical data before produce correct values. The difference between this implementation of RSI and ta-rs is in flexibility. There is hard-coded EMA inside RSI in ta-rs. That's why RSI itself may be cloned at any time, so you can hold it state as long as you want.

In yatas implementation you can change methods inside RSI at runtime, that's why it holds DST inside. That's why this RSI instance cannot be cloned simply.

I'm working on this issue right now. I found the solution very similar to this discussion: https://github.com/amv-dev/yata/issues/16 . You can try this branch https://github.com/amv-dev/yata/tree/window-T-ref . You can clone any instance of any indicator at any time in this implementation. But it is WIP still .

dgoulet commented 3 years ago

I think there is some kind of mistake in your description. You can't simply instantiate RSI at any time because every indicator/method must be evaluated over historical data before produce correct values. The difference between this implementation of RSI and ta-rs is in flexibility. There is hard-coded EMA inside RSI in ta-rs. That's why RSI itself may be cloned at any time, so you can hold it state as long as you want.

Correct, that is what I meant to say! Sorry for the confusion.

I'm working on this issue right now. I found the solution very similar to this discussion: #16 . You can try this branch https://github.com/amv-dev/yata/tree/window-T-ref . You can clone any instance of any indicator at any time in this implementation. But it is WIP still .

This is great. Thank you so much! I'll start testing this and hopefully providing any useful feedback.

agubarev commented 2 years ago

@dgoulet as late as is it, but you can use this: <RelativeStrengthIndex as IndicatorConfig>::Instance as an indicator instance type definition.

amv-dev commented 2 years ago

I think this issue was resolved due v0.5 release. So it might be closed. You are free to re-open it, if you see some other problems.