calumrussell / rotala

Backtesting engine written in Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Python Frontend

calumrussell opened this issue · comments

commented

I am using this package within a Python app that, at the moment, is getting bound somewhere else into Python. Look at moving some of these bindings into this package so backtests can be run from Python.

Key feature add would be to see whether a strategy could be created in Python and then runs in Rust.

@calumrussell What do you think about doing this with pyo3?

commented

@calumrussell What do you think about doing this with pyo3?

Yes, I was using pyo3 as the entrypoint in an application using alator (i.e. you call a python script to run the backtest) and it works. The problem is that you have copies at the boundary between Python and Rust so there was a performance hit. One way to get around this could be to implement the DataSource trait with pyo3 types like PyDict or possibly something like Arrow.

I decided to abandon this path because I wanted to write a strategy in Python and then run it in Rust, as opposed to just adding an entrypoint. This is possible and would only require building implementations around pyo3 types but it adds a layer of complexity because pyo3 types aren't native. I am not sure what the performance implications would be (again, Arrow may also be reasonable as it is zero-copy).

So I decided to go for a complete split of the components - #22 - so you could have a Python trading strategy passing messages to a broker running in Rust with complete separation. This will hurt performance too but with a justifiable improvement in flexibility. This is my current plan for this issue.

Hmm. I believe, if past experience serves me correctly, that zero copy interopt between rust <-> python is possible, just a lot of work. I'll see if I've got some code that I can share re that,

commented

Yes, you can do that by implementing a DataSource from https://github.com/calumrussell/alator/blob/main/src/input/mod.rs with pyo3 types (for example, PyDict) or, possibly, using an Arrow type (I haven't tried this, I believe Arrow only has arrays so you would need to add some more fields to the default HashMapInput). There may be a copy as you return a Quote too, but the impact of that is probably quite minimal.

As an example:

#[derive(Clone, Debug)]
pub struct PyInput {
    quotes: PyDict,
    dividends: PyDict,
    clock: Clock,
}

impl DataSource for PyInput {
    ...
}

The reason why I am not adding to this library is because I have been moving towards needing a strategy written in Python as well, which is possible (I think) but more complex. So I have decided to go in a different direction.

Got it.