145 lines
3.5 KiB
C++
145 lines
3.5 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;
|
|
|
|
unsigned count = 0;
|
|
public:
|
|
double start_price;
|
|
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+2, 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);
|
|
|
|
if (count < 35) return 0;
|
|
|
|
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 = {
|
|
{ (prices[0] * stock + money) / (start_money + start_stock * start_price) },
|
|
{ (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), concat(feedback, state));
|
|
}
|
|
};
|
|
|
|
#endif
|