OnixS C++ FIX Engine 4.13.0
API Documentation
Loading...
Searching...
No Matches
Scheduling Sessions for Automatic Connection

Inner Contents

 Session Schedule
 Session Connection Settings
 Predefined Schedules and Connection Settings

Detailed Description

In real life Sessions FIX Connections occurs at regular intervals. A lot of trading systems have public schedules which declare time frames for trading. Session class exposes members for a FIX Connections basic handling. It also provides users with an automatic reconnection facility in case of the connection failure. However, there is no way in Session functionality to maintain Connections on a systematic basis.

Sessions Scheduler

To satisfy the needs of real-life trading schedules, OnixS FIX Engine offers the Sessions Scheduler. This service will automatically connect certain FIX sessions to the counterparty at the beginning of the trading day, as well as disconnect at the end of the day. It is also possible to keep a FIX Session connected for an entire trading week and disconnect it at the end of the last trading day.

The Sessions Scheduler is available as a part of OnixS FIX Engine.

SessionScheduler class

OnixS::FIX::Scheduling::SessionScheduler is a workhorse class of the Sessions Scheduling services. This class exposes a simple, but comprehensive API, to handle connections by schedules of any complexity.

Registering a Session for Automatic Connection

OnixS::FIX::Scheduling::SessionScheduler::add member schedules a session for automatic logon and logout according to the specified session time, which can be delivered to Scheduler as an instance of the appropriate class, or as a name of the predefined preset. The parameter of the type OnixS::FIX::Scheduling::SessionConnectionSettings specifies the role of Session (either Acceptor or Initiator), and primary connection parameters like host and port, which Session will use to establish FIX Connection.

Note
If Session is being registered at the time, noted by schedule, the Scheduler will connect the Session immediately.

Removing Session from Scheduling Services

OnixS::FIX::Scheduling::SessionScheduler::remove given session from the scheduling services.

Note
OnixS::FIX::Scheduling::SessionScheduler::remove doesn't disconnect an active session from the trading system. Therefore, if the session has already been connected by the scheduler, it remains connected after unregistering.

Important Behavioral Aspects

The following steps take place while scheduling Session:

  • If a session is registered during the time covered by the specified schedule, the scheduler will connect the session immediately.
  • If a session is registered after logout and before logon time, no attempts will be made to connect the session until the next logon time.
  • If a session is registered after logout and before logon time, and the session is in an active state, it will be disconnected immediately.
  • In case of regular logon failure, a scheduler tries to logon again in accordance with his own reconnection settings (OnixS::FIX::Scheduling::SessionScheduler::reconnectAttempts and OnixS::FIX::Scheduling::SessionScheduler::reconnectInterval values).
  • In case of an active connection break by some network issues, the FIX Engine tries to restore the connection in accordance with the Engine configuration (Reconnect.Attempts and Reconnect.Interval values).
  • In case of a normal disconnect of an active connection by Logout messages exchange, during the activity time, the scheduler tries to logon again immediately without an interval.
  • If a session is connected within reconnection attempts defined by the Engine configuration, no error will be reported by the scheduler.
  • If a session is being retried to connect within reconnection attempts and logout time is reached, the scheduler will stop trying to connect the session, and no error will be reported.
  • If a session remains disconnected after all the attempts, the OnixS::FIX::Scheduling::SessionSchedulerListener::onError member will be invoked.
  • Once the OnixS::FIX::Scheduling::SessionSchedulerListener::onError member is invoked by the scheduler, all attempts to logon disconnected session will be suspended until the next activity (logon) time.

Handling Scheduling Warnings and Errors

Scheduler exposes the OnixS::FIX::Scheduling::SessionSchedulerListener class to get notified listeners about errors in the session scheduling. OnixS::FIX::Scheduling::SessionSchedulerListener::onError is not linked with session errors. Scheduler raises notifications only about scheduling-related errors like inability to connect a session within the specified amount of time.

Note
Once OnixS::FIX::Scheduling::SessionSchedulerListener::onError is called by the scheduler, all attempts to logon the disconnected session will be suspended till the next activity (logon) time.

OnixS::FIX::Scheduling::SessionSchedulerListener::onWarning member is called by Scheduler to provide its users with more information about scheduling flow. This kind of information is usually related to non-critical errors that occur during the scheduling of the session.

Note
In case of failure at logon, scheduler will call the OnixS::FIX::Scheduling::SessionSchedulerListener::onWarning member and will try to perform logon again according to the settings from the Engine configuration (Reconnect.Attempts and Reconnect.Interval values). Once all attempts are performed and session remains disconnected, Scheduler will invoke the OnixS::FIX::Scheduling::SessionSchedulerListener::onError member and will stop all subsequent attempts to bring a session to the connected state until the next logon time.

Example

