arma::vec ung_ssm::importance_weights(const ugg_ssm& approx_model, const arma::cube& alpha) const { arma::vec weights(alpha.n_slices, arma::fill::zeros); for(unsigned int t = 0; t < n; t++) { weights += log_weights(approx_model, t, alpha); } return weights; }
void Backtester::run_one_step() { MatrixQuery dq = make_query(); // Get Available Data Row lp = last_price(); // Get Last price // Making public data available DataStruct ds(_price_matrix); ds.data_manager = &dq; //ds.predictors = &this->_GlobalPredictors; //ds.securities = this->_SecurityDatabase; const TransactionWeight* w; Eigen::IOFormat fmt; for(Index k = 0, n = _strategies.size(); k < n; k++) { if (should_run(k)) { // Compute Target owning w = (*get_strategy(k))(ds); // log current target log_weights(title(k), *w); // Compute effective Buy/Sell Matrix orders = get_portfolio(k)->transaction_weight(_time, lp, *w); log_orders(title(k), orders); // update portfolio state get_portfolio(k)->transaction_answer(orders, lp); // Log current holdings log_portfolio_state(title(k), get_portfolio(k)->state()); } MPortfolio& p = get_portfolio(k); // log current portfolio value log_portfolio_values(title(k), p->invested(lp), p->cash(), p->liability(lp)); } // one period has passed _time++; }
int main(int argc, char* argv[]) { // parse command line arguments const long ITERATIONS = argc > 1 ? std::atol(argv[1]) : 200; const bool LOG_FIT = !(argc > 2 && std::string("nofit").compare(argv[2]) == 0); const bool LOG_WEG = !(argc > 3 && std::string("noweg").compare(argv[3]) == 0); const bool LOG_GEN = argc > 4 && std::string("gen").compare(argv[4]) == 0; // draws a random identifier for this run const int RUN_PREFIX = std::uniform_int_distribution<int>(1, 1 << 12)(rand_gen); std::cout << "## simulation " << RUN_PREFIX << std::endl; std::cout << "## " << ITERATIONS << " iterations" << std::endl; std::cout << "## " << (!LOG_FIT ? "won't" : "will") << " log fitness" << std::endl; std::cout << "## " << (!LOG_WEG ? "won't" : "will") << " log weights" << std::endl; std::cout << "## " << (!LOG_GEN ? "won't" : "will") << " log genotypes" << std::endl; std::cout << std::endl; auto start_time = std::chrono::system_clock::now(); // generates FOOD_LOCATIONS random points for each iteration // where collocate the food the creatures should reach double food_angle; double *food_locations = new double[2 * FOOD_LOCATIONS]; for (int i = 0; i < FOOD_LOCATIONS; ++i) { // spread uniformly angles around pi / 4 food_angle = M_PI_4 * (1 + 2 * fuzzy_rand()); food_locations[2 * i] = cos(food_angle) * FOOD_DISTANCE; food_locations[2 * i + 1] = sin(food_angle) * FOOD_DISTANCE; } // allocate memory for the population pool Individual* population[2][POPULATION_SIZE]; Individual** generation = population[0]; Individual** next_generation = population[1]; // mating stuff double draw; double mating_chance[MATING_POPULATION]; double sum; int partner1, partner2; for (int i = 0; i < POPULATION_SIZE; ++i) { generation[i] = Individual::create(); } for (int iter = 0; iter < ITERATIONS; ++iter) { #pragma parallel always _Cilk_for (int i = 0; i < POPULATION_SIZE; ++i) { for (int f = 0; f < FOOD_LOCATIONS; ++f) { for (int j = 0; j < FITNESS_COMPUTING_ITERATIONS; ++j) { generation[i]->tick(food_locations + 2 * f); } // fitness is what fraction of the distance to food it traveled generation[i]->fitness += 1 / (1 + diff_norm(generation[i]->position, food_locations + 2 * f)); generation[i]->reset(); } // mean of all the tests generation[i]->fitness /= FOOD_LOCATIONS; } // sort population by fitness std::sort(generation, generation + POPULATION_SIZE, [](Individual* a, Individual* b) {return a->fitness > b->fitness;}); if (LOG_FIT) { // log the best fitness _Cilk_spawn log_fitness(RUN_PREFIX, iter, generation[0]->fitness); } if (LOG_GEN) { // log genotypes _Cilk_spawn log_genotypes(RUN_PREFIX, iter, generation); } if (LOG_WEG) { // dump weights of the best if (fmod(iter, ITERATIONS / (1.0 * DUMPS)) < 1 || iter == 0) { _Cilk_spawn log_weights(RUN_PREFIX, iter, generation[0]); std::cout << iter << " -> dump at fitness " << generation[0]->fitness << std::endl; } } if (fmod(iter, ITERATIONS / (5.0 * DUMPS)) < 1 || iter == ITERATIONS - 1) { std::cout << iter << " fitness is " << generation[0]->fitness << std::endl; } if (iter != ITERATIONS - 1) { for (int i = 0; i < MATING_POPULATION; ++i) { // skew the distribution mating_chance[i] = pow(generation[i]->fitness, 10); } sum = 0; for (int i = 0; i < MATING_POPULATION; ++i) { sum += mating_chance[i]; } for (int i = 0; i < MATING_POPULATION; ++i) { // get the percentage of contribution to total fitness mating_chance[i] /= sum; } for (int i = 1; i < MATING_POPULATION; ++i) { // cumulate the percentages mating_chance[i] += mating_chance[i - 1]; } // find the partners from the cumulated probability // draw is a number in the interval [0, 1] for (int i = 0; i < POPULATION_SIZE; ++i) { partner1 = partner2 = 0; draw = (fuzzy_rand() + 1) / 2; while(mating_chance[partner1] <= draw && partner1 < MATING_POPULATION) ++partner1; draw = (fuzzy_rand() + 1) / 2; while(mating_chance[partner2] <= draw && partner2 < MATING_POPULATION) ++partner2; // dirty things... next_generation[i] = generation[partner1]->mate(generation[partner2]); } } // wait before free memory if were spawned logging operations if (LOG_FIT || LOG_WEG || LOG_GEN) _Cilk_sync; // free the memory allocated by the old generation for (int i = 0; i < POPULATION_SIZE; ++i) { delete generation[i]; } // switch array generation = next_generation; next_generation = population[iter % 2 == 0 ? 0 : 1]; } flush_fitness(RUN_PREFIX); // stop the stopwatch (lol!!1!1!!) auto total_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start_time).count(); std::cout << std::endl; std::cout << "## simulation " << RUN_PREFIX << " ended succesfully" << std::endl; std::cout << "## total time: " << total_time / 1000.0 << " seconds" << std::endl; std::cout << "## time per iteration: " << total_time / (1000.0 * ITERATIONS) << " seconds" << std::endl; std::cout << std::endl << std::endl; return EXIT_SUCCESS; }
double ung_ssm::psi_filter(const ugg_ssm& approx_model, const double approx_loglik, const arma::vec& scales, const unsigned int nsim, arma::cube& alpha, arma::mat& weights, arma::umat& indices) { arma::mat alphahat(m, n + 1); arma::cube Vt(m, m, n + 1); arma::cube Ct(m, m, n + 1); approx_model.smoother_ccov(alphahat, Vt, Ct); conditional_cov(Vt, Ct); std::normal_distribution<> normal(0.0, 1.0); for (unsigned int i = 0; i < nsim; i++) { arma::vec um(m); for(unsigned int j = 0; j < m; j++) { um(j) = normal(engine); } alpha.slice(i).col(0) = alphahat.col(0) + Vt.slice(0) * um; } std::uniform_real_distribution<> unif(0.0, 1.0); arma::vec normalized_weights(nsim); double loglik = 0.0; if(arma::is_finite(y(0))) { weights.col(0) = arma::exp(log_weights(approx_model, 0, alpha) - scales(0)); double sum_weights = arma::accu(weights.col(0)); if(sum_weights > 0.0){ normalized_weights = weights.col(0) / sum_weights; } else { return -std::numeric_limits<double>::infinity(); } loglik = approx_loglik + std::log(sum_weights / nsim); } else { weights.col(0).ones(); normalized_weights.fill(1.0 / nsim); loglik = approx_loglik; } for (unsigned int t = 0; t < n; t++) { arma::vec r(nsim); for (unsigned int i = 0; i < nsim; i++) { r(i) = unif(engine); } indices.col(t) = stratified_sample(normalized_weights, r, nsim); arma::mat alphatmp(m, nsim); // for (unsigned int i = 0; i < nsim; i++) { // alphatmp.col(i) = alpha.slice(i).col(t); // } for (unsigned int i = 0; i < nsim; i++) { alphatmp.col(i) = alpha.slice(indices(i, t)).col(t); //alpha.slice(i).col(t) = alphatmp.col(indices(i, t)); } for (unsigned int i = 0; i < nsim; i++) { arma::vec um(m); for(unsigned int j = 0; j < m; j++) { um(j) = normal(engine); } alpha.slice(i).col(t + 1) = alphahat.col(t + 1) + Ct.slice(t + 1) * (alphatmp.col(i) - alphahat.col(t)) + Vt.slice(t + 1) * um; } if ((t < (n - 1)) && arma::is_finite(y(t + 1))) { weights.col(t + 1) = arma::exp(log_weights(approx_model, t + 1, alpha) - scales(t + 1)); double sum_weights = arma::accu(weights.col(t + 1)); if(sum_weights > 0.0){ normalized_weights = weights.col(t + 1) / sum_weights; } else { return -std::numeric_limits<double>::infinity(); } loglik += std::log(sum_weights / nsim); } else { weights.col(t + 1).ones(); normalized_weights.fill(1.0 / nsim); } } return loglik; }