#cell 0
import math
import types
import numpy as np
import pandas as pd
from pyqstrat.pq_utils import ReasonCode
[docs]class MarketOrder:
[docs] def __init__(self, contract, timestamp, qty, reason_code = ReasonCode.NONE, properties = None, status = 'open'):
'''
Args:
contract (:obj:`Contract`):
timestamp (:obj:`np.datetime64`): Time the order was placed
qty (float): Number of contracts or shares. Use a negative quantity for sell orders
reason_code (str, optional): The reason this order was created.
Prefer a predefined constant from the ReasonCode class if it matches your reason for creating this order.
Default None
properties (:obj:`SimpleNamespace`, optional): Any order specific data we want to store. Default None
status (str, optional): Status of the order, "open", "filled", etc. (default "open")
'''
self.contract = contract
self.timestamp = timestamp
if not np.isfinite(qty) or math.isclose(qty, 0): raise Exception(f'order qty must be finite and nonzero: {qty}')
self.qty = qty
self.reason_code = reason_code
self.status = status
if properties is None: properties = types.SimpleNamespace()
self.properties = properties
def __repr__(self):
timestamp = pd.Timestamp(self.timestamp).to_pydatetime()
return f'{self.contract.symbol} {timestamp:%Y-%m-%d %H:%M:%S} qty: {self.qty}' + (
'' if self.reason_code == ReasonCode.NONE else f' {self.reason_code}') + (
'' if not self.properties.__dict__ else f' {self.properties}') + (
f' {self.status}')
[docs]class LimitOrder:
[docs] def __init__(self, contract, timestamp, qty, limit_price, reason_code = ReasonCode.NONE, properties = None, status = 'open'):
'''
Args:
contract (:obj:`Contract`):
timestamp (:obj:`np.datetime64`): Time the order was placed
qty (float): Number of contracts or shares. Use a negative quantity for sell orders
limit_price (float): Limit price (float)
reason_code (str, optional): The reason this order was created.
Prefer a predefined constant from the ReasonCode class if it matches your reason for creating this order.
Default None
properties (:obj:`SimpleNamespace`, optional): Any order specific data we want to store. Default None
status (str, optional): Status of the order, "open", "filled", etc. (default "open")
'''
self.contract = contract
self.timestamp = timestamp
if not np.isfinite(qty) or math.isclose(qty, 0): raise Exception(f'order qty must be finite and nonzero: {qty}')
self.qty = qty
self.reason_code = reason_code
self.limit_price = limit_price
if properties is None: properties = types.SimpleNamespace()
self.properties = properties
self.properties.limit_price = self.limit_price
self.status = status
def __repr__(self):
timestamp = pd.Timestamp(self.timestamp).to_pydatetime()
return f'{self.contract.symbol} {timestamp:%Y-%m-%d %H:%M:%S} qty: {self.qty} lmt_prc: {self.limit_price}' + (
'' if self.reason_code == ReasonCode.NONE else f' {self.reason_code}') + (
'' if not self.properties.__dict__ else f' {self.properties}') + (
f' {self.status}')
[docs]class RollOrder:
'''A roll order is used to roll a future from one series to the next. It represents a sell of one future and the buying of another future.'''
[docs] def __init__(self, contract, timestamp, close_qty, reopen_qty, reason_code = ReasonCode.ROLL_FUTURE, properties = None,
status = 'open'):
'''
Args:
contract (:obj:`Contract`):
timestamp (:obj:`np.datetime64`): Time the order was placed
close_qty (float): Quantity of the future you are rolling
reopen_qty (float): Quantity of the future you are rolling to
reason_code (str, optional): The reason this order was created.
Prefer a predefined constant from the ReasonCode class if it matches your reason for creating this order.
Default None
properties (:obj:`SimpleNamespace`, optional): Any order specific data we want to store. Default None
status (str, optional): Status of the order, "open", "filled", etc. (default "open")
'''
self.contract = contract
self.timestamp = timestamp
if not np.isfinite(close_qty) or math.isclose(close_qty, 0) or not np.isfinite(reopen_qty) or math.isclose(reopen_qty, 0):
raise Exception(f'order quantities must be non-zero and finite: {close_qty} {reopen_qty}')
self.close_qty = close_qty
self.reopen_qty = reopen_qty
self.reason_code = reason_code
self.qty = close_qty # For display purposes when we print varying order types
if properties is None: properties = types.SimpleNamespace()
self.properties = properties
self.properties.close_qty = self.close_qty
self.properties.reopen_qty = self.reopen_qty
self.status = status
def __repr__(self):
timestamp = pd.Timestamp(self.timestamp).to_pydatetime()
return f'{self.contract.symbol} {timestamp:%Y-%m-%d %H:%M:%S} close_qty: {self.close_qty} reopen_qty: {self.reopen_qty}' + (
'' if self.reason_code == ReasonCode.NONE else f' {self.reason_code}') + '' if not self.properties.__dict__ else f' {self.properties}' + (
f' {self.status}')
[docs]class StopLimitOrder:
'''Used for stop loss or stop limit orders. The order is triggered when price goes above or below trigger price, depending on whether this is a short
or long order. Becomes either a market or limit order at that point, depending on whether you set the limit price or not.
'''
[docs] def __init__(self, contract, timestamp, qty, trigger_price, limit_price = np.nan, reason_code = ReasonCode.NONE,
properties = None, status = 'open'):
'''
Args:
contract (:obj:`Contract`):
timestamp (:obj:`np.datetime64`): Time the order was placed
qty (float): Number of contracts or shares. Use a negative quantity for sell orders
trigger_price (float): Order becomes a market or limit order if price crosses trigger_price.
limit_price (float, optional): If not set (default), order becomes a market order when price crosses trigger price.
Otherwise it becomes a limit order. Default np.nan
reason_code (str, optional): The reason this order was created.
Prefer a predefined constant from the ReasonCode class if it matches your reason for creating this order.
Default None
properties (:obj:`SimpleNamespace`, optional): Any order specific data we want to store. Default None
status (str, optional): Status of the order, "open", "filled", etc. (default "open")
'''
self.contract = contract
self.timestamp = timestamp
if not np.isfinite(qty) or math.isclose(qty, 0): raise Exception(f'order qty must be finite and nonzero: {qty}')
self.qty = qty
self.trigger_price = trigger_price
self.limit_price = limit_price
self.reason_code = reason_code
self.triggered = False
if properties is None: properties = types.SimpleNamespace()
self.properties = properties
self.properties.trigger_price = trigger_price
self.properties.limit_price = limit_price
self.status = status
def __repr__(self):
timestamp = pd.Timestamp(self.timestamp).to_pydatetime()
return f'{self.contract.symbol} {timestamp:%Y-%m-%d %H:%M:%S} qty: {self.qty} trigger_prc: {self.trigger_price} limit_prc: {self.limit_price}' + (
'' if self.reason_code == ReasonCode.NONE else f' {self.reason_code}') + ('' if not self.properties.__dict__ else f' {self.properties}') + (
f' {self.status}')
if __name__ == "__main__":
import doctest
doctest.testmod(optionflags = doctest.NORMALIZE_WHITESPACE)