MNP01/decider.h
2018-03-18 21:31:48 +01:00

141 lines
3.3 KiB
C++

#ifndef DECIDER_H_
#define DECIDER_H_
#include "helpers.h"
#include "network.h"
#include <iterator>
#include <iostream>
class decider {
public:
double start_money;
unsigned start_stock;
virtual int decide(double price, double money, unsigned stock) = 0;
virtual void reset(double price) = 0;
virtual ~decider() { }
};
class macd_decider {
private:
std::size_t limit;
protected:
buffer<double> prices;
buffer<double> macd;
buffer<double> signal;
public:
macd_decider(std::size_t limit = 1000);
virtual void process(double price);
virtual void reset(double price);
};
template <int p, int m, int s, int r, int ...layers>
class neural_decider : public decider, macd_decider {
public:
using network_t = network<double, p+m+s+r, layers..., 2+r>;
using self_t = neural_decider<p, m, s, r, layers...>;
network_t network;
vector<double, r> feedback;
neural_decider() : network(), macd_decider() { }
neural_decider(typename network_t::normalizer_t normalizer)
: network(normalizer), macd_decider() { }
virtual int decide(double price, double money, unsigned stock)
{
process(price);
auto input = prepare(money, stock);
auto result = network.evaluate(input);
double buy = result.get(0, 0);
double sell = result.get(1, 0);
double amount = buy - sell;
amount -= sign(amount) * .5;
for (int i = 0; i < r; i++) {
feedback.set(i, 0, result.get(i + 2, 0));
}
return abs(buy - sell) <= .5 ? 0 : amount * start_stock;
}
std::ostream& save(std::ostream& stream) {
network.save(stream);
return stream;
}
void load(std::istream& stream) {
network.load(stream);
}
virtual void reset(double price) override
{
macd_decider::reset(price);
}
virtual ~neural_decider() { }
self_t combine(self_t smth, typename network_t::combiner_t combiner = [](const double& a, const double& b) { return .35*a + .65*b; })
{
self_t result;
result.network = network.combine(smth.network, combiner);
result.start_money = start_money;
result.start_stock = start_stock;
return result;
}
self_t mutate(typename network_t::normalizer_t mutator)
{
self_t result;
result.network = network.mutate(mutator);
result.start_money = start_money;
result.start_stock = start_stock;
return result;
}
private:
typename network_t::input prepare(double money, unsigned stock)
{
vector<double, 2> state = {
{ (money - start_money) / start_money },
{ (double)stock / this->start_stock }
};
vector<double, p> prices;
vector<double, m+s> tech;
// prices are normalized as percent change value
for (int j = 0; j < p; j++) {
auto diff = this->prices[j] - this->prices[j+1];
prices.set(j, 0, diff / this->prices[j+1]);
}
int i = 0;
for (int j = 0; j < m; j++, i++) {
tech.set(i, 0, macd[j]);
}
for (int j = 0; j < s; j++, i++) {
tech.set(i, 0, signal[j]);
}
// analytic data is normalized in its own domain
tech = normalize(tech);
return concat(concat(prices, tech), feedback);
}
};
#endif