uczenie i testowanie
This commit is contained in:
parent
72fb76e8c2
commit
7537f02177
2
common.h
2
common.h
@ -1,4 +1,4 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "decider.h"
|
#include "decider.h"
|
||||||
|
|
||||||
using current_decider = neural_decider<24, 16, 16, 32, 16>;
|
using current_decider = neural_decider<24, 12, 12, 32, 16>;
|
||||||
|
@ -11,9 +11,9 @@ void macd_decider::process(double price)
|
|||||||
signal.add(ema<double>(macd.begin(), macd.begin() + 9));
|
signal.add(ema<double>(macd.begin(), macd.begin() + 9));
|
||||||
}
|
}
|
||||||
|
|
||||||
void macd_decider::reset()
|
void macd_decider::reset(double price)
|
||||||
{
|
{
|
||||||
prices = buffer<double>(limit, .0);
|
prices = buffer<double>(limit, price);
|
||||||
signal = buffer<double>(limit, .0);
|
signal = buffer<double>(limit, .0);
|
||||||
macd = buffer<double>(limit, .0);
|
macd = buffer<double>(limit, .0);
|
||||||
}
|
}
|
||||||
|
29
decider.h
29
decider.h
@ -6,6 +6,10 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T sign(const T& value) {
|
||||||
|
return value < 0 ? -1 : (value > 0 ? value : 0);
|
||||||
|
}
|
||||||
|
|
||||||
class decider {
|
class decider {
|
||||||
public:
|
public:
|
||||||
@ -13,7 +17,7 @@ public:
|
|||||||
unsigned start_stock;
|
unsigned start_stock;
|
||||||
|
|
||||||
virtual int decide(double price, double money, unsigned stock) = 0;
|
virtual int decide(double price, double money, unsigned stock) = 0;
|
||||||
virtual void reset() = 0;
|
virtual void reset(double price) = 0;
|
||||||
|
|
||||||
virtual ~decider() { }
|
virtual ~decider() { }
|
||||||
};
|
};
|
||||||
@ -31,7 +35,7 @@ public:
|
|||||||
macd_decider(std::size_t limit = 1000);
|
macd_decider(std::size_t limit = 1000);
|
||||||
|
|
||||||
virtual void process(double price);
|
virtual void process(double price);
|
||||||
virtual void reset();
|
virtual void reset(double price);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int p, int m, int s, int ...layers>
|
template <int p, int m, int s, int ...layers>
|
||||||
@ -56,9 +60,10 @@ public:
|
|||||||
double buy = result.get(0, 0);
|
double buy = result.get(0, 0);
|
||||||
double sell = result.get(1, 0);
|
double sell = result.get(1, 0);
|
||||||
|
|
||||||
double amount = (buy - sell - .5)/1.5;
|
double amount = buy - sell;
|
||||||
|
amount -= sign(amount) * .5;
|
||||||
|
|
||||||
return abs(buy - sell) <= .5 ? 0 : amount * start_stock / 10;
|
return abs(buy - sell) <= .5 ? 0 : amount * start_stock;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& save(std::ostream& stream) {
|
std::ostream& save(std::ostream& stream) {
|
||||||
@ -71,9 +76,9 @@ public:
|
|||||||
network.load(stream);
|
network.load(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void reset() override
|
virtual void reset(double price) override
|
||||||
{
|
{
|
||||||
macd_decider::reset();
|
macd_decider::reset(price);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~neural_decider() { }
|
virtual ~neural_decider() { }
|
||||||
@ -88,6 +93,17 @@ public:
|
|||||||
|
|
||||||
return result;
|
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:
|
private:
|
||||||
typename network_t::input prepare(double money, unsigned stock)
|
typename network_t::input prepare(double money, unsigned stock)
|
||||||
{
|
{
|
||||||
@ -118,7 +134,6 @@ private:
|
|||||||
tech = normalize(tech);
|
tech = normalize(tech);
|
||||||
|
|
||||||
auto concated = concat(prices, tech);
|
auto concated = concat(prices, tech);
|
||||||
|
|
||||||
return concat(concated, state);
|
return concat(concated, state);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
31
matrix.h
31
matrix.h
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
template <typename T, int m, int n>
|
template <typename T, int m, int n>
|
||||||
@ -162,26 +163,45 @@ class matrix
|
|||||||
|
|
||||||
std::ostream& save(std::ostream& stream)
|
std::ostream& save(std::ostream& stream)
|
||||||
{
|
{
|
||||||
|
char start[2] = { char(0xDE), char(0xAD) };
|
||||||
|
char end[2] = { char(0xBE), char(0xEF) };
|
||||||
|
|
||||||
T temp;
|
T temp;
|
||||||
|
stream.write(start, 2);
|
||||||
for (int i = 0; i < m; ++i) {
|
for (int i = 0; i < m; ++i) {
|
||||||
for (int j = 0; j < n; j++) {
|
for (int j = 0; j < n; j++) {
|
||||||
temp = get(i, j);
|
temp = get(i, j);
|
||||||
stream.write(reinterpret_cast<char*>(&temp), sizeof(T));
|
stream.write((char*)(&temp), sizeof(T));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stream.write(end, 2);
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(std::istream& stream)
|
void load(std::istream& stream)
|
||||||
{
|
{
|
||||||
|
char buf[2];
|
||||||
|
|
||||||
|
stream.read(buf, 2);
|
||||||
|
if (buf[0] != char(0xDE) || buf[1] != char(0xAD)) {
|
||||||
|
std::cerr << "Bledny prefix" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
T temp;
|
T temp;
|
||||||
for (int i = 0; i < m; ++i) {
|
for (int i = 0; i < m; ++i) {
|
||||||
for (int j = 0; j < n; j++) {
|
for (int j = 0; j < n; j++) {
|
||||||
stream.read(reinterpret_cast<char*>(&temp), sizeof(T));
|
stream.read((char*)(&temp), sizeof(T));
|
||||||
set(i, j, temp);
|
set(i, j, temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream.read(buf, 2);
|
||||||
|
if (buf[0] != char(0xBE) || buf[1] != char(0xEF)) {
|
||||||
|
std::cerr << "Bledny suffix" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -206,7 +226,7 @@ vector<T, m+n> concat(const vector<T, n> &a, const vector<T, m> &b)
|
|||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
result.set(i, 0, a.get(i, 0));
|
result.set(i, 0, a.get(i, 0));
|
||||||
for (int i = 0; i < m; i++)
|
for (int i = 0; i < m; i++)
|
||||||
result.set(i+n, 0, a.get(i, 0));
|
result.set(i+n, 0, b.get(i, 0)); // YOU LIITLE FUCKING BASTARD
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -218,10 +238,11 @@ vector<T, n> normalize(const vector<T, n> &vec)
|
|||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
T temp = vec.get(i, 0);
|
T temp = vec.get(i, 0);
|
||||||
accumulator += temp * temp;
|
accumulator += abs(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
accumulator = sqrt(accumulator);
|
accumulator /= n;
|
||||||
|
|
||||||
std::function<T(const T&)> normalizer = [accumulator](const T& item) { return item / accumulator; };
|
std::function<T(const T&)> normalizer = [accumulator](const T& item) { return item / accumulator; };
|
||||||
return map(vec, normalizer);
|
return map(vec, normalizer);
|
||||||
}
|
}
|
||||||
|
65
network.h
65
network.h
@ -9,6 +9,7 @@ template <typename T, int in, int out>
|
|||||||
struct layer {
|
struct layer {
|
||||||
using filler_t = std::function<T(const int&, const int&)>;
|
using filler_t = std::function<T(const int&, const int&)>;
|
||||||
using combiner_t = std::function<T(const T&, const T&)>;
|
using combiner_t = std::function<T(const T&, const T&)>;
|
||||||
|
using mutator_t = std::function<T(const T&)>;
|
||||||
|
|
||||||
matrix<T, out, in> weights;
|
matrix<T, out, in> weights;
|
||||||
vector<T, out> bias;
|
vector<T, out> bias;
|
||||||
@ -45,6 +46,21 @@ struct layer {
|
|||||||
return combine(rhs, combiner, combiner);
|
return combine(rhs, combiner, combiner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layer<T, in, out> mutate(mutator_t weight_mutator, mutator_t bias_mutator)
|
||||||
|
{
|
||||||
|
layer<T, in, out> result;
|
||||||
|
|
||||||
|
result.weights = ::map(weights, weight_mutator);
|
||||||
|
result.bias = ::map(bias, bias_mutator);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer<T, in, out> mutate(const layer<T, in, out> &rhs, mutator_t mutator)
|
||||||
|
{
|
||||||
|
return mutate(mutator, mutator);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& save(std::ostream& stream) {
|
std::ostream& save(std::ostream& stream) {
|
||||||
weights.save(stream);
|
weights.save(stream);
|
||||||
bias.save(stream);
|
bias.save(stream);
|
||||||
@ -86,6 +102,7 @@ public:
|
|||||||
using filler_t = typename layer<T, in, out>::filler_t;
|
using filler_t = typename layer<T, in, out>::filler_t;
|
||||||
using combiner_t = typename layer<T, in, out>::combiner_t;
|
using combiner_t = typename layer<T, in, out>::combiner_t;
|
||||||
using normalizer_t = std::function<T(const T&)>;
|
using normalizer_t = std::function<T(const T&)>;
|
||||||
|
using mutator_t = std::function<T(const T&)>;
|
||||||
|
|
||||||
template <std::size_t N> using layer_type = typename layer_types<N, T, in, out>::type;
|
template <std::size_t N> using layer_type = typename layer_types<N, T, in, out>::type;
|
||||||
|
|
||||||
@ -114,7 +131,8 @@ public:
|
|||||||
current.fill(filler);
|
current.fill(filler);
|
||||||
}
|
}
|
||||||
|
|
||||||
self combine(self& rhs, combiner_t weight_combiner, combiner_t bias_combiner) {
|
self combine(self& rhs, combiner_t weight_combiner, combiner_t bias_combiner)
|
||||||
|
{
|
||||||
self result(normalizer);
|
self result(normalizer);
|
||||||
result.template get<0>() = get<0>().combine(rhs.template get<0>(), weight_combiner, bias_combiner);
|
result.template get<0>() = get<0>().combine(rhs.template get<0>(), weight_combiner, bias_combiner);
|
||||||
|
|
||||||
@ -126,6 +144,22 @@ public:
|
|||||||
return combine(rhs, combiner, combiner);
|
return combine(rhs, combiner, combiner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self mutate(mutator_t weight_mutator, mutator_t bias_mutator)
|
||||||
|
{
|
||||||
|
self result(normalizer);
|
||||||
|
result.template get<0>() = get<0>().mutate(
|
||||||
|
weight_mutator,
|
||||||
|
bias_mutator
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
self mutate(mutator_t mutator)
|
||||||
|
{
|
||||||
|
return mutate(mutator, mutator);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& save(std::ostream& stream)
|
std::ostream& save(std::ostream& stream)
|
||||||
{
|
{
|
||||||
current.save(stream);
|
current.save(stream);
|
||||||
@ -184,10 +218,15 @@ public:
|
|||||||
subnetwork.fill(weights, bias);
|
subnetwork.fill(weights, bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
self combine(self& rhs, typename base::combiner_t weight_combiner, typename base::combiner_t bias_combiner) {
|
self combine(self& rhs, typename base::combiner_t weight_combiner, typename base::combiner_t bias_combiner)
|
||||||
self result(normalizer);
|
{
|
||||||
|
self result((this->normalizer));
|
||||||
|
|
||||||
result.template get<0>() = get<0>().combine(rhs.template get<0>(), weight_combiner, bias_combiner);
|
result.template get<0>() = get<0>().combine(
|
||||||
|
rhs.template get<0>(),
|
||||||
|
weight_combiner,
|
||||||
|
bias_combiner
|
||||||
|
);
|
||||||
result.subnetwork = subnetwork.combine(rhs.subnetwork, weight_combiner, bias_combiner);
|
result.subnetwork = subnetwork.combine(rhs.subnetwork, weight_combiner, bias_combiner);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -198,6 +237,24 @@ public:
|
|||||||
return combine(rhs, combiner, combiner);
|
return combine(rhs, combiner, combiner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self mutate(typename base::mutator_t weight_mutator, typename base::mutator_t bias_mutator)
|
||||||
|
{
|
||||||
|
self result((this->normalizer));
|
||||||
|
|
||||||
|
result.template get<0>() = get<0>().mutate(
|
||||||
|
weight_mutator,
|
||||||
|
bias_mutator
|
||||||
|
);
|
||||||
|
result.subnetwork = subnetwork.mutate(weight_mutator, bias_mutator);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
self mutate(typename base::mutator_t mutator)
|
||||||
|
{
|
||||||
|
return mutate(mutator, mutator);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& save(std::ostream& stream)
|
std::ostream& save(std::ostream& stream)
|
||||||
{
|
{
|
||||||
base::save(stream);
|
base::save(stream);
|
||||||
|
37
tester.cpp
37
tester.cpp
@ -1,5 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <stdio.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@ -19,12 +20,15 @@ int main(int argc, const char* argv[])
|
|||||||
args(1) >> network;
|
args(1) >> network;
|
||||||
args(2) >> input;
|
args(2) >> input;
|
||||||
|
|
||||||
double money;
|
double money, start_money;
|
||||||
unsigned stock;
|
unsigned stock, start_stock;
|
||||||
|
|
||||||
args({"s", "stock"}, 1000) >> stock;
|
args({"s", "stock"}, 1000) >> stock;
|
||||||
args({"m", "money"}, 1000.) >> money;
|
args({"m", "money"}, 1000.) >> money;
|
||||||
|
|
||||||
|
start_money = money;
|
||||||
|
start_stock = stock;
|
||||||
|
|
||||||
std::function<double(const double&)> normalizer = [](const double& result) -> double { return erf(result); };
|
std::function<double(const double&)> normalizer = [](const double& result) -> double { return erf(result); };
|
||||||
current_decider decider(normalizer);
|
current_decider decider(normalizer);
|
||||||
|
|
||||||
@ -37,7 +41,11 @@ int main(int argc, const char* argv[])
|
|||||||
decider.start_money = money;
|
decider.start_money = money;
|
||||||
decider.start_stock = stock;
|
decider.start_stock = stock;
|
||||||
std::cout << "x,price,decsion,money,stock" << std::endl;
|
std::cout << "x,price,decsion,money,stock" << std::endl;
|
||||||
for (int i = 0; input_file >> price; i++) {
|
input_file >> price;
|
||||||
|
decider.reset(price);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
auto decision = decider.decide(price, money, stock);
|
auto decision = decider.decide(price, money, stock);
|
||||||
auto current = price * stock + money;
|
auto current = price * stock + money;
|
||||||
auto max_credit = std::max(current * 0.05, -1e4);
|
auto max_credit = std::max(current * 0.05, -1e4);
|
||||||
@ -51,15 +59,20 @@ int main(int argc, const char* argv[])
|
|||||||
money -= price * decision;
|
money -= price * decision;
|
||||||
stock += decision;
|
stock += decision;
|
||||||
|
|
||||||
/* std::cout */
|
std::cout
|
||||||
/* << i << "," */
|
<< ++i << ","
|
||||||
/* << price << "," */
|
<< price << ","
|
||||||
/* << decision << "," */
|
<< decision << ","
|
||||||
/* << money << "," */
|
<< money << ","
|
||||||
/* << stock */
|
<< stock
|
||||||
/* << std::endl; */
|
<< std::endl;
|
||||||
}
|
|
||||||
std::cout << "Koniec: " << money + stock*price;
|
|
||||||
|
} while(input_file >> price);
|
||||||
|
std::cout << "Koniec: "
|
||||||
|
<< money + stock*price << std::showpos << "("
|
||||||
|
<< (money + stock*price) / (start_money + start_stock*price)
|
||||||
|
<< ")";
|
||||||
/* decider.network.save(std::cout); */
|
/* decider.network.save(std::cout); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
trainer.h
35
trainer.h
@ -36,12 +36,10 @@ public:
|
|||||||
std::function<double(std::shared_ptr<trained<T>>, const dataset&, double, unsigned)> q;
|
std::function<double(std::shared_ptr<trained<T>>, const dataset&, double, unsigned)> q;
|
||||||
|
|
||||||
trainer(double money, unsigned stock, std::size_t n, std::function<T()> factory)
|
trainer(double money, unsigned stock, std::size_t n, std::function<T()> factory)
|
||||||
: factory(factory), id(0), generation(1), money(money), stock(stock), n(n),
|
: factory(factory), id(0), generation(1), money(money), stock(stock), n(n), random_engine(std::time(0))
|
||||||
q([](std::shared_ptr<trained<T>> x, const dataset& input, double money, unsigned stock) {
|
|
||||||
return money + input.back() * stock;
|
|
||||||
}),
|
|
||||||
random_engine(std::time(0))
|
|
||||||
{
|
{
|
||||||
|
this->q = [=](std::shared_ptr<trained<T>> x, const dataset& input, double money, unsigned stock) {
|
||||||
|
return (money + stock * input.back()) / (this->money + this->stock * input.front()); };
|
||||||
add(n);
|
add(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +80,7 @@ public:
|
|||||||
{
|
{
|
||||||
trainee->decider.start_money = money;
|
trainee->decider.start_money = money;
|
||||||
trainee->decider.start_stock = stock;
|
trainee->decider.start_stock = stock;
|
||||||
trainee->decider.reset();
|
trainee->decider.reset(input.front());
|
||||||
|
|
||||||
double money = this->money;
|
double money = this->money;
|
||||||
unsigned stock = this->stock;
|
unsigned stock = this->stock;
|
||||||
@ -181,28 +179,39 @@ public:
|
|||||||
std::uniform_real_distribution<double> ratio(0.0, 1.0);
|
std::uniform_real_distribution<double> ratio(0.0, 1.0);
|
||||||
|
|
||||||
auto combiner = [=](const double& a, const double& b){
|
auto combiner = [=](const double& a, const double& b){
|
||||||
auto mutation = (rand() % 2 ? -1 : 1) * exponential(random_engine);
|
|
||||||
|
|
||||||
if (exponential(random_engine) < 1) {
|
if (exponential(random_engine) < 1) {
|
||||||
auto r = ratio(random_engine);
|
auto r = ratio(random_engine);
|
||||||
return r * a + (1 - r) * b + mutation;
|
return r * a + (1 - r) * b;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rand() % 2 ? a : b) + mutation;
|
return rand() % 2 ? a : b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto mutator = [=](const double& a) {
|
||||||
|
auto mutation = (rand() % 2 ? -1 : 1) * exponential(random_engine);
|
||||||
|
return a + mutation;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::size_t to_combine = diff * 0.4, to_mutate = diff * 0.4;
|
||||||
|
|
||||||
unsigned first, second;
|
unsigned first, second;
|
||||||
for (int i = 0; i < diff - 4; i++) {
|
for (int i = 0; i < to_combine; i++) {
|
||||||
first = distribution(random_engine);
|
first = distribution(random_engine);
|
||||||
do { second = distribution(random_engine); } while (first == second);
|
do { second = distribution(random_engine); } while (first == second);
|
||||||
|
|
||||||
auto combined = trainees[first]->decider.combine(trainees[second]->decider, combiner);
|
auto combined = trainees[first]->decider.combine(trainees[second]->decider, combiner).mutate(mutator);
|
||||||
std::cout << "Łączenie #" << trainees[first]->id << " z #" << trainees[second]->id << " dało #" << (id+1) << std::endl;
|
std::cout << "Łączenie #" << trainees[first]->id << " z #" << trainees[second]->id << " dało #" << (id+1) << std::endl;
|
||||||
|
|
||||||
add(combined);
|
add(combined);
|
||||||
}
|
}
|
||||||
|
|
||||||
add(4); // some random things
|
for (int i = 0; i < to_mutate; i++) {
|
||||||
|
first = distribution(random_engine);
|
||||||
|
std::cout << "Mutowanie #" << trainees[first]->id << " w #" << id+1 << std::endl;
|
||||||
|
add(trainees[first]->decider.mutate(mutator));
|
||||||
|
}
|
||||||
|
|
||||||
|
add(diff - to_combine - to_mutate); // some random things
|
||||||
|
|
||||||
generation++;
|
generation++;
|
||||||
}
|
}
|
||||||
|
3
wtf.cpp
3
wtf.cpp
@ -14,8 +14,7 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "decider.h"
|
#include "decider.h"
|
||||||
#include "trainer.h"
|
#include "trainer.h"
|
||||||
|
#include "common.h"
|
||||||
using current_decider = neural_decider<24, 16, 16, 32, 16>;
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user