There are several ways to design a mechanism to launch algos within your process. One such approach is to first create a pure virtual base class that defines the semantics for managing the algo. For example:
#pragma once
#include <sdkalgo.h>
class BaseStrategy
{
public:
BaseStrategy() {};
virtual ~BaseStrategy() {};
// handle the requests from the TT SDK
virtual bool Start(ttsdk::SDKAlgoPtr algoOrder, ttsdk::SDKAlgoRequestPtr req) = 0;
virtual void Update(ttsdk::SDKAlgoRequestPtr req) = 0;
virtual void Stop(ttsdk::SDKAlgoRequestPtr req) = 0;
virtual void Pause(ttsdk::SDKAlgoRequestPtr req) = 0;
virtual void Resume(ttsdk::SDKAlgoRequestPtr req) = 0;
};
Each algo would then be defined by a class which derives from and provides implementation for:
For Example:
class TrailingCrossStrategy : public BaseStrategy,
public ttsdk::IOrderEventHandler,
public ttsdk::IPriceEventHandler
{
public:
TrailingCrossStrategy(SDKAlgoManager& mgr)
{ // … }
virtual ~TrailingCrossStrategy()
{ // … }
// from BaseStrategy
virtual bool Start(ttsdk::SDKAlgoPtr algoOrder, ttsdk::SDKAlgoRequestPtr req)
{ // … }
virtual void Update(ttsdk::SDKAlgoRequestPtr req)
{ // … }
virtual void Stop(ttsdk::SDKAlgoRequestPtr req)
{ // … }
virtual void Pause(ttsdk::SDKAlgoRequestPtr req)
{ // … }
virtual void Resume(ttsdk::SDKAlgoRequestPtr req)
{ // … }
// from ttsdk::IPriceEventHandler
virtual void OnUnsubscribed(const uint64_t subId)
{ // … }
virtual void OnDisconnect(const uint64_t subId, const ttsdk::InstrumentPtr&, const ttsdk::PriceEventType)
{ // … }
virtual void OnPriceUpdate(const uint64_t, const ttsdk::InstrumentPtr&, const ttsdk::PriceSnap& snap)
{ // … }
virtual void OnError(const uint64_t subId, const ttsdk::InstrumentPtr& instrument, const ttsdk::SubscriptionError code, const char* error)
{ // … }
// from ttsdk::IOrderEventHandler
virtual void OnUnsubscribed(const char*)
{ // … }
virtual void OnExecutionReport(ttsdk::OrderPtr order, ttsdk::ExecutionReportPtr execRpt)
{ // … }
virtual void OnReject(ttsdk::OrderPtr order, ttsdk::RejectResponsePtr rejResp)
{ // … }
virtual void OnSendFailed(ttsdk::OrderPtr order, const ttsdk::OrderProfile& profile, const ttsdk::IOrderEventHandler::SendCode code)
{ // … }
};
class SDKAlgoManager : public ttsdk::ISDKAlgoManager
{
// …
protected:
mutable std::mutex mutexStrategies_;
std::map< std::string, std::shared_ptr > strategies_;
};
The SDKAlgoManager::OnStartRequest() method would then be written as follows.
void SDKAlgoManager::OnStartRequest(ttsdk::SDKAlgoPtr algoOrder,
ttsdk::SDKAlgoRequestPtr req)
{
auto algo = algoOrder->GetAlgoDefinition();
if (strncmp(algo->GetName(), "TrailingXSDKAlgo", sizeof(algo->GetName())) == 0)
{
std::shared_ptr strategy(new TrailingCrossStrategy(*this));
if (strategy->Start(algoOrder, req))
{
std::unique_lock lock(mutexStrategies_);
strategies_.insert(std::make_pair(req->GetOrderId(), strategy));
}
}
else if (strncmp(algo->GetName(), "StrikerAlgo", sizeof(algo->GetName())) == 0)
{
std::shared_ptr strategy(new StrikerAlgo(*this));
if (strategy>Start(algoOrder, req))
{
std::unique_lock lock(mutexStrategies_);
strategies_.insert(std::make_pair(req->GetOrderId(), strategy));
}
}
else
{
// …
}
}
Once an algo has been started, external update messages are forwarded to it from the TT UI as follows:
void SDKAlgoManager::OnUpdateRequest(ttsdk::SDKAlgoPtr algoOrder,
ttsdk::SDKAlgoRequestPtr req)
{
std::shared_ptr strategy(nullptr);
{
std::unique_lock lock(this->mutexStrategies_);
auto iter = strategies_.find(algoOrder->GetOrderId());
if (iter != strategies_.end())
{
strategy = iter->second;
}
}
if (strategy)
{
return strategy->Update(req);
}
}
Once an algo has been started, external stop messages are forwarded to it from the TT UI as follows:
void SDKAlgoManager::OnStopRequest(ttsdk::SDKAlgoPtr algoOrder,
ttsdk::SDKAlgoRequestPtr req)
{
std::shared_ptr strategy(nullptr);
{
std::unique_lock lock(this->mutexStrategies_);
auto iter = strategies_.find(algoOrder->GetOrderId());
if (iter != strategies_.end())
{
strategy = iter->second;
}
}
if (strategy)
{
return strategy->Stop(req);
}
}
Once an algo has been started, external pause messages are forwarded to it from the TT UI as follows:
void SDKAlgoManager::OnPauseRequest(ttsdk::SDKAlgoPtr algoOrder,
ttsdk::SDKAlgoRequestPtr req)
{
std::shared_ptr strategy(nullptr);
{
std::unique_lock lock(this->mutexStrategies_);
auto iter = strategies_.find(algoOrder->GetOrderId());
if (iter != strategies_.end())
{
strategy = iter->second;
}
}
if (strategy)
{
return strategy->Pause(req);
}
}
Once an algo has been started, external resume messages are forwarded to it from the TT UI as follows:
void SDKAlgoManager::OnResumeRequest(ttsdk::SDKAlgoPtr algoOrder,
ttsdk::SDKAlgoRequestPtr req)
{
std::shared_ptr strategy(nullptr);
{
std::unique_lock lock(this->mutexStrategies_);
auto iter = strategies_.find(algoOrder->GetOrderId());
if (iter != strategies_.end())
{
strategy = iter->second;
}
}
if (strategy)
{
return strategy->Resume(req);
}
}