architect-py 5.1.4rc1__py3-none-any.whl → 5.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- architect_py/__init__.py +24 -4
- architect_py/async_client.py +121 -67
- architect_py/client.pyi +16 -37
- architect_py/grpc/models/Accounts/ResetPaperAccountRequest.py +59 -0
- architect_py/grpc/models/Accounts/ResetPaperAccountResponse.py +20 -0
- architect_py/grpc/models/Boss/OptionsTransactionsRequest.py +42 -0
- architect_py/grpc/models/Boss/OptionsTransactionsResponse.py +27 -0
- architect_py/grpc/models/Core/ConfigResponse.py +7 -2
- architect_py/grpc/models/Folio/AccountSummary.py +7 -1
- architect_py/grpc/models/Marketdata/Candle.py +6 -0
- architect_py/grpc/models/Marketdata/L1BookSnapshot.py +6 -0
- architect_py/grpc/models/Marketdata/L2BookSnapshot.py +6 -0
- architect_py/grpc/models/Marketdata/Liquidation.py +6 -0
- architect_py/grpc/models/Marketdata/Ticker.py +6 -0
- architect_py/grpc/models/Marketdata/Trade.py +6 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsChain.py +5 -5
- architect_py/grpc/models/OptionsMarketdata/OptionsChainGreeks.py +5 -5
- architect_py/grpc/models/OptionsMarketdata/OptionsChainGreeksRequest.py +5 -1
- architect_py/grpc/models/OptionsMarketdata/OptionsChainRequest.py +5 -1
- architect_py/grpc/models/OptionsMarketdata/OptionsContract.py +45 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsContractGreeksRequest.py +40 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsContractRequest.py +40 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsExpirations.py +4 -1
- architect_py/grpc/models/OptionsMarketdata/OptionsExpirationsRequest.py +8 -1
- architect_py/grpc/models/OptionsMarketdata/OptionsGreeks.py +58 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsWraps.py +28 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsWrapsRequest.py +40 -0
- architect_py/grpc/models/__init__.py +11 -1
- architect_py/grpc/models/definitions.py +57 -86
- architect_py/grpc/orderflow.py +3 -7
- architect_py/grpc/server.py +1 -3
- architect_py/tests/test_order_entry.py +120 -1
- architect_py/tests/test_positions.py +364 -0
- architect_py/tests/test_rounding.py +28 -28
- architect_py/utils/pandas.py +50 -1
- {architect_py-5.1.4rc1.dist-info → architect_py-5.1.6.dist-info}/METADATA +1 -1
- {architect_py-5.1.4rc1.dist-info → architect_py-5.1.6.dist-info}/RECORD +49 -38
- examples/external_cpty.py +2 -1
- examples/funding_rate_mean_reversion_algo.py +4 -4
- examples/order_sending.py +3 -3
- examples/orderflow_channel.py +75 -56
- examples/stream_l1_marketdata.py +3 -1
- examples/stream_l2_marketdata.py +3 -1
- examples/tutorial_async.py +3 -2
- examples/tutorial_sync.py +4 -3
- scripts/generate_functions_md.py +2 -1
- {architect_py-5.1.4rc1.dist-info → architect_py-5.1.6.dist-info}/WHEEL +0 -0
- {architect_py-5.1.4rc1.dist-info → architect_py-5.1.6.dist-info}/licenses/LICENSE +0 -0
- {architect_py-5.1.4rc1.dist-info → architect_py-5.1.6.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,7 @@ from msgspec import Struct
|
|
12
12
|
class OptionsExpirations(Struct, omit_defaults=True):
|
13
13
|
expirations: List[date]
|
14
14
|
underlying: str
|
15
|
+
wrap: str
|
15
16
|
|
16
17
|
# Constructor that takes all field titles as arguments for convenience
|
17
18
|
@classmethod
|
@@ -19,11 +20,13 @@ class OptionsExpirations(Struct, omit_defaults=True):
|
|
19
20
|
cls,
|
20
21
|
expirations: List[date],
|
21
22
|
underlying: str,
|
23
|
+
wrap: str,
|
22
24
|
):
|
23
25
|
return cls(
|
24
26
|
expirations,
|
25
27
|
underlying,
|
28
|
+
wrap,
|
26
29
|
)
|
27
30
|
|
28
31
|
def __str__(self) -> str:
|
29
|
-
return f"OptionsExpirations(expirations={self.expirations},underlying={self.underlying})"
|
32
|
+
return f"OptionsExpirations(expirations={self.expirations},underlying={self.underlying},wrap={self.wrap})"
|
@@ -6,24 +6,31 @@ from architect_py.grpc.models.OptionsMarketdata.OptionsExpirations import (
|
|
6
6
|
OptionsExpirations,
|
7
7
|
)
|
8
8
|
|
9
|
+
from typing import Optional
|
10
|
+
|
9
11
|
from msgspec import Struct
|
10
12
|
|
11
13
|
|
12
14
|
class OptionsExpirationsRequest(Struct, omit_defaults=True):
|
13
15
|
underlying: str
|
16
|
+
wrap: Optional[str] = None
|
14
17
|
|
15
18
|
# Constructor that takes all field titles as arguments for convenience
|
16
19
|
@classmethod
|
17
20
|
def new(
|
18
21
|
cls,
|
19
22
|
underlying: str,
|
23
|
+
wrap: Optional[str] = None,
|
20
24
|
):
|
21
25
|
return cls(
|
22
26
|
underlying,
|
27
|
+
wrap,
|
23
28
|
)
|
24
29
|
|
25
30
|
def __str__(self) -> str:
|
26
|
-
return
|
31
|
+
return (
|
32
|
+
f"OptionsExpirationsRequest(underlying={self.underlying},wrap={self.wrap})"
|
33
|
+
)
|
27
34
|
|
28
35
|
@staticmethod
|
29
36
|
def get_response_type():
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# generated by datamodel-codegen:
|
2
|
+
# filename: OptionsMarketdata/OptionsGreeks.json
|
3
|
+
|
4
|
+
from __future__ import annotations
|
5
|
+
|
6
|
+
from datetime import date
|
7
|
+
from decimal import Decimal
|
8
|
+
|
9
|
+
from msgspec import Struct
|
10
|
+
|
11
|
+
from .. import definitions
|
12
|
+
|
13
|
+
|
14
|
+
class OptionsGreeks(Struct, omit_defaults=True):
|
15
|
+
delta: Decimal
|
16
|
+
expiration: date
|
17
|
+
gamma: Decimal
|
18
|
+
implied_volatility: Decimal
|
19
|
+
put_or_call: definitions.PutOrCall
|
20
|
+
rho: Decimal
|
21
|
+
strike: Decimal
|
22
|
+
symbol: str
|
23
|
+
theta: Decimal
|
24
|
+
underlying: str
|
25
|
+
vega: Decimal
|
26
|
+
|
27
|
+
# Constructor that takes all field titles as arguments for convenience
|
28
|
+
@classmethod
|
29
|
+
def new(
|
30
|
+
cls,
|
31
|
+
delta: Decimal,
|
32
|
+
expiration: date,
|
33
|
+
gamma: Decimal,
|
34
|
+
implied_volatility: Decimal,
|
35
|
+
put_or_call: definitions.PutOrCall,
|
36
|
+
rho: Decimal,
|
37
|
+
strike: Decimal,
|
38
|
+
symbol: str,
|
39
|
+
theta: Decimal,
|
40
|
+
underlying: str,
|
41
|
+
vega: Decimal,
|
42
|
+
):
|
43
|
+
return cls(
|
44
|
+
delta,
|
45
|
+
expiration,
|
46
|
+
gamma,
|
47
|
+
implied_volatility,
|
48
|
+
put_or_call,
|
49
|
+
rho,
|
50
|
+
strike,
|
51
|
+
symbol,
|
52
|
+
theta,
|
53
|
+
underlying,
|
54
|
+
vega,
|
55
|
+
)
|
56
|
+
|
57
|
+
def __str__(self) -> str:
|
58
|
+
return f"OptionsGreeks(delta={self.delta},expiration={self.expiration},gamma={self.gamma},implied_volatility={self.implied_volatility},put_or_call={self.put_or_call},rho={self.rho},strike={self.strike},symbol={self.symbol},theta={self.theta},underlying={self.underlying},vega={self.vega})"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# generated by datamodel-codegen:
|
2
|
+
# filename: OptionsMarketdata/OptionsWraps.json
|
3
|
+
|
4
|
+
from __future__ import annotations
|
5
|
+
|
6
|
+
from typing import List
|
7
|
+
|
8
|
+
from msgspec import Struct
|
9
|
+
|
10
|
+
|
11
|
+
class OptionsWraps(Struct, omit_defaults=True):
|
12
|
+
underlying: str
|
13
|
+
wraps: List[str]
|
14
|
+
|
15
|
+
# Constructor that takes all field titles as arguments for convenience
|
16
|
+
@classmethod
|
17
|
+
def new(
|
18
|
+
cls,
|
19
|
+
underlying: str,
|
20
|
+
wraps: List[str],
|
21
|
+
):
|
22
|
+
return cls(
|
23
|
+
underlying,
|
24
|
+
wraps,
|
25
|
+
)
|
26
|
+
|
27
|
+
def __str__(self) -> str:
|
28
|
+
return f"OptionsWraps(underlying={self.underlying},wraps={self.wraps})"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# generated by datamodel-codegen:
|
2
|
+
# filename: OptionsMarketdata/OptionsWrapsRequest.json
|
3
|
+
|
4
|
+
from __future__ import annotations
|
5
|
+
from architect_py.grpc.models.OptionsMarketdata.OptionsWraps import OptionsWraps
|
6
|
+
|
7
|
+
from msgspec import Struct
|
8
|
+
|
9
|
+
|
10
|
+
class OptionsWrapsRequest(Struct, omit_defaults=True):
|
11
|
+
underlying: str
|
12
|
+
|
13
|
+
# Constructor that takes all field titles as arguments for convenience
|
14
|
+
@classmethod
|
15
|
+
def new(
|
16
|
+
cls,
|
17
|
+
underlying: str,
|
18
|
+
):
|
19
|
+
return cls(
|
20
|
+
underlying,
|
21
|
+
)
|
22
|
+
|
23
|
+
def __str__(self) -> str:
|
24
|
+
return f"OptionsWrapsRequest(underlying={self.underlying})"
|
25
|
+
|
26
|
+
@staticmethod
|
27
|
+
def get_response_type():
|
28
|
+
return OptionsWraps
|
29
|
+
|
30
|
+
@staticmethod
|
31
|
+
def get_unannotated_response_type():
|
32
|
+
return OptionsWraps
|
33
|
+
|
34
|
+
@staticmethod
|
35
|
+
def get_route() -> str:
|
36
|
+
return "/json.architect.OptionsMarketdata/OptionsWraps"
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def get_rpc_method():
|
40
|
+
return "unary"
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from .Accounts.AccountsRequest import AccountsRequest
|
2
2
|
from .Accounts.AccountsResponse import AccountsResponse
|
3
|
+
from .Accounts.ResetPaperAccountRequest import ResetPaperAccountRequest
|
4
|
+
from .Accounts.ResetPaperAccountResponse import ResetPaperAccountResponse
|
3
5
|
from .Algo.AlgoOrder import AlgoOrder
|
4
6
|
from .Algo.AlgoOrderRequest import AlgoOrderRequest
|
5
7
|
from .Algo.AlgoOrdersRequest import AlgoOrdersRequest
|
@@ -18,6 +20,8 @@ from .Auth.CreateJwtRequest import CreateJwtRequest
|
|
18
20
|
from .Auth.CreateJwtResponse import CreateJwtResponse
|
19
21
|
from .Boss.DepositsRequest import DepositsRequest
|
20
22
|
from .Boss.DepositsResponse import DepositsResponse
|
23
|
+
from .Boss.OptionsTransactionsRequest import OptionsTransactionsRequest
|
24
|
+
from .Boss.OptionsTransactionsResponse import OptionsTransactionsResponse
|
21
25
|
from .Boss.RqdAccountStatisticsRequest import RqdAccountStatisticsRequest
|
22
26
|
from .Boss.RqdAccountStatisticsResponse import RqdAccountStatisticsResponse
|
23
27
|
from .Boss.StatementUrlRequest import StatementUrlRequest
|
@@ -89,8 +93,14 @@ from .OptionsMarketdata.OptionsChain import OptionsChain
|
|
89
93
|
from .OptionsMarketdata.OptionsChainGreeks import OptionsChainGreeks
|
90
94
|
from .OptionsMarketdata.OptionsChainGreeksRequest import OptionsChainGreeksRequest
|
91
95
|
from .OptionsMarketdata.OptionsChainRequest import OptionsChainRequest
|
96
|
+
from .OptionsMarketdata.OptionsContract import OptionsContract
|
97
|
+
from .OptionsMarketdata.OptionsContractGreeksRequest import OptionsContractGreeksRequest
|
98
|
+
from .OptionsMarketdata.OptionsContractRequest import OptionsContractRequest
|
92
99
|
from .OptionsMarketdata.OptionsExpirations import OptionsExpirations
|
93
100
|
from .OptionsMarketdata.OptionsExpirationsRequest import OptionsExpirationsRequest
|
101
|
+
from .OptionsMarketdata.OptionsGreeks import OptionsGreeks
|
102
|
+
from .OptionsMarketdata.OptionsWraps import OptionsWraps
|
103
|
+
from .OptionsMarketdata.OptionsWrapsRequest import OptionsWrapsRequest
|
94
104
|
from .Orderflow.Dropcopy import Dropcopy
|
95
105
|
from .Orderflow.DropcopyRequest import DropcopyRequest
|
96
106
|
from .Orderflow.Orderflow import Orderflow
|
@@ -113,4 +123,4 @@ from .Symbology.UploadProductCatalogResponse import UploadProductCatalogResponse
|
|
113
123
|
from .Symbology.UploadSymbologyRequest import UploadSymbologyRequest
|
114
124
|
from .Symbology.UploadSymbologyResponse import UploadSymbologyResponse
|
115
125
|
|
116
|
-
__all__ = ["AccountsRequest", "AccountsResponse", "AlgoOrder", "AlgoOrderRequest", "AlgoOrdersRequest", "AlgoOrdersResponse", "CreateAlgoOrderRequest", "PauseAlgoRequest", "PauseAlgoResponse", "StartAlgoRequest", "StartAlgoResponse", "StopAlgoRequest", "StopAlgoResponse", "AlgoParamTypes", "AuthInfoRequest", "AuthInfoResponse", "CreateJwtRequest", "CreateJwtResponse", "DepositsRequest", "DepositsResponse", "RqdAccountStatisticsRequest", "RqdAccountStatisticsResponse", "StatementUrlRequest", "StatementUrlResponse", "StatementsRequest", "StatementsResponse", "WithdrawalsRequest", "WithdrawalsResponse", "ConfigRequest", "ConfigResponse", "RestartCptyRequest", "RestartCptyResponse", "CptyRequest", "CptyResponse", "CptyStatus", "CptyStatusRequest", "CptysRequest", "CptysResponse", "AccountHistoryRequest", "AccountHistoryResponse", "AccountSummariesRequest", "AccountSummariesResponse", "AccountSummary", "AccountSummaryRequest", "HistoricalFillsRequest", "HistoricalFillsResponse", "HistoricalOrdersRequest", "HistoricalOrdersResponse", "HealthCheckRequest", "HealthCheckResponse", "ArrayOfL1BookSnapshot", "Candle", "HistoricalCandlesRequest", "HistoricalCandlesResponse", "L1BookSnapshot", "L1BookSnapshotRequest", "L1BookSnapshotsRequest", "L2BookSnapshot", "L2BookSnapshotRequest", "L2BookUpdate", "Liquidation", "MarketStatus", "MarketStatusRequest", "SubscribeCandlesRequest", "SubscribeCurrentCandlesRequest", "SubscribeL1BookSnapshotsRequest", "SubscribeL2BookUpdatesRequest", "SubscribeLiquidationsRequest", "SubscribeManyCandlesRequest", "SubscribeTickersRequest", "SubscribeTradesRequest", "Ticker", "TickerRequest", "TickerUpdate", "TickersRequest", "TickersResponse", "Trade", "Cancel", "CancelAllOrdersRequest", "CancelAllOrdersResponse", "CancelOrderRequest", "OpenOrdersRequest", "OpenOrdersResponse", "Order", "PendingCancelsRequest", "PendingCancelsResponse", "PlaceOrderRequest", "OptionsChain", "OptionsChainGreeks", "OptionsChainGreeksRequest", "OptionsChainRequest", "OptionsExpirations", "OptionsExpirationsRequest", "Dropcopy", "DropcopyRequest", "Orderflow", "OrderflowRequest", "SubscribeOrderflowRequest", "DownloadProductCatalogRequest", "DownloadProductCatalogResponse", "ExecutionInfoRequest", "ExecutionInfoResponse", "PruneExpiredSymbolsRequest", "PruneExpiredSymbolsResponse", "SubscribeSymbology", "SymbologyRequest", "SymbologySnapshot", "SymbologyUpdate", "SymbolsRequest", "SymbolsResponse", "UploadProductCatalogRequest", "UploadProductCatalogResponse", "UploadSymbologyRequest", "UploadSymbologyResponse"]
|
126
|
+
__all__ = ["AccountsRequest", "AccountsResponse", "ResetPaperAccountRequest", "ResetPaperAccountResponse", "AlgoOrder", "AlgoOrderRequest", "AlgoOrdersRequest", "AlgoOrdersResponse", "CreateAlgoOrderRequest", "PauseAlgoRequest", "PauseAlgoResponse", "StartAlgoRequest", "StartAlgoResponse", "StopAlgoRequest", "StopAlgoResponse", "AlgoParamTypes", "AuthInfoRequest", "AuthInfoResponse", "CreateJwtRequest", "CreateJwtResponse", "DepositsRequest", "DepositsResponse", "OptionsTransactionsRequest", "OptionsTransactionsResponse", "RqdAccountStatisticsRequest", "RqdAccountStatisticsResponse", "StatementUrlRequest", "StatementUrlResponse", "StatementsRequest", "StatementsResponse", "WithdrawalsRequest", "WithdrawalsResponse", "ConfigRequest", "ConfigResponse", "RestartCptyRequest", "RestartCptyResponse", "CptyRequest", "CptyResponse", "CptyStatus", "CptyStatusRequest", "CptysRequest", "CptysResponse", "AccountHistoryRequest", "AccountHistoryResponse", "AccountSummariesRequest", "AccountSummariesResponse", "AccountSummary", "AccountSummaryRequest", "HistoricalFillsRequest", "HistoricalFillsResponse", "HistoricalOrdersRequest", "HistoricalOrdersResponse", "HealthCheckRequest", "HealthCheckResponse", "ArrayOfL1BookSnapshot", "Candle", "HistoricalCandlesRequest", "HistoricalCandlesResponse", "L1BookSnapshot", "L1BookSnapshotRequest", "L1BookSnapshotsRequest", "L2BookSnapshot", "L2BookSnapshotRequest", "L2BookUpdate", "Liquidation", "MarketStatus", "MarketStatusRequest", "SubscribeCandlesRequest", "SubscribeCurrentCandlesRequest", "SubscribeL1BookSnapshotsRequest", "SubscribeL2BookUpdatesRequest", "SubscribeLiquidationsRequest", "SubscribeManyCandlesRequest", "SubscribeTickersRequest", "SubscribeTradesRequest", "Ticker", "TickerRequest", "TickerUpdate", "TickersRequest", "TickersResponse", "Trade", "Cancel", "CancelAllOrdersRequest", "CancelAllOrdersResponse", "CancelOrderRequest", "OpenOrdersRequest", "OpenOrdersResponse", "Order", "PendingCancelsRequest", "PendingCancelsResponse", "PlaceOrderRequest", "OptionsChain", "OptionsChainGreeks", "OptionsChainGreeksRequest", "OptionsChainRequest", "OptionsContract", "OptionsContractGreeksRequest", "OptionsContractRequest", "OptionsExpirations", "OptionsExpirationsRequest", "OptionsGreeks", "OptionsWraps", "OptionsWrapsRequest", "Dropcopy", "DropcopyRequest", "Orderflow", "OrderflowRequest", "SubscribeOrderflowRequest", "DownloadProductCatalogRequest", "DownloadProductCatalogResponse", "ExecutionInfoRequest", "ExecutionInfoResponse", "PruneExpiredSymbolsRequest", "PruneExpiredSymbolsResponse", "SubscribeSymbology", "SymbologyRequest", "SymbologySnapshot", "SymbologyUpdate", "SymbolsRequest", "SymbolsResponse", "UploadProductCatalogRequest", "UploadProductCatalogResponse", "UploadSymbologyRequest", "UploadSymbologyResponse"]
|
@@ -12,8 +12,6 @@ from typing import Annotated, Dict, List, Literal, Optional, Union
|
|
12
12
|
|
13
13
|
from msgspec import Meta, Struct
|
14
14
|
|
15
|
-
from .Marketdata.Ticker import Ticker
|
16
|
-
|
17
15
|
|
18
16
|
class AccountHistoryGranularity(str, Enum):
|
19
17
|
FiveMinutes = "FiveMinutes"
|
@@ -422,13 +420,51 @@ class L2BookDiff(Struct, omit_defaults=True):
|
|
422
420
|
|
423
421
|
@property
|
424
422
|
def datetime(self) -> datetime:
|
423
|
+
"""
|
424
|
+
Convenience property to get the timestamp as a datetime object in UTC.
|
425
|
+
"""
|
425
426
|
return datetime.fromtimestamp(self.ts, tz=timezone.utc)
|
426
427
|
|
427
428
|
@property
|
428
429
|
def datetime_local(self) -> datetime:
|
430
|
+
"""
|
431
|
+
Convenience property to get the timestamp as a datetime object in local time.
|
432
|
+
"""
|
429
433
|
return datetime.fromtimestamp(self.ts)
|
430
434
|
|
431
435
|
|
436
|
+
class OptionsTransaction(Struct, omit_defaults=True):
|
437
|
+
clearing_firm_account: str
|
438
|
+
quantity: Decimal
|
439
|
+
timestamp: datetime
|
440
|
+
tradable_product: str
|
441
|
+
transaction_type: str
|
442
|
+
price: Optional[Decimal] = None
|
443
|
+
|
444
|
+
# Constructor that takes all field titles as arguments for convenience
|
445
|
+
@classmethod
|
446
|
+
def new(
|
447
|
+
cls,
|
448
|
+
clearing_firm_account: str,
|
449
|
+
quantity: Decimal,
|
450
|
+
timestamp: datetime,
|
451
|
+
tradable_product: str,
|
452
|
+
transaction_type: str,
|
453
|
+
price: Optional[Decimal] = None,
|
454
|
+
):
|
455
|
+
return cls(
|
456
|
+
clearing_firm_account,
|
457
|
+
quantity,
|
458
|
+
timestamp,
|
459
|
+
tradable_product,
|
460
|
+
transaction_type,
|
461
|
+
price,
|
462
|
+
)
|
463
|
+
|
464
|
+
def __str__(self) -> str:
|
465
|
+
return f"OptionsTransaction(clearing_firm_account={self.clearing_firm_account},quantity={self.quantity},timestamp={self.timestamp},tradable_product={self.tradable_product},transaction_type={self.transaction_type},price={self.price})"
|
466
|
+
|
467
|
+
|
432
468
|
OrderId = Annotated[
|
433
469
|
str, Meta(description="System-unique, persistent order identifiers")
|
434
470
|
]
|
@@ -598,6 +634,11 @@ class ProductCatalogInfo(Struct, omit_defaults=True):
|
|
598
634
|
return f"ProductCatalogInfo(exchange={self.exchange},exchange_product={self.exchange_product},category={self.category},cqg_contract_symbol={self.cqg_contract_symbol},info_url={self.info_url},long_description={self.long_description},multiplier={self.multiplier},price_display_format={self.price_display_format},quote_currency={self.quote_currency},schedule_description={self.schedule_description},settle_method={self.settle_method},short_description={self.short_description},sub_category={self.sub_category})"
|
599
635
|
|
600
636
|
|
637
|
+
class PutOrCall(str, Enum):
|
638
|
+
P = "P"
|
639
|
+
C = "C"
|
640
|
+
|
641
|
+
|
601
642
|
class RqdAccountStatistics(Struct, omit_defaults=True):
|
602
643
|
account_number: str
|
603
644
|
account_type: Optional[str] = None
|
@@ -1114,11 +1155,6 @@ class Unknown(Struct, omit_defaults=True):
|
|
1114
1155
|
return f"Unknown(product_type={self.product_type})"
|
1115
1156
|
|
1116
1157
|
|
1117
|
-
class PutOrCall(str, Enum):
|
1118
|
-
P = "P"
|
1119
|
-
C = "C"
|
1120
|
-
|
1121
|
-
|
1122
1158
|
class SnapshotOrUpdateForStringAndProductCatalogInfo1(Struct, omit_defaults=True):
|
1123
1159
|
snapshot: Dict[str, ProductCatalogInfo]
|
1124
1160
|
|
@@ -1854,6 +1890,20 @@ class Fill(Struct, omit_defaults=True):
|
|
1854
1890
|
def trade_time(self, value: int) -> None:
|
1855
1891
|
self.ts = value
|
1856
1892
|
|
1893
|
+
@property
|
1894
|
+
def datetime(self) -> datetime:
|
1895
|
+
"""
|
1896
|
+
Convenience property to get the timestamp as a datetime object in UTC.
|
1897
|
+
"""
|
1898
|
+
return datetime.fromtimestamp(self.ts, tz=timezone.utc)
|
1899
|
+
|
1900
|
+
@property
|
1901
|
+
def datetime_local(self) -> datetime:
|
1902
|
+
"""
|
1903
|
+
Convenience property to get the timestamp as a datetime object in local time.
|
1904
|
+
"""
|
1905
|
+
return datetime.fromtimestamp(self.ts)
|
1906
|
+
|
1857
1907
|
@property
|
1858
1908
|
def execution_venue(self) -> str:
|
1859
1909
|
return self.x
|
@@ -1935,85 +1985,6 @@ class Fill(Struct, omit_defaults=True):
|
|
1935
1985
|
self.xid = value
|
1936
1986
|
|
1937
1987
|
|
1938
|
-
class OptionsContract(Struct, omit_defaults=True):
|
1939
|
-
expiration: date
|
1940
|
-
put_or_call: PutOrCall
|
1941
|
-
strike: Decimal
|
1942
|
-
ticker: Ticker
|
1943
|
-
underlying: str
|
1944
|
-
in_the_money: Optional[bool] = None
|
1945
|
-
|
1946
|
-
# Constructor that takes all field titles as arguments for convenience
|
1947
|
-
@classmethod
|
1948
|
-
def new(
|
1949
|
-
cls,
|
1950
|
-
expiration: date,
|
1951
|
-
put_or_call: PutOrCall,
|
1952
|
-
strike: Decimal,
|
1953
|
-
ticker: Ticker,
|
1954
|
-
underlying: str,
|
1955
|
-
in_the_money: Optional[bool] = None,
|
1956
|
-
):
|
1957
|
-
return cls(
|
1958
|
-
expiration,
|
1959
|
-
put_or_call,
|
1960
|
-
strike,
|
1961
|
-
ticker,
|
1962
|
-
underlying,
|
1963
|
-
in_the_money,
|
1964
|
-
)
|
1965
|
-
|
1966
|
-
def __str__(self) -> str:
|
1967
|
-
return f"OptionsContract(expiration={self.expiration},put_or_call={self.put_or_call},strike={self.strike},ticker={self.ticker},underlying={self.underlying},in_the_money={self.in_the_money})"
|
1968
|
-
|
1969
|
-
|
1970
|
-
class OptionsGreeks(Struct, omit_defaults=True):
|
1971
|
-
delta: Decimal
|
1972
|
-
expiration: date
|
1973
|
-
gamma: Decimal
|
1974
|
-
implied_volatility: Decimal
|
1975
|
-
put_or_call: PutOrCall
|
1976
|
-
rho: Decimal
|
1977
|
-
strike: Decimal
|
1978
|
-
symbol: str
|
1979
|
-
theta: Decimal
|
1980
|
-
underlying: str
|
1981
|
-
vega: Decimal
|
1982
|
-
|
1983
|
-
# Constructor that takes all field titles as arguments for convenience
|
1984
|
-
@classmethod
|
1985
|
-
def new(
|
1986
|
-
cls,
|
1987
|
-
delta: Decimal,
|
1988
|
-
expiration: date,
|
1989
|
-
gamma: Decimal,
|
1990
|
-
implied_volatility: Decimal,
|
1991
|
-
put_or_call: PutOrCall,
|
1992
|
-
rho: Decimal,
|
1993
|
-
strike: Decimal,
|
1994
|
-
symbol: str,
|
1995
|
-
theta: Decimal,
|
1996
|
-
underlying: str,
|
1997
|
-
vega: Decimal,
|
1998
|
-
):
|
1999
|
-
return cls(
|
2000
|
-
delta,
|
2001
|
-
expiration,
|
2002
|
-
gamma,
|
2003
|
-
implied_volatility,
|
2004
|
-
put_or_call,
|
2005
|
-
rho,
|
2006
|
-
strike,
|
2007
|
-
symbol,
|
2008
|
-
theta,
|
2009
|
-
underlying,
|
2010
|
-
vega,
|
2011
|
-
)
|
2012
|
-
|
2013
|
-
def __str__(self) -> str:
|
2014
|
-
return f"OptionsGreeks(delta={self.delta},expiration={self.expiration},gamma={self.gamma},implied_volatility={self.implied_volatility},put_or_call={self.put_or_call},rho={self.rho},strike={self.strike},symbol={self.symbol},theta={self.theta},underlying={self.underlying},vega={self.vega})"
|
2015
|
-
|
2016
|
-
|
2017
1988
|
class OptionsSeriesInfo(Struct, omit_defaults=True):
|
2018
1989
|
derivative_kind: DerivativeKind
|
2019
1990
|
exercise_type: OptionsExerciseType
|
architect_py/grpc/orderflow.py
CHANGED
@@ -4,12 +4,8 @@ from typing import TYPE_CHECKING, Any, AsyncGenerator, AsyncIterator, Optional,
|
|
4
4
|
|
5
5
|
import grpc.aio
|
6
6
|
|
7
|
-
from architect_py.grpc.models.Orderflow.Orderflow import
|
8
|
-
from architect_py.grpc.models.Orderflow.OrderflowRequest import
|
9
|
-
OrderflowRequest,
|
10
|
-
OrderflowRequest_route,
|
11
|
-
OrderflowRequestUnannotatedResponseType,
|
12
|
-
)
|
7
|
+
from architect_py.grpc.models.Orderflow.Orderflow import *
|
8
|
+
from architect_py.grpc.models.Orderflow.OrderflowRequest import *
|
13
9
|
|
14
10
|
if TYPE_CHECKING:
|
15
11
|
from architect_py.async_client import AsyncClient
|
@@ -120,7 +116,7 @@ class OrderflowChannel:
|
|
120
116
|
self, request_iterator: AsyncIterator[OrderflowRequest]
|
121
117
|
) -> AsyncGenerator[Orderflow, None]:
|
122
118
|
"""Low-level wrapper around Architect’s gRPC bidirectional stream."""
|
123
|
-
grpc_client = await self._client.
|
119
|
+
grpc_client = await self._client._core()
|
124
120
|
decoder = grpc_client.get_decoder(OrderflowRequestUnannotatedResponseType)
|
125
121
|
|
126
122
|
stub: grpc.aio.StreamStreamMultiCallable = grpc_client.channel.stream_stream(
|
architect_py/grpc/server.py
CHANGED
@@ -41,9 +41,7 @@ class OrderflowServicer(object):
|
|
41
41
|
|
42
42
|
|
43
43
|
def add_OrderflowServicer_to_server(servicer, server):
|
44
|
-
decoder = msgspec.json.Decoder(
|
45
|
-
type=SubscribeOrderflowRequest.get_unannotated_response_type()
|
46
|
-
)
|
44
|
+
decoder = msgspec.json.Decoder(type=SubscribeOrderflowRequest)
|
47
45
|
rpc_method_handlers = {
|
48
46
|
"SubscribeOrderflow": grpc.unary_stream_rpc_method_handler(
|
49
47
|
servicer.SubscribeOrderflow,
|
@@ -4,7 +4,8 @@ from decimal import Decimal
|
|
4
4
|
import pytest
|
5
5
|
|
6
6
|
from architect_py import AsyncClient, OrderDir, TickRoundMethod
|
7
|
-
from architect_py.
|
7
|
+
from architect_py.common_types.tradable_product import TradableProduct
|
8
|
+
from architect_py.grpc.models.definitions import OrderType, SpreaderParams
|
8
9
|
|
9
10
|
|
10
11
|
@pytest.mark.asyncio
|
@@ -39,3 +40,121 @@ async def test_place_limit_order(async_client: AsyncClient):
|
|
39
40
|
await async_client.cancel_order(order.id)
|
40
41
|
|
41
42
|
await async_client.close()
|
43
|
+
|
44
|
+
|
45
|
+
@pytest.mark.asyncio
|
46
|
+
@pytest.mark.timeout(3)
|
47
|
+
async def test_place_market_order(async_client: AsyncClient):
|
48
|
+
venue = "CME"
|
49
|
+
front_future = await async_client.get_front_future("ES CME Futures", venue)
|
50
|
+
info = await async_client.get_execution_info(front_future, venue)
|
51
|
+
assert info is not None
|
52
|
+
assert info.tick_size is not None
|
53
|
+
snap = await async_client.get_ticker(front_future, venue)
|
54
|
+
assert snap is not None
|
55
|
+
assert snap.bid_price is not None
|
56
|
+
accounts = await async_client.list_accounts()
|
57
|
+
account = accounts[0]
|
58
|
+
|
59
|
+
# bid far below the best bid
|
60
|
+
order = await async_client.place_order(
|
61
|
+
symbol=front_future,
|
62
|
+
execution_venue=venue,
|
63
|
+
dir=OrderDir.BUY,
|
64
|
+
quantity=Decimal(1),
|
65
|
+
order_type=OrderType.MARKET,
|
66
|
+
account=str(account.account.id),
|
67
|
+
)
|
68
|
+
|
69
|
+
assert order is not None
|
70
|
+
|
71
|
+
await asyncio.sleep(1.5)
|
72
|
+
order = await async_client.get_order(order.id)
|
73
|
+
assert order is not None
|
74
|
+
|
75
|
+
await async_client.close()
|
76
|
+
|
77
|
+
|
78
|
+
@pytest.mark.asyncio
|
79
|
+
@pytest.mark.timeout(3)
|
80
|
+
async def test_equity_order(async_client: AsyncClient):
|
81
|
+
tradable_product = TradableProduct(base_or_value="AAPL US Equity/USD")
|
82
|
+
|
83
|
+
product_info = await async_client.get_product_info(tradable_product.base())
|
84
|
+
assert product_info is not None
|
85
|
+
venue = product_info.primary_venue
|
86
|
+
assert venue is not None
|
87
|
+
|
88
|
+
market_status = await async_client.get_market_status(tradable_product, venue)
|
89
|
+
if not market_status.is_trading:
|
90
|
+
pytest.skip(f"Market {venue} for {tradable_product} is not open")
|
91
|
+
|
92
|
+
info = await async_client.get_execution_info(tradable_product, venue)
|
93
|
+
assert info is not None
|
94
|
+
# assert info.tick_size is not None
|
95
|
+
|
96
|
+
tick_size = Decimal("0.01")
|
97
|
+
|
98
|
+
snap = await async_client.get_ticker(tradable_product, venue)
|
99
|
+
assert snap is not None
|
100
|
+
assert snap.bid_price is not None
|
101
|
+
accounts = await async_client.list_accounts()
|
102
|
+
account = accounts[0]
|
103
|
+
|
104
|
+
# bid far below the best bid
|
105
|
+
limit_price = TickRoundMethod.FLOOR(snap.bid_price * Decimal(0.9), tick_size)
|
106
|
+
order = await async_client.place_order(
|
107
|
+
symbol=tradable_product,
|
108
|
+
execution_venue=venue,
|
109
|
+
dir=OrderDir.BUY,
|
110
|
+
quantity=Decimal(1),
|
111
|
+
order_type=OrderType.LIMIT,
|
112
|
+
limit_price=limit_price,
|
113
|
+
post_only=False,
|
114
|
+
account=str(account.account.id),
|
115
|
+
)
|
116
|
+
|
117
|
+
assert order is not None
|
118
|
+
await asyncio.sleep(1)
|
119
|
+
await async_client.cancel_order(order.id)
|
120
|
+
|
121
|
+
await async_client.close()
|
122
|
+
|
123
|
+
|
124
|
+
@pytest.mark.asyncio
|
125
|
+
@pytest.mark.timeout(3)
|
126
|
+
async def test_spreader_algo(async_client: AsyncClient):
|
127
|
+
accounts = await async_client.list_accounts()
|
128
|
+
account = accounts[0]
|
129
|
+
|
130
|
+
venue = "CME"
|
131
|
+
|
132
|
+
front_ES_future = await async_client.get_front_future("ES CME Futures", venue)
|
133
|
+
front_NQ_future = await async_client.get_front_future("NQ CME Futures", venue)
|
134
|
+
|
135
|
+
params = SpreaderParams(
|
136
|
+
dir=OrderDir.BUY, # or OrderDir.SELL
|
137
|
+
leg1_marketdata_venue=venue,
|
138
|
+
leg1_price_offset=Decimal("0"),
|
139
|
+
leg1_price_ratio=Decimal("1"),
|
140
|
+
leg1_quantity_ratio=Decimal("1"),
|
141
|
+
leg1_symbol=front_ES_future,
|
142
|
+
leg2_marketdata_venue=venue,
|
143
|
+
leg2_price_offset=Decimal("0"),
|
144
|
+
leg2_price_ratio=Decimal("-1"),
|
145
|
+
leg2_quantity_ratio=Decimal("-1"),
|
146
|
+
leg2_symbol=front_NQ_future,
|
147
|
+
limit_price=Decimal("0.25"),
|
148
|
+
order_lockout="1s",
|
149
|
+
quantity=Decimal("10"),
|
150
|
+
leg1_account=account.account.id,
|
151
|
+
leg1_execution_venue=venue,
|
152
|
+
leg2_account=account.account.id,
|
153
|
+
leg2_execution_venue=venue,
|
154
|
+
)
|
155
|
+
|
156
|
+
order = await async_client.place_algo_order(params=params)
|
157
|
+
|
158
|
+
print(order)
|
159
|
+
|
160
|
+
await async_client.close()
|