Fix heartbeat and connection issues.
Fix heartbeat and connection issues.
12 Apr 2022, 20:14
Hi,
I am using the Python implementation of Fix for my trading service. I have a pricing connection and a trading connection set up. From the pricing connection I get signals to trade. I would like to keep my connection time as close to default (30s) as possible. To make sure the connection is not closed out I want to make use of the HeartBeat and Test Request messages. From the documentation I found at https://www.fixtrading.org/standards/fix-session-layer-online/ (See Test Request Processing below Figure 7) I understand that if my service responds to heartbeat messages from the cTrade Fix server the connection should stay open.
However, my implementation does not. Please review the behaviour and implementation and provide guidance where I can fix my code / whether my interpretation is wrong.
My service is experiencing the following
cTrade myservice
Heartbeat () -------------------------> Receive Heartbeat ()
time passes (~Heartbeat timeout)
Receive Heartbeat <------------- Heartbeat (TestReqID = datetime.now()) #The referenced documentation suggests this hearbeat response should return an increasing
time passes (~Heartbeat timeout)
TestRequest() -----------------------> Receive TestRequest
time passes (~Heartbeat timeout)
Receive Heartbeat <---------------- Heartbeat (TestReqID = message.get(112) ) # The documentation specifies that my response must include TestReqID used by the TestRequest message
time passes (~Heartbeat timeout)
Close connection ---------------->>>
--------------------------------------------------
I believe the behaviour should be as follows
cTrade myservice
Heartbeat () -------------------------> Receive Heartbeat ()
time passes (~Heartbeat timeout)
Receive Heartbeat <------------- Heartbeat (TestReqID = datetime.now()) #The referenced documentation suggests this hearbeat response should return an increasing
time passes (~Heartbeat timeout)
Heartbeat () -------------------------> Receive Heartbeat ()
-------------------------------------------------------------
My event code are as follows:
def tradingClientOnMessageReceived(tradingClient, responseMessage): messageList = getMessageList(responseMessage) for message in messageList: try: message_type = message.get(35) if message_type == b'0': print() print(end='HB received ') parameters = {'TestReqID': str(datetime.now())} request = Heartbeat(config) setParameters(request, **parameters) tradingClient.send(request) sendTradingClientHeartbeat.timer = datetime.now() elif message_type == b'1': print() print('TR received:', message.get(112).decode("utf-8"), end=' ') #parameters = {'TestReqID': message.get(112).decode("utf-8")} parameters = {'TestReqID': message.get(112)} request = Heartbeat(config) setParameters(request, **parameters) tradingClient.send(request) sendTradingClientHeartbeat.timer = datetime.now()
Replies
Groenewald.a.m
13 Apr 2022, 11:47
Fix heartbeat and connection issues.
Thank you for responding.
Yes, I based my work on your package (thank you, it gave me a great start)
The issue here is that the sample package does not do the kind of handshake that I am looking for. To be clear, as is the connection is re-established after the connection is terminated and the log-on happens through the Open Connection callback.
The problem here is that I have seen if a trade happens around that time, I get a 'Resend Request' which opens up a whole other can of worms which I will ask guidance on in a separate mail
What I am trying to achieve is to use the heartbeats to minimise the number of times a connection gets re-established and login happens again. If I leave the connection timeout at 30 seconds, the connection is re-esttablished every ~ 60 seconds (after heartbeat---30 seconds passes -- TestRequest --- 30 seconds passes --- Connection drops and reconnects then process repeats.)
In this scenario I need to have a real robust resend strategy. Here I will need to re-synchronise the FIX messageIDs and it does not look like I have an obvious way to set that in the python implementation. This is a bunch of work (if you have an example of this in any language it would be much apprecited)
@Groenewald.a.m
amusleh
13 Apr 2022, 13:19
( Updated at: 13 Apr 2022, 13:21 )
Hi,
When you made the connection and sent the LogonRequest to keep alive your connection you have to keep sending Test Request based on your session heartbeat interval and responding to server Test request by sending an heartbeat and using server Test Request TestReqID.
Whenever you send a Test Request server will send you back an heartbeat and you should use an incremental value for Test Request TestReqID, and increment it by one on each subsequent Test Request you send to the server.
This way you will be able to keep your connection alive.
I tested it on our Python package console sample and it works, the issue with our console sample is that it blocks the main running thread while waiting for getting user input, we use a time out based on user config heartbeat amount and when it times out the thread will be released again to continue receiving and sending message from/to server, and after thread release we send a Test Request to keep the connection alive.
I just released a new version of our Python package and I made some changes on console sample, update to latest version and also update your console sample, then test it see if it can keep the connection alive or not.
If you send a Test request before sending Logon message your connection will be dropped.
@amusleh
Groenewald.a.m
13 Apr 2022, 21:13
Fix heartbeat and connection issues. - fixed
Hi,
I downloaded the new version and it worked like a charm, ta !
@Groenewald.a.m
amusleh
13 Apr 2022, 10:55
Hi,
I tested on our cTraderFixPy Python package and the connection remained open after sending heartbeat, can you try cTraderFixPy console sample and see if it happens or not.
spotware/cTraderFixPy: A Python package for interacting with cTrader FIX API. (github.com)
@amusleh