or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

account.mdcore.mdhelpers.mdindex.mdmarket-data.mdtrading.md
tile.json

helpers.mddocs/

Helpers

Request builders, type validation, definitions, and utilities.

Request Builders

Order Requests

class MarketOrderRequest:
    def __init__(
        self,
        instrument: str,
        units: int,  # Positive=buy, negative=sell
        priceBound: float = None,
        positionFill: str = "DEFAULT",
        clientExtensions: dict = None,
        takeProfitOnFill: dict = None,
        timeInForce: str = "FOK",
        stopLossOnFill: dict = None,
        trailingStopLossOnFill: dict = None,
        tradeClientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

class LimitOrderRequest:
    def __init__(
        self,
        instrument: str,
        units: int,
        price: float,
        positionFill: str = "DEFAULT",
        clientExtensions: dict = None,
        takeProfitOnFill: dict = None,
        timeInForce: str = "GTC",
        gtdTime: str = None,
        stopLossOnFill: dict = None,
        trailingStopLossOnFill: dict = None,
        tradeClientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

class StopOrderRequest:
    def __init__(
        self,
        instrument: str,
        units: int,
        price: float,
        priceBound: float = None,
        positionFill: str = "DEFAULT",
        timeInForce: str = "GTC",
        gtdTime: str = None,
        clientExtensions: dict = None,
        takeProfitOnFill: dict = None,
        stopLossOnFill: dict = None,
        trailingStopLossOnFill: dict = None,
        tradeClientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

class MITOrderRequest:
    """Market-If-Touched order."""
    def __init__(
        self,
        instrument: str,
        units: int,
        price: float,
        priceBound: float = None,
        positionFill: str = "DEFAULT",
        timeInForce: str = "GTC",
        gtdTime: str = None,
        clientExtensions: dict = None,
        takeProfitOnFill: dict = None,
        stopLossOnFill: dict = None,
        trailingStopLossOnFill: dict = None,
        tradeClientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

Exit Order Details

class TakeProfitDetails:
    def __init__(
        self,
        price: float,
        timeInForce: str = "GTC",
        gtdTime: str = None,
        clientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

class StopLossDetails:
    def __init__(
        self,
        price: float,
        timeInForce: str = "GTC",
        gtdTime: str = None,
        clientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

class TrailingStopLossDetails:
    def __init__(
        self,
        distance: float,  # Distance in price units
        timeInForce: str = "GTC",
        gtdTime: str = None,
        clientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

Close Requests

class TradeCloseRequest:
    def __init__(self, units: str = "ALL"): ...  # "ALL" or number

    @property
    def data(self) -> dict: ...

class PositionCloseRequest:
    def __init__(
        self,
        longUnits: str = None,  # "ALL" or number
        longClientExtensions: dict = None,
        shortUnits: str = None,
        shortClientExtensions: dict = None
    ): ...

    @property
    def data(self) -> dict: ...

Client Extensions

class ClientExtensions:
    def __init__(
        self,
        clientID: str = None,      # Max 128 chars
        clientTag: str = None,     # Max 128 chars
        clientComment: str = None  # Max 128 chars
    ): ...

    @property
    def data(self) -> dict: ...

Definitions

Order Constants

from oandapyV20.definitions.orders import (
    OrderType, TimeInForce, OrderPositionFill, OrderState, OrderTriggerCondition
)

# Order types
OrderType.MARKET
OrderType.LIMIT
OrderType.STOP
OrderType.MARKET_IF_TOUCHED
OrderType.TAKE_PROFIT
OrderType.STOP_LOSS
OrderType.TRAILING_STOP_LOSS

# Time in force
TimeInForce.GTC  # Good Till Cancelled
TimeInForce.GTD  # Good Till Date
TimeInForce.GFD  # Good For Day
TimeInForce.FOK  # Fill Or Kill
TimeInForce.IOC  # Immediate Or Cancel

# Position fill
OrderPositionFill.OPEN_ONLY
OrderPositionFill.REDUCE_FIRST
OrderPositionFill.REDUCE_ONLY
OrderPositionFill.DEFAULT

# Order states
OrderState.PENDING
OrderState.FILLED
OrderState.TRIGGERED
OrderState.CANCELLED

# Trigger conditions
OrderTriggerCondition.DEFAULT
OrderTriggerCondition.INVERSE
OrderTriggerCondition.BID
OrderTriggerCondition.ASK
OrderTriggerCondition.MID

Instrument Constants

from oandapyV20.definitions.instruments import CandlestickGranularity, PriceComponents

# Granularities: S5, S10, S15, S30, M1-M30, H1-H12, D, W, M
# (See market-data.md for full list)

# Price components
PriceComponents.M  # Mid
PriceComponents.B  # Bid
PriceComponents.A  # Ask

Trade/Account Constants

from oandapyV20.definitions.trades import TradeState, TradePL
from oandapyV20.definitions.primitives import InstrumentType, Direction

# Trade states
TradeState.OPEN
TradeState.CLOSED
TradeState.CLOSE_WHEN_TRADABLE

# Trade P/L
TradePL.POSITIVE
TradePL.NEGATIVE
TradePL.ZERO

# Instrument types
InstrumentType.CURRENCY
InstrumentType.CFD
InstrumentType.METAL

# Direction
Direction.LONG
Direction.SHORT

Type Validation

class AccountID:
    def __init__(self, accountID: str): ...
    @property
    def value(self) -> str: ...

class DateTime:
    def __init__(self, dateTime): ...  # datetime obj or RFC3339 string
    @property
    def value(self) -> str: ...  # RFC3339 format

class Units:
    def __init__(self, units): ...  # int or float (max 2 decimals)
    @property
    def value(self) -> str: ...

class PriceValue:
    def __init__(self, priceValue): ...  # int or float
    @property
    def value(self) -> str: ...  # Formatted to 5 decimals

class AccountUnits:
    def __init__(self, units): ...  # int or float
    @property
    def value(self) -> str: ...  # Formatted to 5 decimals

class OrderID:
    def __init__(self, orderID): ...  # int or str
    @property
    def value(self) -> str: ...

class TradeID:
    def __init__(self, tradeID): ...  # int or str
    @property
    def value(self) -> str: ...

class ClientID:
    def __init__(self, clientID: str): ...  # Max 128 chars
    @property
    def value(self) -> str: ...

class ClientTag:
    def __init__(self, clientTag: str): ...  # Max 128 chars
    @property
    def value(self) -> str: ...

class ClientComment:
    def __init__(self, clientComment: str): ...  # Max 128 chars
    @property
    def value(self) -> str: ...

Usage

from oandapyV20.types import AccountID, DateTime, Units, PriceValue
from datetime import datetime

# Validate account ID
account = AccountID("123-456-7890123-001")
print(account.value)

# Format datetime
dt = DateTime(datetime.utcnow())
print(dt.value)  # RFC3339 format

# Format price
price = PriceValue(1.1)
print(price.value)  # "1.10000"

# Format units
units = Units(1000)
print(units.value)  # "1000"

Utilities

from oandapyV20.contrib.generic import secs2time, granularity_to_time
from oandapyV20.contrib.factories import InstrumentsCandlesFactory

# Convert epoch to datetime
dt = secs2time(1609459200)

# Convert granularity to seconds
seconds = granularity_to_time("H1")  # 3600
seconds = granularity_to_time("M5")  # 300
seconds = granularity_to_time("D")   # 86400

# Large historical data (auto-pagination for >5000 candles)
params = {
    "from": "2023-01-01T00:00:00Z",
    "to": "2023-12-31T23:59:59Z",
    "granularity": "H1"
}
all_candles = []
for endpoint in InstrumentsCandlesFactory("EUR_USD", params):
    all_candles.extend(api.request(endpoint)['candles'])

Common Patterns

Complete Order with All Options

from oandapyV20.contrib.requests import (
    LimitOrderRequest, TakeProfitDetails, StopLossDetails, ClientExtensions
)
from oandapyV20.definitions.orders import TimeInForce, OrderPositionFill

extensions = ClientExtensions(
    clientID="trade-001",
    clientTag="strategy-A",
    clientComment="Entry signal"
).data

order = LimitOrderRequest(
    instrument="EUR_USD",
    units=10000,
    price=1.1000,
    timeInForce=TimeInForce.GTC,
    positionFill=OrderPositionFill.DEFAULT,
    clientExtensions=extensions,
    takeProfitOnFill=TakeProfitDetails(price=1.1200).data,
    stopLossOnFill=StopLossDetails(price=1.0900).data
).data

GTD Order (Good Till Date)

from datetime import datetime, timedelta

expiry = datetime.utcnow() + timedelta(days=1)
gtd_time = expiry.strftime("%Y-%m-%dT%H:%M:%S.%fZ")

order = LimitOrderRequest(
    instrument="EUR_USD",
    units=1000,
    price=1.1000,
    timeInForce="GTD",
    gtdTime=gtd_time
).data

Validation Helper

from oandapyV20.types import AccountID, PriceValue, Units

def validate_order_inputs(account_id, price, units):
    """Validate and format order inputs."""
    return {
        'account_id': AccountID(account_id).value,
        'price': PriceValue(price).value,
        'units': Units(units).value
    }

validated = validate_order_inputs("123-456-7890123-001", 1.1, 1000)