| 741 | |
| 742 | |
| 743 | class _Broker: |
| 744 | def __init__(self, *, data, cash, spread, commission, margin, |
| 745 | trade_on_close, hedging, exclusive_orders, index): |
| 746 | assert cash > 0, f"cash should be > 0, is {cash}" |
| 747 | assert 0 < margin <= 1, f"margin should be between 0 and 1, is {margin}" |
| 748 | self._data: _Data = data |
| 749 | self._cash = cash |
| 750 | |
| 751 | if callable(commission): |
| 752 | self._commission = commission |
| 753 | else: |
| 754 | try: |
| 755 | self._commission_fixed, self._commission_relative = commission |
| 756 | except TypeError: |
| 757 | self._commission_fixed, self._commission_relative = 0, commission |
| 758 | assert self._commission_fixed >= 0, 'Need fixed cash commission in $ >= 0' |
| 759 | assert -.1 <= self._commission_relative < .1, \ |
| 760 | ("commission should be between -10% " |
| 761 | f"(e.g. market-maker's rebates) and 10% (fees), is {self._commission_relative}") |
| 762 | self._commission = self._commission_func |
| 763 | |
| 764 | self._spread = spread |
| 765 | self._leverage = 1 / margin |
| 766 | self._trade_on_close = trade_on_close |
| 767 | self._hedging = hedging |
| 768 | self._exclusive_orders = exclusive_orders |
| 769 | |
| 770 | self._equity = np.tile(np.nan, len(index)) |
| 771 | self.orders: List[Order] = [] |
| 772 | self.trades: List[Trade] = [] |
| 773 | self.position = Position(self) |
| 774 | self.closed_trades: List[Trade] = [] |
| 775 | |
| 776 | def _commission_func(self, order_size, price): |
| 777 | return self._commission_fixed + abs(order_size) * price * self._commission_relative |
| 778 | |
| 779 | def __repr__(self): |
| 780 | return f'<Broker: {self._cash:.0f}{self.position.pl:+.1f} ({len(self.trades)} trades)>' |
| 781 | |
| 782 | def new_order(self, |
| 783 | size: float, |
| 784 | limit: Optional[float] = None, |
| 785 | stop: Optional[float] = None, |
| 786 | sl: Optional[float] = None, |
| 787 | tp: Optional[float] = None, |
| 788 | tag: object = None, |
| 789 | *, |
| 790 | trade: Optional[Trade] = None) -> Order: |
| 791 | """ |
| 792 | Argument size indicates whether the order is long or short |
| 793 | """ |
| 794 | size = float(size) |
| 795 | stop = stop and float(stop) |
| 796 | limit = limit and float(limit) |
| 797 | sl = sl and float(sl) |
| 798 | tp = tp and float(tp) |
| 799 | |
| 800 | is_long = size > 0 |