Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
PROTO_PATH=async_rithmic/protocol_buffers/
TESTS_PATH?=tests

# protoc version: 25.4
protoc:
$(PROTOC_DIR)protoc -I=$(PROTO_PATH)source --python_out=$(PROTO_PATH) $(PROTO_PATH)source/*.proto

Expand Down
6 changes: 2 additions & 4 deletions async_rithmic/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
from collections import defaultdict
from pattern_kit import DelegateMixin, Event

from .plants.ticker import TickerPlant
from .plants.history import HistoryPlant
from .plants.order import OrderPlant
from .plants.pnl import PnlPlant
from .plants import TickerPlant, HistoryPlant, OrderPlant, PnlPlant, RepositoryPlant
from .logger import logger
from .enums import OrderPlacement, SysInfraType
from .objects import ReconnectionSettings, RetrySettings
Expand Down Expand Up @@ -101,6 +98,7 @@ def __init__(
"order": OrderPlant(self, **kwargs),
"pnl": PnlPlant(self, **kwargs),
"history": HistoryPlant(self, **kwargs),
"repository": RepositoryPlant(self, **kwargs),
}

for plant in self.plants.values():
Expand Down
3 changes: 1 addition & 2 deletions async_rithmic/helpers/request_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@ async def send_and_collect(self, timeout: float = 30.0, **kwargs):

expected_response = kwargs.pop("expected_response")

if kwargs["template_id"] in [113, 312, 314, 316, 330, 338, 340, 3504]:
if kwargs["template_id"] in [113, 312, 314, 316, 330, 338, 340, 504, 506, 3504]:
# Some endpoints will contain the user msg / request id
expected_response["user_msg"] = [request_id]

elif "account_id" in kwargs:
# Else, it will contain the same account id as the request
expected_response["account_id"] = kwargs["account_id"]


self.plant.logger.debug(f"Sending request {request_id}")
self.start(request_id, kwargs, expected_response)
await self.plant._send_request(**kwargs)
Expand Down
1 change: 1 addition & 0 deletions async_rithmic/plants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
from .order import OrderPlant
from .history import HistoryPlant
from .pnl import PnlPlant
from .repository import RepositoryPlant
11 changes: 11 additions & 0 deletions async_rithmic/plants/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@
403: pb.response_pnl_position_snapshot_pb2.ResponsePnLPositionSnapshot,
450: pb.instrument_pnl_position_update_pb2.InstrumentPnLPositionUpdate,
451: pb.account_pnl_position_update_pb2.AccountPnLPositionUpdate,

# Repository Plant Infrastructure
500: pb.request_list_unaccepted_agreements_pb2.RequestListUnacceptedAgreements,
501: pb.response_list_unaccepted_agreements_pb2.ResponseListUnacceptedAgreements,
502: pb.request_list_accepted_agreements_pb2.RequestListAcceptedAgreements,
503: pb.response_list_accepted_agreements_pb2.ResponseListAcceptedAgreements,
504: pb.request_accept_agreement_pb2.RequestAcceptAgreement,
505: pb.response_accept_agreement_pb2.ResponseAcceptAgreement,
506: pb.request_show_agreement_pb2.RequestShowAgreement,
507: pb.response_show_agreement_pb2.ResponseShowAgreement,
}

class BasePlant(BackgroundTaskMixin):
Expand Down Expand Up @@ -176,6 +186,7 @@ def plant_type(self):
SysInfraType.PNL_PLANT: "pnl",
SysInfraType.TICKER_PLANT: "ticker",
SysInfraType.ORDER_PLANT: "order",
SysInfraType.REPOSITORY_PLANT: "repository",
}[self.infra_type]

async def _connect(self):
Expand Down
67 changes: 67 additions & 0 deletions async_rithmic/plants/repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from typing import Literal

from .base import BasePlant
from ..enums import SysInfraType


class RepositoryPlant(BasePlant):
infra_type = SysInfraType.REPOSITORY_PLANT

async def list_unaccepted_agreements(self) -> list:
"""
Return list of unaccepted agreements
"""

return await self._send_and_collect(
template_id=500,
expected_response=dict(template_id=501),
account_id=None,
)

async def list_accepted_agreements(self) -> list:
"""
Return list of accepted agreements
"""

return await self._send_and_collect(
template_id=502,
expected_response=dict(template_id=503),
account_id=None,
)

async def get_agreement(self, agreement_id: str):
"""
Return an agreement
"""

responses = await self._send_and_collect(
template_id=506,
expected_response=dict(template_id=507),
agreement_id=agreement_id,
account_id=None,
)
return self._first(responses)

async def accept_agreement(
self,
agreement_id: str,
market_data_usage_capacity: Literal["Professional", "Non-Professional"]
):
"""
Attempt to accept an agreement.

Notes
-----
Rithmic appears to restrict this functionality through the API. In practice,
this request may fail even when the agreement ID and usage capacity are valid.

Users may need to accept agreements manually through an official Rithmic app.
"""

return await self._send_and_collect(
template_id=504,
expected_response=dict(template_id=505),
agreement_id=agreement_id,
market_data_usage_capacity=market_data_usage_capacity,
account_id=None,
)
26 changes: 26 additions & 0 deletions async_rithmic/protocol_buffers/request_accept_agreement_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions async_rithmic/protocol_buffers/request_show_agreement_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions async_rithmic/protocol_buffers/response_accept_agreement_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions async_rithmic/protocol_buffers/response_show_agreement_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
syntax = "proto3";

package rti;

message RequestAcceptAgreement
{
int32 template_id = 154467;
repeated string user_msg = 132760;

string agreement_id = 153407;
string market_data_usage_capacity = 153431; // Professional or Non-Professional
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

package rti;

message RequestListAcceptedAgreements
{
int32 template_id = 154467;
repeated string user_msg = 132760;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

package rti;

message RequestListUnacceptedAgreements
{
int32 template_id = 154467;
repeated string user_msg = 132760;
}
Loading
Loading