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
13 changes: 13 additions & 0 deletions omega_client/communication/omega_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,19 @@ def logoff(self, request_header: RequestHeader):
"""
return self._request_sender.logoff(request_header=request_header)

def send_test_message(self, request_header: RequestHeader,
test_message: str):
"""
Sends a test message to Omega for checking connectivity. Client id
and sender_comp_id won't be checked although they are required,
so fake ids can be sent.
:param request_header: Header parameter object for requests.
:param test_message: (str) Test message.
:return: (capnp._DynamicStructBuilder) test_message capnp object.
"""
return self._request_sender.send_test_message(
request_header=request_header, test_message=test_message)

def send_heartbeat(self, request_header: RequestHeader):
"""
Sends a heartbeat to Omega for maintaining and verifying connection.
Expand Down
19 changes: 13 additions & 6 deletions omega_client/communication/request_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
OrderType, RequestHeader, TimeInForce, WorkingOrdersReport, Batch, OPO, OCO
from omega_client.messaging.message_factory import cancel_all_orders_capnp, \
cancel_order_capnp, heartbeat_capnp, logoff_capnp, logon_capnp, \
place_order_capnp, replace_order_capnp, request_account_balances_capnp, \
request_account_data_capnp, request_auth_refresh_capnp, \
request_completed_orders_capnp, request_exchange_properties_capnp, \
request_open_positions_capnp, request_order_status_capnp, \
request_server_time_capnp, request_working_orders_capnp, \
place_contingent_order_capnp
omega_test_message_capnp, place_order_capnp, replace_order_capnp, \
request_account_balances_capnp, request_account_data_capnp, \
request_auth_refresh_capnp, request_completed_orders_capnp, \
request_exchange_properties_capnp, request_open_positions_capnp, \
request_order_status_capnp, request_server_time_capnp, \
request_working_orders_capnp, place_contingent_order_capnp

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -168,6 +168,13 @@ def send_heartbeat(self, request_header: RequestHeader):
self._queue_message(omega_message)
return body

def send_test_message(self, request_header: RequestHeader,
test_message: str):
omega_message, body = omega_test_message_capnp(
request_header=request_header, test_message=test_message)
self._queue_message(omega_message)
return body

def request_server_time(self, request_header: RequestHeader):
"""
Request Omega server time for syncing client and server timestamps.
Expand Down
4 changes: 4 additions & 0 deletions omega_client/communication/single_client_omega_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ def logoff(self):
"""
return self._request_sender.logoff()

def send_test_message(self, test_message: str):
return self._request_sender.send_test_message(
test_message=test_message)

