我正在开发一个小型交易机器人作为练习。他日复一日地接受股票价格(表示为迭代)。
这是我的Trade
课程的样子:
class Trade
{
private:
int capital_;
int days_; // Total number of days of available stock prices
int daysInTrading_; // Increments as days go by.
std::list<int> stockPrices_; // Contains stock prices day after day.
int currentStock_; // Current stock we are dealing with.
int lastStock_; // Last stock dealt with
int trend_; // Either {-1; 0; 1} depending on the trend.
int numOfStocks_; // Number of stocks in our possession
int EMA_; // Exponential Moving Average
int lastEMA_; // Last EMA
public:
// functions
};
从我最近的两个属性中可以看出,我希望将指数移动平均线作为趋势跟踪算法的一部分来实现。
但我认为我不太明白如何实施它;这是我的calcEMA
函数,它只计算EMA
:
int Trade::calcEMA()
{
return ((this->currentStock_ - this->lastEMA_
* (2/(this->daysInTrading_ + 1)))
+ this->lastEMA_);
}
但是当我的股票价值(在文件中传递)是这样的时候:
1000, 1100, 1200, 1300, 1400, 1500, 1400, 1300, 1200, 1100, 1000
为了确保我的EMA有意义,而且......它没有!
我在哪里操作错了?
另外,如果我第一次拨打lastEMA
,我应该给calcEMA
一个什么价值?
答案 0 :(得分:1)
正如您所注意到的那样,操作是错误的。
免责声明 我从wikipedia获得了此算法,因此可能不准确。 Here(第3页)可能更好,但我无法判断,我从未使用过这些算法,因此不知道我在说什么:)
c(EMA) = y(EMA) + a * (c(price) - y(EMA))
c(EMA)
是当前的EMAy(EMA)
是以前的EMAa
是介于0和1之间的“随机”值c(price)
是当前价格
但你做了几乎相同的事情:
c(EMA) = (c(price) - y(EMA) * b) + y(EMA)
我不知道你为什么做2 / daysInTrading_ + 1
,但这并不总是0到1之间的值(实际上,它甚至可能大部分时间都是0,因为这些都是整数)。 / p>
您将括号放在错误的位置(b
之后,而不是y(EMA)
之后)。
所以操作现在看起来像这样:
<强> lastEMA_ + 0.5 * (currentStock_ - lastEMA_)
强>
对于第一个lastEMA_
,根据Wikipedia:
S 1 未定义。 S 1 可以通过多种不同的方式初始化,最常见的是通过设置S 11 [列表中的第一个元素],尽管其他技术存在,例如将S 1 设置为前4或5个观测值的平均值。
S 1 初始化对合成移动平均线影响的重要性取决于α;较小的α值使得S 1 的选择比较大的α值相对更重要,因为较高的α会使较早的观察值更快地折现。
答案 1 :(得分:1)
我相信你在calcEMA函数中遗漏了一个括号。它有助于将表达式分解为具有临时变量的较小表达式,以保存中间结果。
int Trade::calcEMA()
{
auto mult = 2/(timePeriod_ + 1);
auto rslt = (currentStock_ - lastEMA_) * mult + lastEMA_;
return rslt;
}
另外,正如PaulMcKenzie在评论中指出的那样,你正在使用整数进行浮点数学运算。您应该考虑使用浮点数或双精度数来避免截断。
像您这样的EMA定义了一段时间,上面称为timePeriod_。虽然daysInTrading_小于或等于timePeriod_,但lastEMA_应该设置为正常平均值。一旦daysInTrading_大于timePeriod_,您就可以开始调用calcEMA函数并正确初始化lastEMA_。请记住在每次调用calcEMA后更新lastEMA_。这是一个可能的实现:
#include <vector>
#include <list>
#include <iostream>
// calculate a moving average
double calcMA(double previousAverage, unsigned int previousNumDays, double newStock)
{
auto rslt = previousNumDays * previousAverage + newStock;
return rslt / (previousNumDays + 1.0);
}
// calculate an exponential moving average
double calcEMA(double previousAverage, int timePeriod, double newStock)
{
auto mult = 2.0 / (timePeriod + 1.0);
auto rslt = (newStock - previousAverage) * mult + previousAverage;
return rslt;
}
class Trade
{
unsigned int timePeriod_ = 5;
double lastMA_ = 0.0;
std::list<double> stockPrices_;
public:
void addStock(double newStock)
{
stockPrices_.push_back(newStock);
auto num_days = stockPrices_.size();
if (num_days <= timePeriod_)
lastMA_ = calcMA(lastMA_, num_days - 1, newStock);
else
lastMA_ = calcEMA(lastMA_, num_days - 1, newStock);
}
double getAverage() const { return lastMA_; }
};
int main()
{
std::vector<double> stocks =
{1000, 1100, 1200, 1300, 1400, 1500, 1400, 1300, 1200, 1100, 1000};
Trade trade;
for (auto stock : stocks)
trade.addStock(stock);
std::cout << "Average: " << trade.getAverage() << std::endl;
return 0;
}
答案 2 :(得分:1)
通常有两种可接受的EMA形式。
传统:
m = 2/(1+n) // where n >= 1
EMA = m * currentPrice + (1-m) * previousEMA
rf the Wilder:
m = 1/n // where n >= 1
EMA Wilder = m * currentPrice + (1-m) * previousEMA