Spread feeds

I'm currently working on spread trading and have some architectural improvements in mind that I'd like to discuss. Basically what I'd like to achieve is having a user defined spread feed that can be traded as a single instrument, so all analyzers, observers etc work just as for regular feeds. In order to avoid special casing this feed all over the place, I was considering adding an intermediate order processing layer to the data classes. By default they would simply pass all operations directly to the broker, in case of the spread feed they would dispatch to the underlying datas/brokers, using the appropriate order types and sizes depending on the feed configuration.

Why do you need to have a spread as a data feed, but not as an indicator calculated in strategy __init__(), for example?
At the end of the day you still send orders to original data feeds, not to spread data feed.

For instance for pairs trading, but let's just make it more general and say I want to have user defined instruments, be it spreads, indices or other kinds of combinations. The reason for having a data represent it is, as I wrote, to be able to treat it like a single symbol without having to special case it in analyzers, observers, PnL calculations etc. From what I gathered from their documentation, this seems to be how multiple commercial products allow to represent this.

Ok. Probably you will need to rewrite also observers and analyzers since most of them are using broker's value/cash data and actual trades/orders data. Which you are not going to touch based on my understanding.

Broker cash/value should still be correct to use. Regarding trades and positions, they all use notifiers routed through cerebro/strategies/..., not direct access to the broker, so they might have to go through the data as well. Not sure about that part yet, will investigative.

I'd like to hear from @backtrader if such an architectorial change would be considered for upstream, assuming it is well designed and coded and doesn't break things.

backtrader would need an architectural rewrite itself. It went through many iterations and in an attempt to keep backwards compatibility with anything previously implemented, many workarounds, quirks and others were added.