def send_heartbeat(self):
"""
Sends a heartbeat to Omega for maintaining and verifying connection.
Expand Down
4 changes: 4 additions & 0 deletions omega_client/communication/single_client_request_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def logon(self,
def logoff(self):
return self._request_sender.logoff(request_header=self._request_header)

def send_test_message(self, test_message: str):
return self._request_sender.send_test_message(
request_header=self._request_header, test_message=test_message)

def send_heartbeat(self):
return self._request_sender.send_heartbeat(
request_header=self._request_header)
Expand Down
20 changes: 10 additions & 10 deletions omega_client/examples/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

def main():
client_id = 1
# sender_comp_id is a unique identifier for a omega_client. Omega supports the
# sender_comp_id is a unique identifier. Omega supports the
# use case of multiple omega_clients sending messages with the same
# client_id, hence a sender_comp_id is needed to distinguish the machine
# and client in the middle of a request and response communication.
Expand All @@ -33,12 +33,12 @@ def main():
sender_comp_id = str(uuid.uuid4())
client_id_machine_dict[client_id] = sender_comp_id

omega_connection, request_sender, response_receiver = (
configure_single_client_omega_connection(OMEGA_ENDPOINT,
OMEGA_SERVER_KEY,
client_id,
sender_comp_id,
PrintingResponseHandler()))
omega_connection = configure_single_client_omega_connection(
OMEGA_ENDPOINT,
OMEGA_SERVER_KEY,
client_id,
sender_comp_id,
PrintingResponseHandler())

omega_connection.start()
omega_connection.wait_until_running()
Expand All @@ -50,9 +50,9 @@ def main():
credentials = AccountCredentials(AccountInfo(account_id), api_key,
secret_key, passphrase)

request_sender.logon([credentials])
request_sender.send_heartbeat()
request_sender.logoff()
omega_connection.logon([credentials])
omega_connection.send_heartbeat()
omega_connection.logoff()
time.sleep(2)
omega_connection.cleanup()

Expand Down
33 changes: 9 additions & 24 deletions omega_client/examples/logon_logoff.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from omega_client.messaging.common_types import AccountCredentials, AccountInfo
from omega_client.messaging.printing_response_handler import \
PrintingResponseHandler
from omega_client.examples.single_client_session_refresher import SingleClientSessionRefresher

OMEGA_ENDPOINT = "tcp://0.0.0.0:9999"
OMEGA_SERVER_KEY = "omega_server_key"
Expand Down Expand Up @@ -37,13 +36,12 @@ def main():
# See omega_client.messaging.response_handler and
# omega_client.messaging.printing_response_handler (example child class
# that just prints everything).
omega_connection, request_sender, response_receiver = (
configure_single_client_omega_connection(
omega_endpoint=OMEGA_ENDPOINT,
omega_server_key=OMEGA_SERVER_KEY,
client_id=client_id,
sender_comp_id=sender_comp_id,
response_handler=PrintingResponseHandler()))
omega_connection = configure_single_client_omega_connection(
omega_endpoint=OMEGA_ENDPOINT,
omega_server_key=OMEGA_SERVER_KEY,
client_id=client_id,
sender_comp_id=sender_comp_id,
response_handler=PrintingResponseHandler())
# Starting the TesConnection thread.
omega_connection.start()
# Waiting for the TesConnection to be set up.
Expand All @@ -61,33 +59,20 @@ def main():
secret_key=secret_key,
passphrase=passphrase)

# initialize SessionRefresher
session_refresher = SingleClientSessionRefresher(
request_sender=request_sender,
client_id=client_id,
sender_comp_id=sender_comp_id
)

# update response_handler to use SessionRefresher
response_receiver.set_response_handler(
PrintingResponseHandler(session_refresher=session_refresher)
)

# Send logon message, which when received will start and update token for
# session_refresher. session_refresher will run until stopped
request_sender.logon([credentials])
omega_connection.logon([credentials])
time.sleep(2)

# send a heartbeat every minute for 2 hours (during which the session
# should refresh at least once)
minutes_left = 120
while minutes_left > 0:
request_sender.send_heartbeat()
omega_connection.send_heartbeat()
time.sleep(60)

# stop and cleanup
session_refresher.stop()
request_sender.logoff()
omega_connection.logoff()
time.sleep(2)
omega_connection.cleanup()

Expand Down
20 changes: 10 additions & 10 deletions omega_client/examples/place_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
def main():
client_id = 1
sender_comp_id = str(uuid.uuid4())
omega_connection, request_sender, response_receiver = (
configure_single_client_omega_connection(OMEGA_ENDPOINT,
OMEGA_SERVER_KEY,
client_id,
sender_comp_id,
PrintingResponseHandler()))
omega_connection = configure_single_client_omega_connection(
OMEGA_ENDPOINT,
OMEGA_SERVER_KEY,
client_id,
sender_comp_id,
PrintingResponseHandler())

omega_connection.start()
omega_connection.wait_until_running()
Expand All @@ -32,8 +32,8 @@ def main():
credentials = AccountCredentials(AccountInfo(account_id), api_key,
secret_key, passphrase)

request_sender.logon([credentials])
request_sender.send_heartbeat()
omega_connection.logon([credentials])
omega_connection.send_heartbeat()
order = Order(
account_info=AccountInfo(account_id=account_id),
# ID generated by client to keep track of the order
Expand All @@ -47,9 +47,9 @@ def main():
time_in_force=TimeInForce.gtc.name,
leverage_type=LeverageType.none.name
)
request_sender.place_order(order)
omega_connection.place_order(order)
time.sleep(2)
request_sender.logoff()
omega_connection.logoff()
time.sleep(2)
omega_connection.cleanup()

Expand Down
14 changes: 14 additions & 0 deletions omega_client/messaging/message_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,20 @@ def logoff_capnp(request_header: RequestHeader):
return omega_message, body


def omega_test_message_capnp(request_header: RequestHeader,
test_message: str):
"""
Generates a capnp test message with a specific clientID.
:param request_header: Header parameter object for requests.
:param test_message: (str) Test message.
:return: (capnp._DynamicStructBuilder) Test capnp object.
"""
omega_message, body = _generate_omega_request(request_header=request_header)
test = body.init('test')
test.string = test_message
return omega_message, body


def heartbeat_capnp(request_header: RequestHeader):
"""
Generates a capnp heartbeat message.
Expand Down
8 changes: 8 additions & 0 deletions tests/communication/test_request_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,3 +842,11 @@ def test_place_contingent_opo_batch_order(fake_request_sender):
assert batch_order1.stopPrice == 0.0
assert batch_order1.timeInForce == 'gtc'
assert batch_order1.expireAt == 0.0


