diff --git a/lib/ex_fix/session.ex b/lib/ex_fix/session.ex index 1e923f0..13f4571 100644 --- a/lib/ex_fix/session.ex +++ b/lib/ex_fix/session.ex @@ -480,7 +480,7 @@ defmodule ExFix.Session do reject_msg = build_message(config, @msg_type_reject, out_lastseq, [ {@field_session_reject_reason, "10"}, - {@field_text, "SendingTime acccuracy problem"} + {@field_text, "SendingTime accuracy problem"} ]) {:ok, [reject_msg], @@ -720,7 +720,7 @@ defmodule ExFix.Session do end defp validate_sending_time(session_name, %Session{config: config, out_lastseq: out_lastseq} = session, %InMessage{fields: fields, other_msgs: other}, expected_seqnum) do - %SessionConfig{time_service: time_service, session_handler: handler, env: env} = config + %SessionConfig{time_service: time_service, session_handler: handler, env: env, sending_time_tolerance: tolerance} = config now = case time_service do @@ -733,7 +733,7 @@ defmodule ExFix.Session do {@field_sending_time, st} -> with {:ok, sending_dt} <- DateUtil.parse_date(st), diff <- abs(DateTime.to_unix(now) - DateTime.to_unix(sending_dt)), - true <- diff <= 120 do + true <- diff <= tolerance do :ok else _ -> @@ -743,7 +743,7 @@ defmodule ExFix.Session do reject_msg = build_message(config, @msg_type_reject, out_lastseq, [ {@field_session_reject_reason, "10"}, - {@field_text, "SendingTime acccuracy problem"} + {@field_text, "SendingTime accuracy problem"} ]) out_lastseq = out_lastseq + 1 diff --git a/lib/ex_fix/session_config.ex b/lib/ex_fix/session_config.ex index 585ffa9..51c7696 100644 --- a/lib/ex_fix/session_config.ex +++ b/lib/ex_fix/session_config.ex @@ -26,6 +26,7 @@ defmodule ExFix.SessionConfig do transport_mod: :gen_tcp, transport_options: [], time_service: nil, + sending_time_tolerance: 120, env: %{} @type t :: %__MODULE__{} diff --git a/test/session_test.exs b/test/session_test.exs index 7b5c9ef..1824790 100644 --- a/test/session_test.exs +++ b/test/session_test.exs @@ -406,7 +406,7 @@ defmodule ExFix.SessionTest do assert reject_msg.target == "SELLSIDE" assert reject_msg.orig_sending_time == @t_plus_1 assert :lists.keyfind("373", 1, reject_msg.body) == {"373", "10"} - assert :lists.keyfind("58", 1, reject_msg.body) == {"58", "SendingTime acccuracy problem"} + assert :lists.keyfind("58", 1, reject_msg.body) == {"58", "SendingTime accuracy problem"} end test "PossDupFlag=Y and OrigSendingTime not specified (p. 51)", %{config: cfg} do @@ -617,7 +617,7 @@ defmodule ExFix.SessionTest do assert reject_msg.target == "SELLSIDE" assert reject_msg.orig_sending_time == @t_plus_1 assert :lists.keyfind("373", 1, reject_msg.body) == {"373", "10"} - assert :lists.keyfind("58", 1, reject_msg.body) == {"58", "SendingTime acccuracy problem"} + assert :lists.keyfind("58", 1, reject_msg.body) == {"58", "SendingTime accuracy problem"} assert logout_msg.seqnum == 7 assert logout_msg.msg_type == @msg_type_logout @@ -627,6 +627,36 @@ defmodule ExFix.SessionTest do assert :lists.keyfind("58", 1, logout_msg.body) == {"58", "Incorrect SendingTime value"} end + test "SendingTime accuracy with custom tolerance", %{config: cfg} do + # Test with custom tolerance of 30 seconds + custom_config = %SessionConfig{cfg | sending_time_tolerance: 30} + {:ok, session} = Session.init(custom_config) + session = %Session{session | status: :online, in_lastseq: 10, out_lastseq: 5} + + seq = 11 + # Use 1 minute difference (60 seconds), which should exceed 30 second tolerance + incoming_data = + build_message( + @msg_type_execution_report, + seq, + "SELLSIDE", + "BUYSIDE", + DateTime.add(@t0, 60, :second), + [{@field_account, "1234"}] + ) + + session = Session.set_time(session, @t0) + {:logout, msgs_to_send, session} = Session.handle_incoming_data(session, incoming_data) + + assert Session.get_status(session) == :disconnecting + assert length(msgs_to_send) == 2 + [reject_msg, _logout_msg] = msgs_to_send + + assert reject_msg.msg_type == @msg_type_reject + assert :lists.keyfind("373", 1, reject_msg.body) == {"373", "10"} + assert :lists.keyfind("58", 1, reject_msg.body) == {"58", "SendingTime accuracy problem"} + end + test "Checksum error (p. 55)", %{config: cfg} do # > CheckSum error is not the last field of message, value doesn't have length of 3, or isn't delimited by SOH # Ignore message - don't increment expected MsgSeqNum