I am trying to find a solution to the following design problem
(code at the bottom):
We are implementing a trader agent that can trade with other traders
on an electronical trading platform. To make the trader more
extensible, we have defined a strategy interface and implemented this
interface for different trading strategies. The problem relates to how
to connect the trader and the strategy.
The problem is tricky because the strategy has to call back the
trader, for instance to get information about orders (i.e. prices) on
the trading platform, and to initiate own orders. Technically, the
strategy constructor takes an argument of type StrategyCallback. The
latter is an interface which is implemented by the trader class.
The quick and dirty approach would be the following:
The user (1) instantiates the trader and then (2) uses the reference
to the trader to instantiate the strategy. After that (3), the user
calls a method of the trader that initializes the trader's strategy,
passing it the reference to the strategy.
The problem is that the initialization takes place outside of, and
after the constructor. Also, the user has to worry about internals of
the trader.
A bit more elegant is the following approach:
The strategy cannot be instantiated before the trader. It would be
nice to let the trader instantiate it. But the trader doesn't know the
exact type of the strategy. So let's make the trader a template. Like
this, the initialization can take place in the trader's constructor
and is hidden from the user.
We have implemented this approach, and it works. However, it doesn't
really solve the design problem. Every instantiation of the trader
template has a different type. The trader class has to be recompiled
whenever we write a new strategy for it. For the same reason, it is
awkward to manage a collection of traders with different strategies.
Is there another way?
struct Strategy;
struct StrategyCallback;
/// trader class aggregating a strategy
class Trader
: public StrategyCallback
{
public:
//construction
Trader(trading::Strategy*);
~Trader();
private:
Trader(const& Trader);
Trader& operator=(const Trader&);
//private data
Strategy* m_pStrategy;
};
/// interface representing a trader's strategy.
struct Strategy
{
virtual ~Strategy() { /*cleanup*/ }
/// reevaluate situation.
virtual void evaluate() = 0;
/// the strategy has reached the goal.
virtual bool succeeded() = 0;
/// the strategy has failed.
virtual bool failed() = 0;
/// perform the strategy.
virtual void trade() = 0;
};
/// callback interface for strategy.
struct StrategyCallback
{
/// access orders.
virtual OrderIseq getOrders() = 0;
/// create an order.
virtual trading::Order* createOrder(
double dPrice,
double dVolume) = 0;
};
--
Claudio Jolowicz
Department of Computing
180 Queen's Gate
South Kensington campus
Imperial College
LONDON SW7 2AZ
31 Humbolt Road
Fulham
LONDON W6 8QH
mobile: +44(0)7963 892810
mail to: cj***@doc.ic.ac.uk
webpage: www.doc.ic.ac.uk/~cj603