@pytest.mark.test_id(30)
def test_omega_test_message(fake_request_sender):
test = fake_request_sender.send_test_message(
request_header=__FAKE_REQUEST_HEADER, test_message='test message')
assert type(test) == capnp.lib.capnp._DynamicStructBuilder
assert test.test.string == 'test message'
12 changes: 11 additions & 1 deletion tests/communication/test_single_client_request_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def fake_zmq_context():
def fake_request_sender(fake_zmq_context):
request_sender = SingleClientRequestSender(
zmq_context=fake_zmq_context,
connection_string=__FAKE_REQUEST_SENDER_CONNECTION_STR,
zmq_endpoint=__FAKE_REQUEST_SENDER_CONNECTION_STR,
client_id=TEST_CLIENT_ID,
sender_comp_id=TEST_SENDER_COMP_ID
)
Expand Down Expand Up @@ -387,3 +387,13 @@ def test_request_exchange_properties_invalid_case(fake_request_sender):
)
assert type(exch_prop) == capnp.lib.capnp._DynamicStructBuilder
assert exch_prop.exchange == exch_capnp.Exchange.undefined


@pytest.mark.test_id(18)
def test_send_test_message(fake_request_sender):
# valid exchange test case
test = fake_request_sender.send_test_message(
test_message='test message'
)
assert type(test) == capnp.lib.capnp._DynamicStructBuilder
assert test.test.string == 'test message'
62 changes: 53 additions & 9 deletions tests/messaging/test_message_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
completed_orders_report_py, \
exchange_properties_report_py, execution_report_py, \
generate_client_order_id, logoff_ack_py, logon_ack_py, \
open_positions_report_py, system_message_py, omega_test_message_py, \
working_orders_report_py, cancel_order_capnp, heartbeat_capnp, \
logoff_capnp, logon_capnp, place_order_capnp, replace_order_capnp, \
request_account_balances_capnp, request_account_data_capnp, \
request_auth_refresh_capnp, request_completed_orders_capnp, \
request_exchange_properties_capnp, request_open_positions_capnp, \
request_order_status_capnp, request_server_time_capnp, \
request_working_orders_capnp, _determine_order_price, \
_generate_omega_request
omega_test_message_capnp, open_positions_report_py, system_message_py, \
omega_test_message_py, working_orders_report_py, cancel_order_capnp, \
heartbeat_capnp, logoff_capnp, logon_capnp, place_order_capnp, \
replace_order_capnp, request_account_balances_capnp, \
request_account_data_capnp, request_auth_refresh_capnp, \
request_completed_orders_capnp, request_exchange_properties_capnp, \
request_open_positions_capnp, request_order_status_capnp, \
request_server_time_capnp, request_working_orders_capnp, \
_determine_order_price, _generate_omega_request

__FAKE_ACCESS_TOKEN = 'FakeAccessToken'
__FAKE_REQUEST_HEADER = RequestHeader(client_id=123,
Expand Down Expand Up @@ -953,3 +953,47 @@ def test_handle_omega_message_completed_contingent_orders_report():
assert exec_reports[1].contingent_type == 'oco'
assert type(exec_reports[2].contingent_type) == str
assert exec_reports[2].contingent_type == 'batch'


@pytest.mark.test_id(21)
def test_handle_omega_message_test():
omega_mess = msgs_capnp.TradeMessage.new_message()
test_resp = omega_mess.init('type').init('response')
test_resp.clientID = 123
test_resp.senderCompID = str(987)
test_resp.requestID = 100001
body = test_resp.init('body')

test_message = 'test message'
test = body.init('test')
test.string = test_message

test_message = omega_test_message_py(omega_mess.type.response.body.test)
assert type(test_message) == str
assert test_message == test_message


@pytest.mark.test_id(22)
def test_send_test_message_capnp():
test_message = 'test message'
expected_omega_message = msgs_capnp.TradeMessage.new_message()
test_req = expected_omega_message.init('type').init('request')
test_req.clientID = 123
test_req.senderCompID = str(987)
test_req.requestID = 100001
test_req.accessToken = __FAKE_ACCESS_TOKEN
body = test_req.init('body')
test = body.init('test')
test.string = test_message

actual_omega_message = omega_test_message_capnp(__FAKE_REQUEST_HEADER,
test_message)[0]

assert actual_omega_message.type.request.clientID == (
expected_omega_message.type.request.clientID)
assert actual_omega_message.type.request.senderCompID == (
expected_omega_message.type.request.senderCompID)
assert actual_omega_message.type.request.requestID == (
expected_omega_message.type.request.requestID)
actual_test_string = actual_omega_message.type.request.body.test.string
assert actual_test_string == test_message