-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Feat/order size #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/order size #24
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a daring endeavor, or at least that was the impression I got the last time I was looking at it. Hope it pans out.
Position size likely is the best first step towards #10. The next would probably be order pyramiding so one can do:
buy 2
buy 3
buy 5
sell 10
Have an idea how to go about that?
@@ -493,7 +503,8 @@ def _open_position(self, price, is_long): | |||
|
|||
i, price = self._get_market_price(price) | |||
|
|||
position = float(self._cash * self._leverage / (price * (1 + self._commission))) | |||
size = self._cash if self.orders._size is None else self.orders._size | |||
position = float(size * self._leverage / (price * (1 + self._commission))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this position
computation correct? You effectively replace former cash
with size
, but size actually corresponds to cash / price
?
I think when size is given, position might better be float(size) if enough_cash else error
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention for the size
variable being computed as such is because:
- If size is not specified when performing an order, it will default to the default behaviour of using entire holding cash amount.
- I did not notice there was a
margin
option to define a leveraged trade. (Only found out about it after reading: How to use backtesting.py for forex trading #10 ) Was initially under the assumption that all trades were on a 1:1 leverage. Under my assumption, i believed that specifying themargin
option wasn't needed in order to define a "leveraged trade". In fact, by specifying an order size that is larger than your holding cash amount would technically mean you enter a trade on cross margin. (which was why I did not implement a check forif enough_cash
). Reason for this assumption is largely influenced by Trading View's pine script, and how "leveraged trades" would be entered under their backtesting tools.
So my thoughts are as follows, and would need some clarification:
- Does the library actually calculate liquidations. If it does, the
margin
option would come in handy for that. A quick look into the code base shows howmargin
is used to calculateleverage
amount. Butmargin
andleverage
are simply being used in reporting functions and likely no where else? - Would it make sense to have margin be calculated dynamically if order size was specified, and larger than than holding cash. In that case, we could dynamically calculate a cross margin on init instead.
Would love to take a stab at pyramiding too, there are indeed many use cases for that. Let me know your thoughts. I might be working on a path different than the philosophy of this library. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the library actually calculate liquidations.
It simulates them.
backtesting.py/backtesting/backtesting.py
Lines 561 to 570 in b3cfaff
# Log account equity for the equity curve | |
equity = self.equity | |
self.log.equity[i] = equity | |
# Hovever, if negative, set all to 0 and stop the simulation | |
if equity < 0: | |
self._close_position() | |
self._cash = 0 | |
self.log.equity[i:] = 0 | |
raise _OutOfMoneyError |
margin=
therefore represents initial and maintenance margin of the trades. It's used only in stats and plots so the interested user gets a rough idea on how leveraged their strategy is allowed to be to still remain afloat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In our case, position
is actually equal to size
when the user requests it. Thus, we only need to deduct the commission and then confirm we have (leveraged) cash to cover it all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think? 😅
An error message is displayed during this operation.
An error occurs when only a target price is specified for a sell order. Conditional error in broker class Please solve. |
Does this change work properly? |
@kernc I am just starting out with backtesting and it seems like the order sizing isn't in place. I am running backtesting version 0.1.7 however the changes above seem no to be commited. |
@kernc when do you expect to release the 0.2.0 version with this feature? |
429e859
to
de1bcf8
Compare
Added order sizing feature. Usage is as per discussion in #3
Opted to use absolute position size instead of a percentage based off holding cash.
Ran with the code on the example, with a tweak on sizing:
On a quick eyeball, it seems to work.
Did write one simple test. Let me know if there needs be further coverage.