ITQuants blog

Fusion Capital Sophis v7: how to filter calculations of native instruments on F9?

Mar 8

Written by:
3/8/2016 6:20 PM  RssIcon

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.

Tags:
Categories: Sophis, C++

Search blog