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

Add Place Order models and validation #98

Merged
merged 34 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7e19060
Add vs code folder to .gitignore
ChocoShell May 24, 2020
caa61b3
Add list of all enums used by order api
ChocoShell May 24, 2020
0193fb6
Add orders submodule
ChocoShell May 24, 2020
576c88d
Add Instrument classes for Orders API
ChocoShell May 24, 2020
08120db
Add Activity classes for Orders API
ChocoShell May 24, 2020
9e2d5b2
Switch to Base class for Orders
ChocoShell May 24, 2020
3bff83e
Add WIP orders builder
ChocoShell May 24, 2020
031c4c9
Change BaseOrder class into a dataclass
ChocoShell May 25, 2020
084f0ff
Remove Enum subclass to allow JSON serialization
ChocoShell May 25, 2020
8461895
Change order subclasses into dataclasses
ChocoShell May 25, 2020
ef3e697
Format orders builder
ChocoShell May 25, 2020
004a27e
Make user facing dataclasses frozen
ChocoShell May 25, 2020
6318d77
Add link to dataclass documentation
ChocoShell May 25, 2020
6fd6093
Fix base enum class for orders
ChocoShell May 25, 2020
dc33c7a
Add tests for orders submodule
ChocoShell May 25, 2020
96df02d
Add Equity Order function
ChocoShell May 31, 2020
9407173
Make Dataclasses JSON serializable
ChocoShell Jun 13, 2020
44c7c90
Add tests for orders submodule
ChocoShell Jun 13, 2020
cfd7ddc
typo fix
ChocoShell Jun 13, 2020
8479b5e
format
ChocoShell Jun 13, 2020
e3b1f00
Add asdict method to dataclasses
ChocoShell Jun 16, 2020
cbbf96b
Add create option order leg and make leg parameters all optional
ChocoShell Jun 16, 2020
2484cb2
Expand order sample functions
ChocoShell Jun 16, 2020
e29ec01
Update test for order sample functions
ChocoShell Jun 16, 2020
2ffca5b
Format orders submodule
ChocoShell Jun 16, 2020
8b3cf3d
Move dataclasses to models subfolder
ChocoShell Jun 16, 2020
0e145d6
Move tests to subfolder
ChocoShell Jun 16, 2020
1d72cbe
Move order builder tests
ChocoShell Jun 16, 2020
99e1a29
Move tests
ChocoShell Jun 16, 2020
12d3851
Validation
ChocoShell Jun 16, 2020
006c098
Handle typing lib issue
ChocoShell Jun 16, 2020
acd2549
format orders submodule
ChocoShell Jun 16, 2020
4eae3bc
Update orders doc
ChocoShell Jun 16, 2020
6ab4d6d
isort
ChocoShell Jun 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ ENV/
# Rope project settings
.ropeproject

# VS Code project settings
.vscode

# mkdocs documentation
/site

Expand Down
14 changes: 14 additions & 0 deletions tdameritrade/orders/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Orders Submodule

This module is used to construct valid json for the place orders endpoint.
https://developer.tdameritrade.com/account-access/apis/post/accounts/%7BaccountId%7D/orders-0

The validation is done by the orders.models.base.BaseOrder class

The order_builder file incudes sample order builder functions created from
https://developer.tdameritrade.com/content/place-order-samples
"""

from . import order_builder

__all__ = ["order_builder"]
258 changes: 258 additions & 0 deletions tdameritrade/orders/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
"""Constants used in Orders
"""
from enum import Enum


class ExtendedConstant(str, Enum):
"""
Base Enum class used by all order Enums.
"""

@classmethod
def list(cls):
"""Lists all values in Enum

