【发布时间】:2020-05-21 09:00:28
【问题描述】:
编辑:已发现问题是 Wrapper 类在传递到 MCEngine 函数和下面所示的 SimulationEngine 类时正在创建 BSCallFunction 的副本。考虑到这一点,我仍然需要弄清楚如何让程序做我想做的事情,如问题中所述。评论部分包含迄今为止的发现。
class SimulationEngine
{
public:
SimulationEngine(double horizon, const Wrapper<valuationFunction>& theFunction_, RiskFactor simulatedRiskFactor);
virtual void DoOnePath(double vol, double normvariate) = 0;
virtual SimulationEngine* clone() const = 0;
const double GetHorizon();
Wrapper<valuationFunction>& GetFunction();
RiskFactor simulatedRiskFactor;
protected:
double horizon;
Wrapper<valuationFunction> theFunction;
};
在我的主类中,我正在创建这个对象:
BSCallFunction ThisBsCall(nominal, S0, r, d, impvol, TTM, Strike);
我将其传递给两个类(派生自同一个基类),这将改变它的一些值(如 S0 和 r)。
OneStepBSEngine BSSimulation(timeHorizon, zeroDrift, ThisBsCall, RiskFactor::equity);
OneStepBrownianMotionEngine ShortRateSimulation(timeHorizon, zeroDrift, ThisBsCall, RiskFactor::interest_rate);
我希望这两个类都更改同一个对象的值,以便最终得到一个具有不同 r 和 S0 的 ThisBsCall。
类的结构如下:
class OneStepBrownianMotionEngine : public SimulationEngine
{
public:
OneStepBrownianMotionEngine(double horizon_, double drift_,const Wrapper<valuationFunction>& theFunction_, RiskFactor simulatedRiskFactor_);
virtual SimulationEngine* clone() const;
void DoOnePath(double vol, double normvariate);
private:
double drift;
};
OneStepBrownianMotionEngine::OneStepBrownianMotionEngine(double horizon_, double drift_,const Wrapper<valuationFunction>& theFunction_, RiskFactor simulatedRiskFactor_) : SimulationEngine(horizon_, theFunction_, simulatedRiskFactor_), drift(drift_)
{
}
我通过 const 引用传递“ThisBsCall”对象。
回到我的主类,然后我将创建对象 MCEngine 并使用将使用上面的 Engine 类更改 r 和 S0 的值的函数,Enginevector 只是两个 Engine 类的向量:
MCEngine VAREngine(EngineVector, covmat);
VAREngine.DoSimulation(gathererCombiner, NumberOfPaths);
我也像这样通过 const 引用传递 enginevector:
MCEngine(const std::vector<Wrapper<SimulationEngine>>& EngineVector, std::vector<std::vector<double>> covMatrix_);
我不确定这是否重要,但使用的构造函数和函数在 MCEngine 类中如下所示:
MCEngine::MCEngine(const std::vector< Wrapper<SimulationEngine>>& EngineVector_, std::vector<std::vector<double>> covMatrix_)
: cholMatrix(Cholesky_Decomposition(covMatrix_)), EngineVector(EngineVector_), V(0)
{
}
void MCEngine::DoSimulation(StatisticsMC& TheGatherer, unsigned long NumberOfPaths)
{
UpdateTTM();
double thisPortfolioValue;
for (unsigned long i = 0; i < NumberOfPaths; ++i)
{
std::vector<Wrapper<SimulationEngine>> tmpEngineVector(EngineVector); //save the origianl EngineVector to use on next path
//create vector of correlated normal variats with cholezky decompositon
MJArray corrNormVariates(cholMatrix.size());
corrNormVariates = 0;
MJArray NormVariates(cholMatrix.size());
for (unsigned long i = 0; i < cholMatrix.size(); i++)
{
NormVariates[i] = GetOneGaussianByBoxMuller();
for (unsigned long j = 0; j < cholMatrix[i].size(); j++) {
corrNormVariates[i] += cholMatrix[i][j] * NormVariates[j];
}
corrNormVariates[i] /= cholMatrix[i][i]; //normalize the random variates
}
//use each one for simulation with spotvector/volvector
for (unsigned long j = 0; j < EngineVector.size(); ++j)
{
EngineVector[j]->DoOnePath(cholMatrix[j][j], corrNormVariates[j]); //updates the riskfactors for the positions
}
ValuePortfolio();
thisPortfolioValue = GetPortfolioValue();
TheGatherer.DumpOneResult(thisPortfolioValue);
EngineVector = tmpEngineVector;
}
}
现在我的问题是,当我查看 2 个 BSCallFunction 对象(我希望它们是相同的 ThisBsCall)时,它们的 S0 和 r 具有不同的值,所以似乎在某些时候我复制了对象并更改了r 或 S0 这个副本而不是原来的然后返回结果。是否有可能从我发布的内容(或关于我可能做错的一般建议)中看到这可能发生在哪里?如果有帮助,我可以发布更多代码。
编辑:包装类以防万一这可能是导致问题的原因:
#ifndef WRAPPER_H
#define WRAPPER_H
template< class T>
class Wrapper
{
public:
Wrapper()
{
DataPtr = 0;
}
Wrapper(const T& inner)
{
DataPtr = inner.clone();
}
Wrapper(T* DataPtr_)
{
DataPtr = DataPtr_;
}
~Wrapper()
{
if (DataPtr != 0)
delete DataPtr;
}
Wrapper(const Wrapper<T>& original)
{
if (original.DataPtr != 0)
DataPtr = original.DataPtr->clone();
else
DataPtr = 0;
}
Wrapper& operator=(const Wrapper<T>& original)
{
if (this != &original)
{
T* newPtr = (original.DataPtr != 0) ?
original.DataPtr->clone() : 0;
if (DataPtr != 0)
delete DataPtr;
DataPtr = newPtr;
}
return *this;
}
T& operator*()
{
return *DataPtr;
}
const T& operator*() const
{
return *DataPtr;
}
const T* const operator->() const
{
return DataPtr;
}
T* operator->()
{
return DataPtr;
}
private:
T* DataPtr;
};
#endif
【问题讨论】:
-
看起来您传递的是
const Wrapper<BSCallFunction> &而不是const BSCallFunction &如果为每次调用构建一个临时对象,这可能解释了您所看到的差异。 -
你的意思是它可能是因为 Wrapper 类而构建的吗?我和班级一起编辑了帖子,你能看看是不是这样?
-
包装类正在克隆对象。见
Wrapper(const T& inner) -
有简单的解决方案吗?我自己没有编写 Wrapper 类,所以我不确定它是如何工作的,它似乎只是为了满足我的目的
-
如果包装类使用指针构造函数,它不会复制而是使用原始对象。
OneStepBSEngine BSSimulation(timeHorizon, zeroDrift, &ThisBsCall, RiskFactor::equity);老实说,在尝试改变之前,你需要了解这个类在做什么。
标签: c++ reference const-reference