OnixS C++ FIX Engine  4.12.0
API Documentation
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:

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_;
};
};
{
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,
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;
}
};