When an `Order` is filled, it results in an active `Trade`. Find active trades in `Strategy.trades` and closed, settled trades in `Strategy.closed_trades`.
| 558 | |
| 559 | |
| 560 | class Trade: |
| 561 | """ |
| 562 | When an `Order` is filled, it results in an active `Trade`. |
| 563 | Find active trades in `Strategy.trades` and closed, settled trades in `Strategy.closed_trades`. |
| 564 | """ |
| 565 | def __init__(self, broker: '_Broker', size: int, entry_price: float, entry_bar, tag): |
| 566 | self.__broker = broker |
| 567 | self.__size = size |
| 568 | self.__entry_price = entry_price |
| 569 | self.__exit_price: Optional[float] = None |
| 570 | self.__entry_bar: int = entry_bar |
| 571 | self.__exit_bar: Optional[int] = None |
| 572 | self.__sl_order: Optional[Order] = None |
| 573 | self.__tp_order: Optional[Order] = None |
| 574 | self.__tag = tag |
| 575 | self._commissions = 0 |
| 576 | |
| 577 | def __repr__(self): |
| 578 | return f'<Trade size={self.__size} time={self.__entry_bar}-{self.__exit_bar or ""} ' \ |
| 579 | f'price={self.__entry_price}-{self.__exit_price or ""} pl={self.pl:.0f}' \ |
| 580 | f'{" tag=" + str(self.__tag) if self.__tag is not None else ""}>' |
| 581 | |
| 582 | def _replace(self, **kwargs): |
| 583 | for k, v in kwargs.items(): |
| 584 | setattr(self, f'_{self.__class__.__qualname__}__{k}', v) |
| 585 | return self |
| 586 | |
| 587 | def _copy(self, **kwargs): |
| 588 | return copy(self)._replace(**kwargs) |
| 589 | |
| 590 | def close(self, portion: float = 1.): |
| 591 | """Place new `Order` to close `portion` of the trade at next market price.""" |
| 592 | assert 0 < portion <= 1, "portion must be a fraction between 0 and 1" |
| 593 | # Ensure size is an int to avoid rounding errors on 32-bit OS |
| 594 | size = copysign(max(1, int(round(abs(self.__size) * portion))), -self.__size) |
| 595 | order = Order(self.__broker, size, parent_trade=self, tag=self.__tag) |
| 596 | self.__broker.orders.insert(0, order) |
| 597 | |
| 598 | # Fields getters |
| 599 | |
| 600 | @property |
| 601 | def size(self): |
| 602 | """Trade size (volume; negative for short trades).""" |
| 603 | return self.__size |
| 604 | |
| 605 | @property |
| 606 | def entry_price(self) -> float: |
| 607 | """Trade entry price.""" |
| 608 | return self.__entry_price |
| 609 | |
| 610 | @property |
| 611 | def exit_price(self) -> Optional[float]: |
| 612 | """Trade exit price (or None if the trade is still active).""" |
| 613 | return self.__exit_price |
| 614 | |
| 615 | @property |
| 616 | def entry_bar(self) -> int: |
| 617 | """Candlestick bar index of when the trade was entered.""" |
no outgoing calls