robcarver17 / pysystemtrade

Systematic Trading in python
GNU General Public License v3.0
2.48k stars 797 forks source link

Does priceMagnifier work in IB config? #628

Closed emretezel closed 2 years ago

emretezel commented 2 years ago

Hi Rob,

I wanted to ask whether priceMagnifier column does what is expected in the ib_config_futures.csv file.

For example for Orange Juice futures, my historical data displays prices correctly in cents, but when I update daily prices from IB, the prices come in in dollars. So I have changed the priceMagnifier to 100 and updated daily prices again, but it doesn't seem to be doing anything?

Any tip on overcoming this issue greatly appreciated.

Best, Emre

robcarver17 commented 2 years ago

Consider wheat (I don't trade OJ)

Basically I correct everything so the price coming from IB can be used without changing it, whatever the units are.

Wheat has a contract size of $5000, but wheat prices come from IB in cents:

2022-05-23 15:00:00    1088.5
2022-05-23 16:00:00    1087.5
2022-05-23 17:00:00    1088.5
2022-05-23 18:00:00    1094.0
2022-05-23 19:00:00    1093.5
INTERACTIVE DIAGONSTICS
1: View instrument configuration

10: View instrument configuration data
11: View contract configuration data
12: View trading hours for all instruments

Your choice? <RETURN for Back> 10
Instrument code?WHEAT
instrumentMetaData(Description='Wheat', Pointsize=50.0, Currency='USD', AssetClass='Ags', Slippage=0.25, PerBlock=2.9, Percentage=0.0, PerTrade=0.0)
futuresInstrumentWithIBConfigData(instrument=WHEAT, ib_data=symbol='ZW', exchange='ECBOT', currency='', ibMultiplier='5000.0', priceMagnifier=100.00, ignoreWeekly='False, effective_multiplier=50.00' )

My configuration: Pointsize=50.0 (so if the price moves by 1 cent, then I stand to gain or lose $50)

IB configuration: ibMultiplier='5000.0', priceMagnifier=100.00 effective_multiplier=50.00 (this is ibMultiplier / priceMagnifier. I want it to be the same as my pointsize. It is)

The actual price isn't adjusted, it is however it comes from IB. ibMultiplier and priceMagnifier are just used to make sure that the IB contract spec matches what I am expecting. effective_multiplier is just a diagnostic field.

Note if the price was coming from IB in dollars then I would set priceMagnifer to 1 and the ibMultiplier would be the same as my point size.

emretezel commented 2 years ago

In this instance probably both your initial Barchart historical data and IB feed for Wheat are in cents.

In my case my historical data which I uploaded into arctic is in cents, but new IB data comes in dollars.

Do you recommend scaling my historical data before upload?

Thank you, Emre

robcarver17 commented 2 years ago

"Do you recommend scaling my historical data before upload?"

Well the alternative is very hacky, always scaling IB prices by some number whenever you get them. So yes, I would recommend it.

tgibson11 commented 2 years ago

With all respect, I don't see how the alternative is hacky.

In fact, I would argue that it would be better if all price data in the database was in dollars (or major currency units).

By storing price data as-is, you are also required to know where the data came from in order to use it. In addition to emretzel's scenario, you might have EOD and intra-day data from different sources. Or different sources for different instruments. Or you might use one data source for running the system, but another for live trading. Each of those scenarios would currently require you to know where the price data came from, in order to know what price magnifier to apply. Seems to me like it would make more sense to apply the price magnifier at the point the data is received, and then everything downstream doesn't have to worry about it.

To be clear, I'm not suggesting pysystemtrade should be changed to work this way...just observing that it seems preferable to have standardized price data.

Is there some aspect I'm not seeing?

robcarver17 commented 2 years ago

FWIW in my previous (not open source and very hacky) python system I did it like this. I applied a constant multiplier to certain IB prices. It was a pain, because you had to apply it to ticks, limit prices, historical prices... quite a few places. Also if I had to interact with the IB system any other way eg through web trader or looking at reports I had to do the conversions in my head.

For me personally, any use of weird constants should be discouraged if at all possible. If you must then of course it's preferable to use them on the outer layers where you have a broker or data source specific API that does the conversion so the rest of the system doesn't care about it.

If you were using multiple sources then of course you would have to apply a weird constant somewhere, eithier in the IB feed or the barchart feed. For me it's preferable not to do this for IB data since that means for me I don't have to use a weird constant at all in my main production code. Since I only use barchart for backfilling, which is a one off exercise, I just need to apply it once per market in the little hacky scripts I use for this purpose. If I was using barchart for EOD prices then of course I would do this properly, with a table of multipliers and so on.

Having all prices in dollars or EUR or whatever isn't 'standardised', since a price is effectively just a number. It doesn't have any value. It only gets currency value when multiplied by a multiplier that has a currency attached to it. Just because some prices - mainly in commodities - are dollar prices, or cent prices, doesn't mean anything as far as the trading system goes and isn't true of many other markets. As an example, the price of the VIX isn't $20. It's 20. If you go out and buy eurodollar futures, you pay 99.50, not $99.50. The price of ES isn't $4000 it's 4000. I don't personally get any extra intuition from translating all commodity prices into round number units.

For me 'standardized' basically means whatever IB reports the price as. Any other price source like barchart has to conform to this.

I will finish with an anecdote. At AHL we had quite a few of these weird multipliers, mainly because our proprietary trading software (long since retired, so I can talk about it) had a very efficient way of storing time series data but which wasn't true floating point. So for something like KRWUSD you couldn't store prices every accurately, unless you first multiplied them by a magic number. Let's say it was 100,000.

The very first trading strategy I had implemented there was set to start running at midnight. One of the developers had coded up a production system that replaced my crappy research code, so I thought all would be well.

I got a phone call at 1am.

"Did you really mean to buy the entire outstanding national debt of Korea?" "Er.... no?" "OK, I will cancel this order for a million korean 10 year bond futures then"

Of course what had happened was the developer (who was also inexperienced) hadn't known about the magic number, and the strategy code had very helpfully multiplied everything by 100,000.

So you can see why I'm a little biased...

emretezel commented 2 years ago

I am going to adjust my historical data, thank you both.