Skip to content
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

Error creating OTOCO order v8.5 #177

Open
salamad opened this issue Nov 12, 2024 · 14 comments
Open

Error creating OTOCO order v8.5 #177

salamad opened this issue Nov 12, 2024 · 14 comments

Comments

@salamad
Copy link

salamad commented Nov 12, 2024

Trying to follow the example in the documentation to create an OTOCO order. Modified it for a simulated COIN transaction. Error message seems to indicate that something may be missing in the NewComplexOrder method and when calling the TastyTrade API. Not 100% sure.

Below is the OTOCO order once created by the NewComplexOrder method call

NewComplexOrder(orders=[NewOrder(time_in_force=<OrderTimeInForce.GTC: 'GTC'>, order_type=<OrderType.LIMIT: 'Limit'>, source='tastyware/tastytrade:v8.5', legs=[Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220C00400000', action=<OrderAction.BUY_TO_CLOSE: 'Buy to Close'>, quantity=Decimal('1'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220C00450000', action=<OrderAction.SELL_TO_CLOSE: 'Sell to Close'>, quantity=Decimal('2'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220P00250000', action=<OrderAction.BUY_TO_CLOSE: 'Buy to Close'>, quantity=Decimal('1'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220P00220000', action=<OrderAction.SELL_TO_CLOSE: 'Sell to Close'>, quantity=Decimal('2'), remaining_quantity=None, fills=None)], gtc_date=None, stop_trigger=None, price=Decimal('4.4'), price_effect=<PriceEffect.CREDIT: 'Credit'>, value=None, value_effect=None, partition_key=None, preflight_id=None, rules=None), NewOrder(time_in_force=<OrderTimeInForce.GTC: 'GTC'>, order_type=<OrderType.STOP: 'Stop'>, source='tastyware/tastytrade:v8.5', legs=[Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220C00400000', action=<OrderAction.BUY_TO_CLOSE: 'Buy to Close'>, quantity=Decimal('1'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220C00450000', action=<OrderAction.SELL_TO_CLOSE: 'Sell to Close'>, quantity=Decimal('2'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220P00250000', action=<OrderAction.BUY_TO_CLOSE: 'Buy to Close'>, quantity=Decimal('1'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220P00220000', action=<OrderAction.SELL_TO_CLOSE: 'Sell to Close'>, quantity=Decimal('2'), remaining_quantity=None, fills=None)], gtc_date=None, stop_trigger=Decimal('2.15'), price=None, price_effect=<PriceEffect.DEBIT: 'Debit'>, value=None, value_effect=None, partition_key=None, preflight_id=None, rules=None)], source='tastyware/tastytrade:v8.5', trigger_order=NewOrder(time_in_force=<OrderTimeInForce.GTC: 'GTC'>, order_type=<OrderType.LIMIT: 'Limit'>, source='tastyware/tastytrade:v8.5', legs=[Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220C00400000', action=<OrderAction.BUY_TO_OPEN: 'Buy to Open'>, quantity=Decimal('1'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220C00450000', action=<OrderAction.SELL_TO_OPEN: 'Sell to Open'>, quantity=Decimal('2'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220P00250000', action=<OrderAction.BUY_TO_OPEN: 'Buy to Open'>, quantity=Decimal('1'), remaining_quantity=None, fills=None), Leg(instrument_type=<InstrumentType.EQUITY_OPTION: 'Equity Option'>, symbol='COIN  241220P00220000', action=<OrderAction.SELL_TO_OPEN: 'Sell to Open'>, quantity=Decimal('2'), remaining_quantity=None, fills=None)], gtc_date=None, stop_trigger=None, price=Decimal('0.81'), price_effect=<PriceEffect.CREDIT: 'Credit'>, value=None, value_effect=None, partition_key=None, preflight_id=None, rules=None), type=<ComplexOrderType.OTOCO: 'OTOCO'>)

When calling a dry run order, I'm getting the following error message:

---------------------------------------------------------------------------
TastytradeError                           Traceback (most recent call last)
Cell In[12], line 1
----> 1 resp = account.place_complex_order(session, otoco, dry_run=True)

File ~/.local/lib/python3.9/site-packages/tastytrade/account.py:980, in Account.place_complex_order(self, session, order, dry_run)
    978     url += "/dry-run"
    979 json = order.model_dump_json(exclude_none=True, by_alias=True)
--> 980 data = session.post(url, data=json)
    981 return PlacedOrderResponse(**data)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:109, in Session.post(self, url, **kwargs)
    107 def post(self, url, **kwargs) -> Dict[str, Any]:
    108     response = self.client.post(url, **kwargs)
--> 109     return self._validate_and_parse(response)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:116, in Session._validate_and_parse(self, response)
    115 def _validate_and_parse(self, response: httpx._models.Response) -> Dict[str, Any]:
--> 116     validate_response(response)
    117     return response.json()["data"]

File ~/.local/lib/python3.9/site-packages/tastytrade/utils.py:228, in validate_response(response)
    225         else:
    226             error_message += f"\n{error['domain']}: {error['reason']}"
--> 228 raise TastytradeError(error_message)

TastytradeError: preflight_check_failure: One or more preflight checks failed
invalid_complex_structure: Complex order structure is invalid

You can reproduce it by running:

from decimal import Decimal
from tastytrade.instruments import Option
from tastytrade.order import *

opening = [
    Option.get_option(session, 'COIN  241220C00400000').build_leg(Decimal(1), OrderAction.BUY_TO_OPEN),
    Option.get_option(session, 'COIN  241220C00450000').build_leg(Decimal(2), OrderAction.SELL_TO_OPEN),
    Option.get_option(session, 'COIN  241220P00250000').build_leg(Decimal(1), OrderAction.BUY_TO_OPEN),
    Option.get_option(session, 'COIN  241220P00220000').build_leg(Decimal(2), OrderAction.SELL_TO_OPEN)
]
closing = [
    Option.get_option(session, 'COIN  241220C00400000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
    Option.get_option(session, 'COIN  241220C00450000').build_leg(Decimal(2), OrderAction.SELL_TO_CLOSE),
    Option.get_option(session, 'COIN  241220P00250000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
    Option.get_option(session, 'COIN  241220P00220000').build_leg(Decimal(2), OrderAction.SELL_TO_CLOSE)
]

otoco = NewComplexOrder(
    trigger_order=NewOrder(
        time_in_force=OrderTimeInForce.GTC,
        order_type=OrderType.LIMIT,
        legs=opening,
        price=Decimal('0.81'),
        price_effect=PriceEffect.CREDIT
    ),
    orders=[
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.LIMIT,
            legs=closing,
            price=Decimal('4.4'),  # take profits
            price_effect=PriceEffect.CREDIT
        ),
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.STOP,
            legs=closing,
            stop_trigger=Decimal('2.15'),  # stop loss
            price_effect=PriceEffect.DEBIT
        )
    ]
)

####
# NEED TO DEFINE account and session
####
resp = account.place_complex_order(session, otoco, dry_run=True)
@Graeme22
Copy link
Contributor

Both closing orders should be debit or credit, having one credit and the other debit is an invalid structure.

@salamad
Copy link
Author

salamad commented Nov 12, 2024

Appreciate your prompt response. I am now getting a different error. If I change the order to maintain the correct structure (shown below), I am getting the following error:

---------------------------------------------------------------------------
TastytradeError                           Traceback (most recent call last)
Cell In[15], line 1
----> 1 res = account.place_complex_order(session, otoco, dry_run = True)

File ~/.local/lib/python3.9/site-packages/tastytrade/account.py:980, in Account.place_complex_order(self, session, order, dry_run)
    978     url += "/dry-run"
    979 json = order.model_dump_json(exclude_none=True, by_alias=True)
--> 980 data = session.post(url, data=json)
    981 return PlacedOrderResponse(**data)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:109, in Session.post(self, url, **kwargs)
    107 def post(self, url, **kwargs) -> Dict[str, Any]:
    108     response = self.client.post(url, **kwargs)
--> 109     return self._validate_and_parse(response)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:116, in Session._validate_and_parse(self, response)
    115 def _validate_and_parse(self, response: httpx._models.Response) -> Dict[str, Any]:
--> 116     validate_response(response)
    117     return response.json()["data"]

File ~/.local/lib/python3.9/site-packages/tastytrade/utils.py:228, in validate_response(response)
    225         else:
    226             error_message += f"\n{error['domain']}: {error['reason']}"
--> 228 raise TastytradeError(error_message)

TastytradeError: preflight_check_failure: One or more preflight checks failed
invalid_complex_structure: Complex order structure is invalid
invalid_triggered_order_price: Order price is invalid for this trade.

Not quite sure what is now wrong with the trade. Why is the structure invalid and why is the order price invalid?

from decimal import Decimal
from tastytrade.instruments import Option
from tastytrade.order import *

opening = [
    Option.get_option(session, 'COIN  241220C00400000').build_leg(Decimal(1), OrderAction.BUY_TO_OPEN),
    Option.get_option(session, 'COIN  241220C00450000').build_leg(Decimal(2), OrderAction.SELL_TO_OPEN),
    Option.get_option(session, 'COIN  241220P00250000').build_leg(Decimal(1), OrderAction.BUY_TO_OPEN),
    Option.get_option(session, 'COIN  241220P00220000').build_leg(Decimal(2), OrderAction.SELL_TO_OPEN)
]
closing = [
    Option.get_option(session, 'COIN  241220C00400000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
    Option.get_option(session, 'COIN  241220C00450000').build_leg(Decimal(2), OrderAction.SELL_TO_CLOSE),
    Option.get_option(session, 'COIN  241220P00250000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
    Option.get_option(session, 'COIN  241220P00220000').build_leg(Decimal(2), OrderAction.SELL_TO_CLOSE)
]

otoco = NewComplexOrder(
    trigger_order=NewOrder(
        time_in_force=OrderTimeInForce.GTC,
        order_type=OrderType.LIMIT,
        legs=opening,
        price=Decimal('0.81'),
        price_effect=PriceEffect.CREDIT
    ),
    orders=[
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.LIMIT,
            legs=closing,
            price=Decimal('4.4'),  # take profits
            price_effect=PriceEffect.DEBIT
        ),
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.STOP,
            legs=closing,
            stop_trigger=Decimal('2.15'),  # stop loss
            price_effect=PriceEffect.DEBIT
        )
    ]
)

####
# NEED TO DEFINE account and session
####
resp = account.place_complex_order(session, otoco, dry_run=True)

@Graeme22
Copy link
Contributor

So think about it this way. You're sending an order for a credit, then you're immediately sending two closing orders for a debit which would in theory both fill instantly since the order is actually worth a credit. Tastytrade doesn't allow this because it's nonsensical.

What you could do that would probably work is have all 3 be credits, but set the stop loss at $0 credit.

Are you able to do a corresponding order in the actual Tastytrade platform?

@salamad
Copy link
Author

salamad commented Nov 12, 2024

I can't replicate it in the platform as you mention. When I do a bracket order on the platform, it does allow me to put the profit as a credit and the stop loss as a debit.

We could look at possible another, maybe simpler example. If I have the following legs:

opening = [
    Option.get_option(session, 'AMD   250117C00150000').build_leg(Decimal(1), OrderAction.BUY_TO_OPEN),
    Option.get_option(session, 'AMD   241220C00150000').build_leg(Decimal(1), OrderAction.SELL_TO_OPEN),
    Option.get_option(session, 'AMD   241220P00130000').build_leg(Decimal(1), OrderAction.SELL_TO_OPEN)
]
closing = [
    Option.get_option(session, 'AMD   250117C00150000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
    Option.get_option(session, 'AMD   250117C00150000').build_leg(Decimal(1), OrderAction.SELL_TO_CLOSE),
    Option.get_option(session, 'AMD   250117C00150000').build_leg(Decimal(1), OrderAction.SELL_TO_CLOSE)
]

My trade parameters are as follow:

  1. Net Open Credit of $0.22
  2. Stop Loss of -$0.78
  3. Target Profit of $1.89

No matter how I structure the order, I get either invalid structure or invalid order price error messages. How would you set it up, if you don't mind me asking? I've tried all combinations of CREDIT/CREDIT, DEBIT/DEBIT, CREDIT/DEBIT, etc to no avail.

otoco = NewComplexOrder(
    trigger_order=NewOrder(
        time_in_force=OrderTimeInForce.GTC,
        order_type=OrderType.LIMIT,
        legs=opening,
        price=Decimal('0.22'),
        price_effect=PriceEffect.CREDIT
    ),
    orders=[
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.LIMIT,
            legs=closing,
            price=Decimal('1.89'),  # take profits
            price_effect=PriceEffect.CREDIT
        ),
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.STOP,
            legs=closing,
            stop_trigger=Decimal('0.78'),  # stop loss
            price_effect=PriceEffect.CREDIT
        )
    ]
)

resp = account.place_complex_order(session, otoco, dry_run=True)

@Graeme22
Copy link
Contributor

So I just tried and I wasn't able to build any of these orders in the browser platform.

otoco = NewComplexOrder(
    trigger_order=NewOrder(
        time_in_force=OrderTimeInForce.GTC,
        order_type=OrderType.LIMIT,
        legs=opening,
        price=Decimal('0.22'),
        price_effect=PriceEffect.CREDIT
    ),
    orders=[
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.LIMIT,
            legs=closing,
            price=Decimal('1.89'),  # take profits
            price_effect=PriceEffect.CREDIT
        ),
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.STOP,
            legs=closing,
            stop_trigger=Decimal('0.78'),  # stop loss
            price_effect=PriceEffect.CREDIT
        )
    ]
)

resp = account.place_complex_order(session, otoco, dry_run=True)

And in this case, your take profit and stop loss are both higher than the trigger order price, which also doesn't make sense. And you can't have a price effect of credit for everything either.

@Graeme22
Copy link
Contributor

What I'd recommend is first building the order in the platform, then copying EXACTLY the parameters you see to make sure you're building it right.

The basic concept is this: trigger order is an opening order. The take profit and stop loss are both closing orders, one for wins and the other for losses. So the price effect of both closing orders needs to be opposite that of the trigger order, and all the prices need to look like this: stop loss price < trigger order price < take profit price

@Graeme22
Copy link
Contributor

In the case of the kinds of orders you're doing where in the future they could be worth either a credit or a debit, it may just be a platform limitation that you can't place complex orders in the way you're trying to.

@salamad
Copy link
Author

salamad commented Nov 13, 2024

Thank you for your responses again. I will try to do one of these on the platform and once successful, will attempt to do it via the API and provide feedback. Thank you again

@salamad
Copy link
Author

salamad commented Nov 17, 2024

Hello again. I tried another trade via the desktop and then tried to replicate it via the API. The desktop order was processed with no problem, however, the API call came back with similar errors. Below is code used and output. Attached is screenshot from desktop before the order was placed. Any help is greatly appreciated.

import ttaccount
import ttsession
from decimal import Decimal
from tastytrade.instruments import Option
from tastytrade.order import *

session = ttsession.prod_session()
account = ttaccount.get_account('BA', session)

opening = [
    Option.get_option(session, 'AVGO  250117P00151000').build_leg(Decimal(1), OrderAction.BUY_TO_OPEN),
    Option.get_option(session, 'AVGO  250117P00141000').build_leg(Decimal(1), OrderAction.SELL_TO_OPEN)
]
closing = [
    Option.get_option(session, 'AVGO  250117P00151000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
    Option.get_option(session, 'AVGO  250117P00141000').build_leg(Decimal(1), OrderAction.SELL_TO_CLOSE)
]

otoco = NewComplexOrder(
    trigger_order=NewOrder(
        time_in_force=OrderTimeInForce.GTC,
        order_type=OrderType.LIMIT,
        legs=opening,
        price=Decimal('2.52'),
        price_effect=PriceEffect.CREDIT
    ),
    orders=[
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.LIMIT,
            legs=closing,
            price=Decimal('0.74'),  # take profits
            price_effect=PriceEffect.CREDIT
        ),
        NewOrder(
            time_in_force=OrderTimeInForce.GTC,
            order_type=OrderType.STOP,
            legs=closing,
            stop_trigger=Decimal('3.81'),  # stop loss
            price_effect=PriceEffect.DEBIT
        )
    ]
)

resp = account.place_complex_order(session, otoco, dry_run=True)
---------------------------------------------------------------------------
TastytradeError                           Traceback (most recent call last)
Cell In[2], line 1
----> 1 resp = account.place_complex_order(session, otoco, dry_run=True)

File ~/.local/lib/python3.9/site-packages/tastytrade/account.py:980, in Account.place_complex_order(self, session, order, dry_run)
    978     url += "/dry-run"
    979 json = order.model_dump_json(exclude_none=True, by_alias=True)
--> 980 data = session.post(url, data=json)
    981 return PlacedOrderResponse(**data)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:109, in Session.post(self, url, **kwargs)
    107 def post(self, url, **kwargs) -> Dict[str, Any]:
    108     response = self.client.post(url, **kwargs)
--> 109     return self._validate_and_parse(response)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:116, in Session._validate_and_parse(self, response)
    115 def _validate_and_parse(self, response: httpx._models.Response) -> Dict[str, Any]:
--> 116     validate_response(response)
    117     return response.json()["data"]

File ~/.local/lib/python3.9/site-packages/tastytrade/utils.py:228, in validate_response(response)
    225         else:
    226             error_message += f"\n{error['domain']}: {error['reason']}"
--> 228 raise TastytradeError(error_message)

TastytradeError: preflight_check_failure: One or more preflight checks failed
invalid_complex_structure: Complex order structure is invalid
invalid_triggered_order_price: Order price is invalid for this trade.

Screenshot 2024-11-15 at 11 41 00 AM

@Graeme22
Copy link
Contributor

In this case, the take profit that you see in the platform is a debit, not a credit. So you should be able to get this to go through by switching it to a debit. The price effects of both closing orders should always match and be the opposite of the opening order.

@salamad
Copy link
Author

salamad commented Nov 18, 2024

When I change both closing orders to debit, I get the following error:

TastytradeError                           Traceback (most recent call last)
Cell In[2], line 45
     14 closing = [
     15     Option.get_option(session, 'AVGO  250117P00151000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
     16     Option.get_option(session, 'AVGO  250117P00141000').build_leg(Decimal(1), OrderAction.SELL_TO_CLOSE)
     17 ]
     19 otoco = NewComplexOrder(
     20     trigger_order=NewOrder(
     21         time_in_force=OrderTimeInForce.GTC,
   (...)
     42     ]
     43 )
---> 45 resp = account.place_complex_order(session, otoco, dry_run=True)

File ~/.local/lib/python3.9/site-packages/tastytrade/account.py:980, in Account.place_complex_order(self, session, order, dry_run)
    978     url += "/dry-run"
    979 json = order.model_dump_json(exclude_none=True, by_alias=True)
--> 980 data = session.post(url, data=json)
    981 return PlacedOrderResponse(**data)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:109, in Session.post(self, url, **kwargs)
    107 def post(self, url, **kwargs) -> Dict[str, Any]:
    108     response = self.client.post(url, **kwargs)
--> 109     return self._validate_and_parse(response)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:116, in Session._validate_and_parse(self, response)
    115 def _validate_and_parse(self, response: httpx._models.Response) -> Dict[str, Any]:
--> 116     validate_response(response)
    117     return response.json()["data"]

File ~/.local/lib/python3.9/site-packages/tastytrade/utils.py:228, in validate_response(response)
    225         else:
    226             error_message += f"\n{error['domain']}: {error['reason']}"
--> 228 raise TastytradeError(error_message)

TastytradeError: preflight_check_failure: One or more preflight checks failed
invalid_complex_structure: Complex order structure is invalid

@Graeme22
Copy link
Contributor

Hmm, one more thing you can try. I think it may be invalid to pass a price effect at all for the stop loss order.

@salamad
Copy link
Author

salamad commented Nov 20, 2024

Hi. The example in your documentation does show a price effect in the stop loss order. Not sure if maybe TastyTrade's own API has changed the requirements.

Anyway, I tried removing the price effect from the stop loss order and got the following error:

---------------------------------------------------------------------------
TastytradeError                           Traceback (most recent call last)
Cell In[1], line 44
     14 closing = [
     15     Option.get_option(session, 'AVGO  250117P00151000').build_leg(Decimal(1), OrderAction.BUY_TO_CLOSE),
     16     Option.get_option(session, 'AVGO  250117P00141000').build_leg(Decimal(1), OrderAction.SELL_TO_CLOSE)
     17 ]
     19 otoco = NewComplexOrder(
     20     trigger_order=NewOrder(
     21         time_in_force=OrderTimeInForce.GTC,
   (...)
     41     ]
     42 )
---> 44 resp = account.place_complex_order(session, otoco, dry_run=True)

File ~/.local/lib/python3.9/site-packages/tastytrade/account.py:980, in Account.place_complex_order(self, session, order, dry_run)
    978     url += "/dry-run"
    979 json = order.model_dump_json(exclude_none=True, by_alias=True)
--> 980 data = session.post(url, data=json)
    981 return PlacedOrderResponse(**data)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:109, in Session.post(self, url, **kwargs)
    107 def post(self, url, **kwargs) -> Dict[str, Any]:
    108     response = self.client.post(url, **kwargs)
--> 109     return self._validate_and_parse(response)

File ~/.local/lib/python3.9/site-packages/tastytrade/session.py:116, in Session._validate_and_parse(self, response)
    115 def _validate_and_parse(self, response: httpx._models.Response) -> Dict[str, Any]:
--> 116     validate_response(response)
    117     return response.json()["data"]

File ~/.local/lib/python3.9/site-packages/tastytrade/utils.py:228, in validate_response(response)
    225         else:
    226             error_message += f"\n{error['domain']}: {error['reason']}"
--> 228 raise TastytradeError(error_message)

TastytradeError: preflight_check_failure: One or more preflight checks failed
invalid_complex_structure: Complex order structure is invalid
invalid_triggered_order_price: Order price is invalid for this trade.

@Graeme22
Copy link
Contributor

I took another look and it seems like in your code you switched the long and short legs, so it wasn't allowing you to place the opening trade for a credit when it should've been a debit.
Basically, just be careful with the details and make sure you understand how OTOCO orders work and you should be fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants