def modify(self, broker: Broker, **kwargs): """ Modify an existing order """ order_args = { "order_id": self.order_id, "quantity": self.quantity, "price": self.price, "trigger_price": self.trigger_price, "order_type": self.order_type.upper(), "disclosed_quantity": self.disclosed_quantity, } dct = {k: v for k, v in kwargs.items() if k not in order_args.keys()} order_args.update(dct) broker.order_modify(**order_args)
def compound_order_average_prices(): com = CompoundOrder(broker=Broker()) com.add_order( symbol="aapl", quantity=20, side="buy", order_id="111111", filled_quantity=20, average_price=1000, ) com.add_order( symbol="aapl", quantity=20, side="buy", order_id="222222", filled_quantity=20, average_price=900, ) com.add_order( symbol="goog", quantity=20, side="sell", order_id="333333", filled_quantity=20, average_price=700, ) com.add_order( symbol="goog", quantity=15, side="sell", order_id="444444", filled_quantity=15, average_price=600, ) return com
def simple_compound_order(): com = CompoundOrder(broker=Broker()) com.add_order( symbol="aapl", quantity=20, side="buy", filled_quantity=20, average_price=920, status="COMPLETE", order_id="aaaaaa", ) com.add_order( symbol="goog", quantity=10, side="sell", filled_quantity=10, average_price=338, status="COMPLETE", order_id="bbbbbb", ) com.add_order( symbol="aapl", quantity=12, side="sell", filled_quantity=9, average_price=975, order_id="cccccc", ) return com
def test_option_strategy_update_orders( simple_compound_order, compound_order_average_prices ): broker = Broker() strategy = OptionStrategy(broker=broker) strategy.add_order(simple_compound_order) strategy.add_order(compound_order_average_prices) # Reset order_id to None to simulate new orders for order in simple_compound_order.orders: order.order_id = None for order in compound_order_average_prices.orders: order.order_id = None order_data = { "aaaaaa": {"order_id": "aaaaaa", "exchange_order_id": 10001}, "bbbbbb": {"order_id": "bbbbbb", "exchange_order_id": 10002}, "333333": {"order_id": "333333", "exchange_order_id": 10003}, "111111": {"order_id": "111111", "exchange_order_id": 10004}, } strategy.update_orders(data=order_data) # Order not updated for completed orders for order in strategy.all_orders: if order.order_id in ["333333", "111111"]: assert ( order.exchange_order_id == order_data[order.order_id]["exchange_order_id"] ) else: # Already completed orders will have no exchange_order_id in dummy data assert order.exchange_order_id is None
def test_option_order_add_all_orders(): broker = Broker() order = OptionOrder( symbol="nifty", spot=17144, expiry=923, step=50, contracts=[(0, "c", "b", 50), (0, "p", "b", 50)], broker=broker, ) known = pendulum.datetime(2021, 1, 1, 10) pendulum.set_test_now(known) orders = [ Order( symbol="NIFTY92317150CE", side="buy", quantity=50, exchange="NSE", timezone="Asia/Kolkata", order_type="MARKET", ), Order( symbol="NIFTY92317150PE", side="buy", quantity=50, exchange="NSE", timezone="Asia/Kolkata", order_type="MARKET", ), ] order.add_all_orders(exchange="NSE", timezone="Asia/Kolkata") for i in range(len(orders)): order.orders[i].internal_id = orders[i].internal_id pendulum.set_test_now() assert order.orders == orders
def test_option_strategy_all_orders(simple_compound_order): order = simple_compound_order broker = Broker() strategy = OptionStrategy(broker=broker) for i in range(3): strategy.add_order(order) assert len(strategy.all_orders) == 9
def execute(self, broker: Broker, **kwargs) -> Optional[str]: """ Execute an order on a broker, place a new order kwargs Additional arguments to the order Note ---- Only new arguments added to the order in keyword arguments """ # Do not place a new order if this order is complete or has order_id if not (self.is_complete) and not (self.order_id): order_args = { "symbol": self.symbol.upper(), "side": self.side.upper(), "order_type": self.order_type.upper(), "quantity": self.quantity, "price": self.price, "trigger_price": self.trigger_price, "disclosed_quantity": self.disclosed_quantity, } dct = {k: v for k, v in kwargs.items() if k not in order_args.keys()} order_args.update(dct) order_id = broker.order_place(**order_args) self.order_id = order_id return order_id else: return self.order_id
def test_option_strategy_orders(simple_compound_order): order = simple_compound_order broker = Broker() strategy = OptionStrategy(broker=broker) strategy.add_order(order) assert len(strategy.orders) == 1 strategy.add_order(order) assert len(strategy.orders) == 2
def test_option_strategy_call_attribute_do_not_exist( simple_compound_order, compound_order_average_prices ): broker = Broker() strategy = OptionStrategy(broker=broker) strategy.add_order(simple_compound_order) strategy.add_order(compound_order_average_prices) assert strategy._call("no_attribute") == [None, None]
def test_option_strategy_call(simple_compound_order, compound_order_average_prices): broker = Broker() strategy = OptionStrategy(broker=broker) strategy.add_order(simple_compound_order) strategy.add_order(compound_order_average_prices) assert strategy._call("count") == [3, 4] for i in range(2): strategy.add_order(simple_compound_order) assert strategy._call("count") == [3, 4, 3, 3]
def test_option_strategy_update_ltp(simple_compound_order): order = simple_compound_order broker = Broker() strategy = OptionStrategy(broker=broker) for i in range(3): strategy.add_order(order) strategy.update_ltp({"goog": 415}) for order in strategy.orders: order.ltp["goog"] == 415
def test_option_strategy_can_exit_strategy(compound_order_average_prices): com = compound_order_average_prices broker = Broker() strategy = OptionStrategy(profit=1000, loss=-1000, broker=broker) strategy.add_order(com) strategy.update_ltp({"aapl": 925, "goog": 620}) print(strategy.total_mtm, strategy.can_exit_strategy) assert strategy.can_exit_strategy is False strategy.update_ltp({"aapl": 1000, "goog": 800}) assert strategy.can_exit_strategy is True
def test_option_strategy_is_profit_hit(compound_order_average_prices): com = compound_order_average_prices broker = Broker() strategy = OptionStrategy(profit=1000, loss=-1000, broker=broker) strategy.add_order(com) strategy.update_ltp({"aapl": 925, "goog": 620}) assert strategy.total_mtm == 300 assert strategy.is_profit_hit is False strategy.update_ltp({"aapl": 1025, "goog": 620}) assert strategy.is_profit_hit is True
def test_option_order_default_format_function(): broker = Broker() order = OptionOrder( symbol="nifty", spot=17128, expiry=923, contracts=[(0, "c", "b", 1), (0, "p", "b", 1)], broker=broker, ) assert order._fmt_function("nifty", 923, 17200, "c") == "NIFTY92317200CE"
def test_option_strategy_update_ltp( simple_compound_order, compound_order_average_prices ): broker = Broker() strategy = OptionStrategy(broker=broker) strategy.add_order(simple_compound_order) strategy.add_order(compound_order_average_prices) strategy.update_ltp({"amzn": 300, "goog": 350}) for order in strategy.orders: assert order.ltp == {"amzn": 300, "goog": 350}
def test_option_order_generate_contract_names(): broker = Broker() order = OptionOrder( symbol="nifty", spot=17144, expiry=923, step=50, contracts=[(0, "c", "b", 1), (0, "p", "b", 1)], broker=broker, ) assert order._generate_contract_names() == ["NIFTY92317150CE", "NIFTY92317150PE"]
def test_option_order_generate_strikes(contracts, spot, step, expected): broker = Broker() order = OptionOrder( symbol="nifty", spot=spot, expiry=923, contracts=contracts, broker=broker, step=step, ) assert order._generate_strikes() == expected
def test_option_strategy_total_mtm(compound_order_average_prices): broker = Broker() strategy = OptionStrategy(broker=broker) for i in range(5): strategy.add_order(compound_order_average_prices) strategy.update_ltp({"aapl": 900, "goog": 300}) assert strategy.total_mtm == 52500 for i in range(5): strategy.add_order(compound_order_average_prices) strategy.update_ltp({"aapl": 950, "goog": 550}) assert strategy.total_mtm == 37500
def test_option_strategy_positions(simple_compound_order): broker = Broker() order = simple_compound_order strategy = OptionStrategy(broker=broker) strategy.add_order(deepcopy(order)) strategy.add_order(deepcopy(order)) order.add_order( symbol="aapl", quantity=20, side="buy", filled_quantity=20, average_price=920, status="COMPLETE", ) strategy.add_order(deepcopy(order)) assert strategy.positions == {"aapl": 53, "goog": -30}
def test_stop_limit_order(): broker = Broker() order= StopLimitOrder( symbol="aapl", side="buy", quantity=100, trigger_price=850, broker=broker, ) assert order.orders[-1].price == 850 order= StopLimitOrder( symbol="aapl", side="buy", quantity=100, trigger_price=850, stop_limit_price=855, broker=broker ) assert order.orders[-1].price == 855
def cancel(self, broker: Broker): """ Cancel an existing order """ broker.order_cancel(order_id=self.order_id)
def test_order_has_parent(): order = Order(symbol="aapl", side="buy", quantity=10) assert order.has_parent is False com = CompoundOrder(broker=Broker()) com.add_order(symbol="aapl", side="buy", quantity=10) com.orders[0].has_parent is True
def test_compound_order_add_order(): order = CompoundOrder(broker=Broker()) order.add_order(symbol="aapl", quantity=5, side="buy", filled_quantity=5) order.add_order(symbol="aapl", quantity=4, side="buy", filled_quantity=4) assert order.count == 2 assert order.positions == Counter({"aapl": 9})