Fusion Capital Sophis v7: how to filter calculations of native instruments on F9?
Mar
8
Written by:
3/8/2016 6:20 PM
Testing recently the calculations of some instruments (Convertible bonds) on the calculation servers, I've discovered that very old instruments which are not anymore in position were sent to calculation servers. By the way, these instruments are not valid too, and trying to calculate them today will generate some check error messages. These instruments were stored in position in some folios several years ago (trade date far away from the well-known REPORTING.DATE_DEB date), but are still loaded in memory and sent to calculation servers. The problem does not appear when calculating the folio locally, only when calculated by calculation servers, abd the whole calculation of the folio is then rejected. The goal of this post is to propose a workaround that permits to calculate the folios which contain such instruments.
I've tried to implement several classes in order to filter the instruments. The first tentatives were done by trying to declare my own grid service using an implementation of CSRGridService. My code was not called, even when trying to replace the existing default grid service.
After several investigations, I finally found an interface whose implementation works fine : CSRExternalCalculator. This interface contains several methods to implement : GetName, CreatePortfolioCalculation and CreateScenarioCalculation. The implementation can be registered using the singleton gExternalCalculators which list several calculators, in the UNIVERSAL_MAIN entry point for example. CreatePortfolioCalculation and CreateScenarioCalculation method give access to several parameters:
- the list of splitted steps, given by the calculation service, whose names correspond to instrument identifiers,
- the list of managed steps, that will be managed by our implementation,
- a listener, in order to notify the service that calculations are completed or cancelled.
In order to manage instruments which are expired, I've thus declared the following class:
class
ExpiryCalculator :
public
CSRExternalCalculator
{
public
:
ExpiryCalculator() {};
virtual
~ExpiryCalculator()
{
}
virtual
_STL::string GetName()
const
{
return
"ExpiryCalculator"
; }
virtual
CSRExternalCalculation * CreatePortfolioCalculation(
const
_STL::set<_STL::string> & steps,
_STL::set<_STL::string> & managedSteps,
CSRExternalCalculationListener & listener)
{
DummyCalculation* _result =
new
DummyCalculation(
this
,listener);
addSteps(_result,steps,managedSteps);
return
_result;
}
virtual
CSRExternalCalculation * CreateScenarioCalculation(
sophis::scenario::CSRScenario & scenario,
const
_STL::set<_STL::string> & steps,
_STL::set<_STL::string> & managedSteps,
CSRExternalCalculationListener & listener)
{
DummyCalculation* _result =
new
DummyCalculation(
this
,listener);
addSteps(_result,steps,managedSteps);
return
_result;
}
protected
:
void
addSteps(DummyCalculation* calculation,
const
_STL::set<_STL::string> & steps,
_STL::set<_STL::string> & managedSteps)
{
for
(auto iter = steps.begin(); iter!=steps.end(); iter++)
{
if
(iter->length()>1 && (*iter)[0]==
'I'
)
{
std::string sSicovam = iter->substr(1);
long
sicovam =
atol
(sSicovam.c_str());
const
CSRInstrument* instrument = gApplicationContext->GetCSRInstrument(sicovam);
if
(instrument && instrument->GetExpiry()!=0 && instrument->GetExpiry()GetDate())
{
managedSteps.insert(*iter);
calculation->addStep(*iter);
}
}
}
}
};
The dummy calculation does nothing except indicating that the computation is completed. This is done by implementing the CSRExternalCalculation interface as follow:
class
DummyCalculation :
public
CSRExternalCalculation
{
public
:
DummyCalculation(CSRExternalCalculator* calculator, CSRExternalCalculationListener& listener)
: m_calculator(calculator),
m_listener(listener)
{
}
virtual
~DummyCalculation()
{
}
virtual
CSRExternalCalculator & GetCalculator()
const
{
return
*m_calculator;
}
virtual
void
GetSteps(_STL::map<_STL::string, SSExternalStepData> & steps)
const
{
}
virtual
void
Start()
{
for
(
int
i=0;i
{
std::auto_ptr archive(CSRArchive::CreateInstance());
m_listener.OnExternalStepComputed(*
this
,m_steps[i],archive);
}
}
virtual
void
Cancel()
{
}
virtual
void
WaitForCompletion()
{
}
inline
void
addStep(
const
std::string& step) { m_steps.push_back(step); }
protected
:
std::vector m_steps;
mutable
CSRExternalCalculator* m_calculator;
CSRExternalCalculationListener& m_listener;
};
In the entry point method, the calculator is declared as follow :
gExternalCalculators.insert(gExternalCalculators.begin(),
new
ExpiryCalculator());
By the way, it permits to increase performance on the calculation servers, since invalid results won't be serialized.