#include "Investor.h" #include #include #include #include "Stock.h" #include "BuyStrategy.h" #include "SellOrder.h" #include "BuyOrder.h" #include "StockMarket.h" #include Investor::Investor( double capital, StockMarket* market ) : capital_( capital ), reservedCapital_( 0 ), market_( market ), buyStrategy_( 0 ) { } Investor::~Investor() { delete buyStrategy_; } void Investor::setBuyStrategy( BuyStrategy * buy ) { buyStrategy_ = buy; } void Investor::reserve( double capital ) { reservedCapital_ += capital; assert( reservedCapital_ <= capital_ ); } void Investor::release( double capital ) { reservedCapital_ -= capital; // avoid machine precision problems if ( abs(reservedCapital_) < 1.e-6 ) reservedCapital_ = 0; assert( reservedCapital_ >= 0 ); } void Investor::reserve( Stock* stock, long amount ) { stockInfo & info = portfolio_[ stock ]; assert( amount <= info.available() ); info.reserved += amount; } void Investor::release( Stock* stock, long amount ) { stockInfo & info = portfolio_[ stock ]; assert( amount <= info.reserved ); info.reserved -= amount; } double Investor::buyPrice( Stock * stock ) const { map::const_iterator found = portfolio_.find( stock ); return found == portfolio_.end() ? 0 : found->second.buyPrice; } long Investor::amount( Stock * stock ) const { map::const_iterator found = portfolio_.find( stock ); return found == portfolio_.end() ? 0 : found->second.amount; } long Investor::amountAvailable( Stock * stock ) const { map::const_iterator found = portfolio_.find( stock ); return found == portfolio_.end() ? 0 : found->second.available(); } void Investor::doTask() { if ( market_ == 0 ) return; vector::const_iterator s; for( s = market_->begin(); s != market_->end(); s++ ) { Stock * stock = *s; double buyPrice = Investor::buyPrice( stock ); long amountAvailable = Investor::amountAvailable( stock ); double capitalAvailable = capital_- reservedCapital_; long buyAmount = buyStrategy_->buy( stock, capitalAvailable, buyPrice, amountAvailable ); double price = buyStrategy_->price(); if ( buyAmount < 0 ) { // cout << "sell order: " << -buyAmount << " " << stock->symbol() // << " at " << price << endl; market_->addSell( new SellOrder( this, stock, price, -buyAmount ) ); } else if ( buyAmount > 0 ) { // cout << "buy order: " << buyAmount << " " << stock->symbol() // << " at " << price << endl; market_->addBuy( new BuyOrder( this, stock, price, buyAmount ) ); } } // print(); } bool Investor::buy( Stock* stock, double price, long amount ) { double cost = amount * price; if ( capital_ >= cost ) { capital_ -= cost; stockInfo & info = portfolio_[ stock ]; double averagePrice = info.buyPrice; double ownedAmount = info.amount; double newAverage = ( price * amount + averagePrice * ownedAmount ) / ( ownedAmount + amount); info.buyPrice = newAverage; info.amount += amount; // cout << "bought " << amount << " " << stock->symbol() << " at $" << price << endl; return true; } else return false; } bool Investor::sell( Stock* stock , double price, long amount ) { stockInfo & info = portfolio_[ stock ]; long ownedAmount = info.amount; if ( ownedAmount >= amount ) { double cost = amount * price; capital_ += cost; info.amount -= amount; double averagePrice = info.buyPrice; double gain = ( price - averagePrice )/ averagePrice; // cout << "sold " << amount << " " << stock->symbol() << " at $" << price // << " (" << ( gain >= 0 ? '+' : '-' ) << fabs( gain ) * 100 <<"%)" << endl; return true; } else return false; } void Investor::print() { map::iterator i; double virtualCapital = capital_; for ( i = portfolio_.begin(); i != portfolio_.end(); i++) { long amount = i->second.amount; double price = i->second.buyPrice; virtualCapital += amount * price; } cout << "capital: $" << setprecision(9) << setw(10) << capital_ << " (" << setprecision(9) << setw(10) << virtualCapital <<" virtual)" << endl; for ( i = portfolio_.begin(); i != portfolio_.end(); i++) { Stock * stock = i->first; long amount = i->second.amount; double price = i->second.buyPrice; double gain = ( stock->price() - price ) / price; if ( amount >0 ) cout << " " << stock->symbol() << ": " << amount << " (" << ( gain >= 0 ? '+' : '-' ) << setprecision(4) << setw(5) << fabs( gain ) * 100 <<"%)"<< endl; } }