From ebb22d72d338d12b5c040649377aa7a7f85d3382 Mon Sep 17 00:00:00 2001 From: Kyle Widmann Date: Thu, 13 Feb 2025 21:49:15 -0500 Subject: [PATCH 1/6] Update broker to handle relative order sizing --- pytrade/broker.py | 5 +++++ pytrade/data.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pytrade/broker.py b/pytrade/broker.py index 36b3dd2..e9dbda4 100644 --- a/pytrade/broker.py +++ b/pytrade/broker.py @@ -1,3 +1,4 @@ +from math import copysign from typing import List, Tuple from pytrade.data import CandleData @@ -40,6 +41,10 @@ def order(self, order: Order): def process_orders(self): for order in self._orders: + if order.size > 0 and order.size < 1: + _data = self._data_context.get(order.instrument) + _adjusted_size = copysign(self.margin_available * self.leverage * abs(order.size)) // _data.last_price + order.resize(_adjusted_size) self.client.order(order) self._orders.clear() diff --git a/pytrade/data.py b/pytrade/data.py index 86c4def..edb8d44 100644 --- a/pytrade/data.py +++ b/pytrade/data.py @@ -121,7 +121,7 @@ def __new__(cls, *args, **kwargs): # Need to handle case where instantiatied and different max size is provided return cls.instance - def get(self, instrument: Instrument, granularity: Granularity): + def get(self, instrument: Instrument, granularity: Granularity) -> InstrumentCandles: key = (instrument, granularity) instrument_candles: InstrumentCandles = self._data.get( key, InstrumentCandles(max_size=self._max_size) From 65132224f9cd99724d1c995de7748efcdab25895 Mon Sep 17 00:00:00 2001 From: Kyle Widmann Date: Fri, 14 Feb 2025 06:37:28 -0500 Subject: [PATCH 2/6] Adding rel order size calculation to strategy --- pytrade/strategy.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pytrade/strategy.py b/pytrade/strategy.py index a40bef6..89b5b1d 100644 --- a/pytrade/strategy.py +++ b/pytrade/strategy.py @@ -1,6 +1,7 @@ import asyncio from abc import abstractmethod from datetime import timedelta, timezone +from math import copysign from typing import Optional from pandas import Timestamp @@ -96,6 +97,9 @@ def get_data( self, instrument: Instrument, granularity: Granularity ) -> IInstrumentData: return self._data_context.get(instrument, granularity) + + def _get_order_size(self, rel_size: float, price: float): + return copysign(self.broker.margin_available * self.broker.leverage * abs(rel_size)) // price @abstractmethod def _init(self) -> None: From b071f2a91446e9103ea46127243f2648f000a340 Mon Sep 17 00:00:00 2001 From: Kyle Widmann Date: Fri, 14 Feb 2025 08:07:05 -0500 Subject: [PATCH 3/6] Remove order sizing from broker --- pytrade/broker.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pytrade/broker.py b/pytrade/broker.py index e9dbda4..be358da 100644 --- a/pytrade/broker.py +++ b/pytrade/broker.py @@ -41,10 +41,6 @@ def order(self, order: Order): def process_orders(self): for order in self._orders: - if order.size > 0 and order.size < 1: - _data = self._data_context.get(order.instrument) - _adjusted_size = copysign(self.margin_available * self.leverage * abs(order.size)) // _data.last_price - order.resize(_adjusted_size) self.client.order(order) self._orders.clear() From e3c748505cc067df20fc5ce0745ee2941c8cbd9c Mon Sep 17 00:00:00 2001 From: Kyle Widmann Date: Fri, 14 Feb 2025 08:12:07 -0500 Subject: [PATCH 4/6] Fix copysign call --- pytrade/broker.py | 1 - pytrade/data.py | 4 +++- pytrade/strategy.py | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pytrade/broker.py b/pytrade/broker.py index be358da..36b3dd2 100644 --- a/pytrade/broker.py +++ b/pytrade/broker.py @@ -1,4 +1,3 @@ -from math import copysign from typing import List, Tuple from pytrade.data import CandleData diff --git a/pytrade/data.py b/pytrade/data.py index edb8d44..58a2638 100644 --- a/pytrade/data.py +++ b/pytrade/data.py @@ -121,7 +121,9 @@ def __new__(cls, *args, **kwargs): # Need to handle case where instantiatied and different max size is provided return cls.instance - def get(self, instrument: Instrument, granularity: Granularity) -> InstrumentCandles: + def get( + self, instrument: Instrument, granularity: Granularity + ) -> InstrumentCandles: key = (instrument, granularity) instrument_candles: InstrumentCandles = self._data.get( key, InstrumentCandles(max_size=self._max_size) diff --git a/pytrade/strategy.py b/pytrade/strategy.py index 89b5b1d..7f2c5b8 100644 --- a/pytrade/strategy.py +++ b/pytrade/strategy.py @@ -97,9 +97,15 @@ def get_data( self, instrument: Instrument, granularity: Granularity ) -> IInstrumentData: return self._data_context.get(instrument, granularity) - + def _get_order_size(self, rel_size: float, price: float): - return copysign(self.broker.margin_available * self.broker.leverage * abs(rel_size)) // price + return ( + copysign( + self.broker.margin_available * self.broker.leverage * abs(rel_size), + rel_size, + ) + // price + ) @abstractmethod def _init(self) -> None: From af9d96e157e1967434c21f652e1bd8efa9e7c2de Mon Sep 17 00:00:00 2001 From: Kyle Widmann Date: Sun, 16 Feb 2025 10:48:47 -0500 Subject: [PATCH 5/6] Remove relative order sizing from strategy --- pytrade/strategy.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pytrade/strategy.py b/pytrade/strategy.py index 7f2c5b8..5e77fc3 100644 --- a/pytrade/strategy.py +++ b/pytrade/strategy.py @@ -98,15 +98,6 @@ def get_data( ) -> IInstrumentData: return self._data_context.get(instrument, granularity) - def _get_order_size(self, rel_size: float, price: float): - return ( - copysign( - self.broker.margin_available * self.broker.leverage * abs(rel_size), - rel_size, - ) - // price - ) - @abstractmethod def _init(self) -> None: """ From 73ef49438d5409ae9fdf25ba0d6023778e1df6d3 Mon Sep 17 00:00:00 2001 From: Kyle Widmann Date: Sun, 16 Feb 2025 10:49:52 -0500 Subject: [PATCH 6/6] lint fixes --- pytrade/strategy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pytrade/strategy.py b/pytrade/strategy.py index 5e77fc3..a40bef6 100644 --- a/pytrade/strategy.py +++ b/pytrade/strategy.py @@ -1,7 +1,6 @@ import asyncio from abc import abstractmethod from datetime import timedelta, timezone -from math import copysign from typing import Optional from pandas import Timestamp