Found here: https://stackoverflow.com/questions/29503339/how-to-get-all-values-from-python-enum-class/54919285#54919285
"""
return list(map(lambda c: c.value, cls))


class Session(ExtendedConstant):
NORMAL = "NORMAL"
AM = "AM"
PM = "PM"
SEAMLESS = "SEAMLESS"


class Duration(ExtendedConstant):
DAY = "DAY"
GOOD_TILL_CANCEL = "GOOD_TILL_CANCEL"
FILL_OR_KILL = "FILL_OR_KILL"


class OrderType(ExtendedConstant):
MARKET = "MARKET"
LIMIT = "LIMIT"
STOP = "STOP"
STOP_LIMIT = "STOP_LIMIT"
TRAILING_STOP = "TRAILING_STOP"
MARKET_ON_CLOSE = "MARKET_ON_CLOSE"
EXERCISE = "EXERCISE"
TRAILING_STOP_LIMIT = "TRAILING_STOP_LIMIT"
NET_DEBIT = "NET_DEBIT"
NET_CREDIT = "NET_CREDIT"
NET_ZERO = "NET_ZERO"


class ComplexOrderStrategyType(ExtendedConstant):
NONE = "NONE"
COVERED = "COVERED"
VERTICAL = "VERTICAL"
BACK_RATIO = "BACK_RATIO"
CALENDAR = "CALENDAR"
DIAGONAL = "DIAGONAL"
STRADDLE = "STRADDLE"
STRANGLE = "STRANGLE"
COLLAR_SYNTHETIC = "COLLAR_SYNTHETIC"
BUTTERFLY = "BUTTERFLY"
CONDOR = "CONDOR"
IRON_CONDOR = "IRON_CONDOR"
VERTICAL_ROLL = "VERTICAL_ROLL"
COLLAR_WITH_STOCK = "COLLAR_WITH_STOCK"
DOUBLE_DIAGONAL = "DOUBLE_DIAGONAL"
UNBALANCED_BUTTERFLY = "UNBALANCED_BUTTERFLY"
UNBALANCED_CONDOR = "UNBALANCED_CONDOR"
UNBALANCED_IRON_CONDOR = "UNBALANCED_IRON_CONDOR"
UNBALANCED_VERTICAL_ROLL = "UNBALANCED_VERTICAL_ROLL"
CUSTOM = "CUSTOM"


class RequestedDestination(ExtendedConstant):
INET = "INET"
ECN_ARCA = "ECN_ARCA"
CBOE = "CBOE"
AMEX = "AMEX"
PHLX = "PHLX"
ISE = "ISE"
BOX = "BOX"
NYSE = "NYSE"
NASDAQ = "NASDAQ"
BATS = "BATS"
C2 = "C2"
AUTO = "AUTO"


class StopPriceLinkBasis(ExtendedConstant):
MANUAL = "MANUAL"
BASE = "BASE"
TRIGGER = "TRIGGER"
LAST = "LAST"
BID = "BID"
ASK = "ASK"
ASK_BID = "ASK_BID"
MARK = "MARK"
AVERAGE = "AVERAGE"


class StopPriceLinkType(ExtendedConstant):
VALUE = "VALUE"
PERCENT = "PERCENT"
TICK = "TICK"


class StopType(ExtendedConstant):
STANDARD = "STANDARD"
BID = "BID"
ASK = "ASK"
LAST = "LAST"
MARK = "MARK"


class PriceLinkBasis(ExtendedConstant):
MANUAL = "MANUAL"
BASE = "BASE"
TRIGGER = "TRIGGER"
LAST = "LAST"
BID = "BID"
ASK = "ASK"
ASK_BID = "ASK_BID"
MARK = "MARK"
AVERAGE = "AVERAGE"


class PriceLinkType(ExtendedConstant):
VALUE = "VALUE"
PERCENT = "PERCENT"
TICK = "TICK"


class TaxLotMethod(ExtendedConstant):
FIFO = "FIFO"
LIFO = "LIFO"
HIGH_COST = "HIGH_COST"
LOW_COST = "LOW_COST"
AVERAGE_COST = "AVERAGE_COST"
SPECIFIC_LOT = "SPECIFIC_LOT"


class SpecialInstruction(ExtendedConstant):
ALL_OR_NONE = "ALL_OR_NONE"
DO_NOT_REDUCE = "DO_NOT_REDUCE"
ALL_OR_NONE_DO_NOT_REDUCE = "ALL_OR_NONE_DO_NOT_REDUCE"


class OrderStrategyType(ExtendedConstant):
SINGLE = "SINGLE"
OCO = "OCO"
TRIGGER = "TRIGGER"


class Status(ExtendedConstant):
AWAITING_PARENT_ORDER = "AWAITING_PARENT_ORDER"
AWAITING_CONDITION = "AWAITING_CONDITION"
AWAITING_MANUAL_REVIEW = "AWAITING_MANUAL_REVIEW"
ACCEPTED = "ACCEPTED"
AWAITING_UR_OUT = "AWAITING_UR_OUT"
PENDING_ACTIVATION = "PENDING_ACTIVATION"
QUEUED = "QUEUED"
WORKING = "WORKING"
REJECTED = "REJECTED"
PENDING_CANCEL = "PENDING_CANCEL"
CANCELED = "CANCELED"
PENDING_REPLACE = "PENDING_REPLACE"
REPLACED = "REPLACED"
FILLED = "FILLED"
EXPIRED = "EXPIRED"


# Order Leg Constants


class OrderLegType(ExtendedConstant):
EQUITY = "EQUITY"
OPTION = "OPTION"
INDEX = "INDEX"
MUTUAL_FUND = "MUTUAL_FUND"
CASH_EQUIVALENT = "CASH_EQUIVALENT"
FIXED_INCOME = "FIXED_INCOME"
CURRENCY = "CURRENCY"


class Instruction(ExtendedConstant):
BUY = "BUY"
SELL = "SELL"
BUY_TO_COVER = "BUY_TO_COVER"
SELL_SHORT = "SELL_SHORT"
BUY_TO_OPEN = "BUY_TO_OPEN"
BUY_TO_CLOSE = "BUY_TO_CLOSE"
SELL_TO_OPEN = "SELL_TO_OPEN"
SELL_TO_CLOSE = "SELL_TO_CLOSE"
EXCHANGE = "EXCHANGE"


class PositionEffect(ExtendedConstant):
OPENING = "OPENING"
CLOSING = "CLOSING"
AUTOMATIC = "AUTOMATIC"


class QuantityType(ExtendedConstant):
ALL_SHARES = "ALL_SHARES"
DOLLARS = "DOLLARS"
SHARES = "SHARES"


# Activity Enums


class ActivityType(ExtendedConstant):
EXECUTION = "EXECUTION"
ORDER_ACTION = "ORDER_ACTION"


class ExecutionType(ExtendedConstant):
FILL = "FILL"


# Instrument Enums


class InstrumentAssetType(ExtendedConstant):
EQUITY = "EQUITY"
OPTION = "OPTION"
INDEX = "INDEX"
MUTUAL_FUND = "MUTUAL_FUND"
CASH_EQUIVALENT = "CASH_EQUIVALENT"
FIXED_INCOME = "FIXED_INCOME"
CURRENCY = "CURRENCY"


class MutualFundType(ExtendedConstant):
NOT_APPLICABLE = "NOT_APPLICABLE"
OPEN_END_NON_TAXABLE = "OPEN_END_NON_TAXABLE"
OPEN_END_TAXABLE = "OPEN_END_TAXABLE"
NO_LOAD_NON_TAXABLE = "NO_LOAD_NON_TAXABLE"
NO_LOAD_TAXABLE = "NO_LOAD_TAXABLE"


class CashEquivalentType(ExtendedConstant):
SAVINGS = "SAVINGS"
MONEY_MARKET_FUND = "MONEY_MARKET_FUND"


class OptionType(ExtendedConstant):
VANILLA = "VANILLA"
BINARY = "BINARY"
BARRIER = "BARRIER"


class OptionPutCall(ExtendedConstant):
PUT = "PUT"
CALL = "CALL"


class OptionDeliverableCurrencyType(ExtendedConstant):
USD = "USD"
CAD = "CAD"
EUR = "EUR"
JPY = "JPY"
48 changes: 48 additions & 0 deletions tdameritrade/orders/leg_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from .constants import Instruction, InstrumentAssetType
from .models.instruments import EquityInstrument, OptionInstrument
from .models.leg import OrderLeg


def create_equity_order_leg(
instruction, quantity, symbol, description=None, cusip=None, **order_leg_kwargs,
):
"""Creates OrderLeg for equity orders
"""
valid_instructions = [
Instruction("BUY"),
Instruction("SELL"),
Instruction("BUY_TO_COVER"),
Instruction("SELL_SHORT"),
]

asset_type = InstrumentAssetType.EQUITY

if instruction not in valid_instructions:
raise Exception(
f"{instruction} not in valid instruction list for Equity Order Leg"
)

instrument = EquityInstrument(symbol=symbol, assetType=asset_type)
return OrderLeg(
instruction=instruction,
quantity=quantity,
instrument=instrument,
**order_leg_kwargs,
)


def create_option_order_leg(
instruction, quantity, symbol, description=None, cusip=None, **order_leg_kwargs,
):
"""Creates Option OrderLeg
"""
asset_type = InstrumentAssetType.OPTION

instrument = OptionInstrument(symbol=symbol, assetType=asset_type)

return OrderLeg(
instruction=instruction,
quantity=quantity,
instrument=instrument,
**order_leg_kwargs,
)
8 changes: 8 additions & 0 deletions tdameritrade/orders/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from . import activities, instruments, leg, orders

__all__ = [
"activities",
"instruments",
"leg",
"orders",
]
34 changes: 34 additions & 0 deletions tdameritrade/orders/models/activities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from dataclasses import dataclass
from typing import List

from ..constants import ActivityType, ExecutionType
from .base import BaseOrder


@dataclass
class OrderActivity(BaseOrder):
pass


@dataclass(frozen=True)
class ExecutionLeg(BaseOrder):
"""ExecutionLeg used in Execution
"""

legId: int = None
quantity: int = None
mismarkedQuantity: int = None
price: int = None
time: str = None


@dataclass(frozen=True)
class Execution(OrderActivity):
"""Execution
"""

activityType: ActivityType = None
executionType: ExecutionType = None
quantity: int = None
orderRemainingQuantity: int = None
executionLegs: List = None # List[ExecutionLeg]. Issue with List[type] formatting
Loading