using namespace std;
using namespace OnixS::FIX;
using namespace OnixS::FIX::Scheduling;
namespace
{
class MySessionListener : public ISessionListener
{
public:
void onInboundApplicationMsg (Message&, Session*) ONIXS_FIXENGINE_OVERRIDE {}
};
};
struct SchedulingTimeSpan
{
class Seconds
{
public:
Seconds (int span)
: span_ (span)
{
}
int span() const
{
return span_;
}
private:
int span_;
};
};
TimeOfDay operator + (TimeOfDay time, SchedulingTimeSpan::Seconds seconds)
{
const int SecondsPerMinute = 60;
const int MinutesPerHour = 60;
const int SecondsPerHour = SecondsPerMinute * MinutesPerHour;
int sinceMidnight = time.sinceMidnight() + seconds.span();
return TimeOfDay (
sinceMidnight / SecondsPerHour,
(sinceMidnight / SecondsPerMinute) % MinutesPerHour,
sinceMidnight % SecondsPerMinute);
}
class SessionStateChangeTracer : public ISessionListener
{
void onStateChange (SessionState::Enum newState, SessionState::Enum, Session* session) ONIXS_FIXENGINE_OVERRIDE
{
cout << static_cast<const string&> (*session) << " changed its state to " << SessionState::toString (newState) << '.' << endl;
}
void onInboundApplicationMsg (Message&, Session*) ONIXS_FIXENGINE_OVERRIDE
{
;
}
};
class SchedulingIssueDetector : public SessionSchedulerListener
{
public:
SchedulingIssueDetector()
{}
~SchedulingIssueDetector()
{}
void onLoggingOut (const SessionScheduler&, Session*, bool* /*allowLogout*/) ONIXS_FIXENGINE_OVERRIDE
{}
void onInitiatorConnecting(const SessionScheduler &, Session *, const Counterparty & /*counterparty*/) ONIXS_FIXENGINE_OVERRIDE
{}
void onWarning (const SessionScheduler&, Session* session, const std::string& warningReason) ONIXS_FIXENGINE_OVERRIDE
{
cout << "Scheduler reported a warning for the session " << static_cast<const string&> (*session) << ": " << warningReason;
}
void onError (const SessionScheduler&, Session* session, const std::string& errorReason) ONIXS_FIXENGINE_OVERRIDE
{
cout << "Error occurred while scheduling session " << static_cast<const string&> (*session) << ": " << errorReason;
}
};
class Sample
{
public:
Sample()
{
representYourself();
initializeFixEngine();
constructSessions();
constructScheduler();
}
~Sample()
{
initiator_->shutdown();
initiator_.reset();
acceptor_->shutdown();
acceptor_.reset();
scheduler_.reset();
Engine::shutdown();
}
void run()
{
acceptor_->resetLocalSequenceNumbers();
initiator_->resetLocalSequenceNumbers();
acceptor_->logonAsAcceptor();
cout << "Scheduling Initiator session " << static_cast<const string&> (*initiator_) << " for automatic connection." << endl;
SessionSchedule initiatorSchedule = constructShortTimeActivitySchedule();
InitiatorConnectionSettings initiatorConnectivity ("localhost", sessionPort() );
scheduler_->add (initiator_.get(), initiatorSchedule, initiatorConnectivity);
cout << "Waiting for activity on scheduled session " << static_cast<const string&> (*initiator_) << '.' << endl << endl;
// Should sleep for a while to let Scheduler connect Initiator session.
OnixS::Threading::ThisThread::sleep (1000 * sessionActivityTimeInSeconds() );
waitUntilLogout (initiator_.get() );
cout << endl << "Removing Initiator session " << static_cast<const string&> (*initiator_) << " from scheduling service." << endl;
// Session had to 'pulse' connection till this time, so scheduling can be destroyed.
scheduler_->remove (initiator_.get() );
// Clean-up.
acceptor_->logout();
waitUntilLogout (acceptor_.get() );
}
void useConfigurationFile()
{
initiator_->resetLocalSequenceNumbers();
SessionSchedulerOptions schedulerOptions;
schedulerOptions.configurationFile ("SchedulerConfiguration.xml");
SessionScheduler scheduler (schedulerOptions);
scheduler.add (initiator_.get(), "ScheduleId", "ConnectionId");
OnixS::Threading::ThisThread::sleep (1000 * sessionActivityTimeInSeconds() );
scheduler_->remove (initiator_.get() );
}
private:
MySessionListener acceptorListener_;
SessionStateChangeTracer initiatorStateChangeTracer_;
SchedulingIssueDetector schedulingIssueDetector_;
void constructScheduler()
{
SessionSchedulerOptions schedulerOptions;
schedulerOptions.eventListener (&schedulingIssueDetector_);
scheduler_.reset (new SessionScheduler (schedulerOptions) );
}
void constructSessions()
{
acceptor_.reset (new Session ( acceptorCompId(), initiatorCompId(), protocolVersion(), &acceptorListener_) );
initiator_.reset ( new Session (initiatorCompId(), acceptorCompId(), protocolVersion(), &initiatorStateChangeTracer_) );
}
static SessionSchedule constructShortTimeActivitySchedule()
{
TimeOfDay now = TimeOfDay::now();
TimeOfDay logonTime = now + SchedulingTimeSpan::Seconds (5);
TimeOfDay logoutTime = logonTime + SchedulingTimeSpan::Seconds (sessionActivityTimeInSeconds() );
return SessionSchedule (
DayOfWeek::Monday,
DayOfWeek::Sunday,
logonTime,
logoutTime,
SessionDuration::Day,
SequenceNumberResetPolicy::Never);
}
static void waitUntilLogout (Session* session)
{
const unsigned oneSecondPause = 1000;
while (session->state() != SessionState::Disconnected)
}
static void initializeFixEngine()
{
EngineSettings settings;
settings.licenseStore ("../../license")
.listenPort (sessionPort() );
Engine::init (settings);
}
static string initiatorCompId()
{
return "Initiator";
}
static string acceptorCompId()
{
return "Acceptor";
}
static ProtocolVersion::Enum protocolVersion()
{
return ProtocolVersion::FIX_42;
}
static int sessionPort()
{
return 4500;
}
static int sessionActivityTimeInSeconds()
{
return 30;
}
static void representYourself()
{
cout << "OnixS C++ FIX Engine Session Scheduling Sample." << endl << endl;
}
};