# POJO-like class in Python

I simply want to organize some data (class= MarketOnCloseSecurity) to be used in another class MarketOnClosePortfolio. The former class would not have any methods but just a constructor that includes a ticker for a company symbol and two Pandas dataframes bars and signals.

class MarketOnCloseSecurity():
"""Encapsulates the notion of a portfolio of positions based
on a set of signals as provided by a Strategy.

Requires:
symbol - A stock symbol which forms the basis of the portfolio.
bars - A DataFrame of bars for a symbol set.
signals - A pandas DataFrame of signals (1, 0, -1) for each symbol.
"""

def __init__(self, symbol, bars, signals):
self.symbol = symbol
self.bars = bars
self.signals = signals


Now the MarketOnClosePortfolio would have all the methods to calculate a portfolio.

Is creating a class with essentially no methods (besides constructor) in python a good practice?

The idea is to pass MarketOnClosePortfolio a list of MarketOnCloseSecurity objects.

An alternative (non-OOP) solution would do something like list_of_MOCS = [{'symbol_1':(bars_1,signals_1)},...,{'symbol_N':(bars_N,signals_N)}] so basically a list containing a map with the key being the ticker and value being a tuple of the two dataframes.

MarketOnClosePortfolio will identify the positions (buy/sell) and how based on each MarketOnCloseSecurity and form a Portfolio Dataframe. It will then calculate metrics, such as holdings, cash, and returns based on the summation of each MarketOnCloseSecurity. The code is not complete, but I have included it for reference.

class MarketOnClosePortfolio(Portfolio):
"""Encapsulates the notion of a portfolio of positions based
on a set of signals as provided by a Strategy.

Requires:
market_on_close_securities
initial_capital - The amount in cash at the start of the portfolio."""

def __init__(self, market_on_close_securities, initial_capital=100000.0):
self.market_on_close_securities = market_on_close_securities
self.initial_capital = float(initial_capital)
self.positions = self.generate_positions()

def generate_positions(self):
#loop through each MOCS (market_on_close_security) to calculate positions

# Initialize index for positions Dataframe. Picking index 0 was arbitary they all have same index length
positions = pd.DataFrame(index=self.market_on_close_securities[0].signals.index).fillna(0.0)
for security in self.market_on_close_securities:
positions[security.symbol] = 100 * security.signals['signal'] # This strategy buys 100 shares

return positions

def backtest_portfolio(self):

portfolio_series = self.positions[self.symbol] * self.bars[0]['close_price'].astype(float)

pos_diff = self.positions.diff()

# Will need to use this for multiple columns (Eventually)
symbol_columns = [self.symbol]

portfolio = pd.DataFrame(index=self.bars[0].index, columns=symbol_columns)
portfolio[self.symbol] = portfolio_series.values

# Sum holdings from each company
portfolio['holdings'] = portfolio.sum(axis=1)
portfolio['cash'] = self.initial_capital - (pos_diff[self.symbol] * self.bars[0]['close_price'].astype(float)).cumsum()
portfolio['cash'][0] = self.initial_capital
portfolio['total'] = portfolio['cash'] + portfolio['holdings']
portfolio['returns'] = portfolio['total'].pct_change()

return portfolio


The backtest_portfolio() will determine the total returns/holdings based on each MarketOnCloseSecurity. This implementation is not complete, and is currently the method used when MarketOnClosePortfolio was adapted for only one security.

• I think it's ok. But, most of time, i use NamedTuple for POJO like objects. Not sure that it is possible with Dataframes. – Arnial Oct 27 '16 at 17:49
• namedtuples are awesome. You can inherit from them too in cases where you don't need to alter them just a tiny bit - like this – Daerdemandt Oct 27 '16 at 18:01
• Knowing how you would use this data into MarketOnClosePortfolio will help us give more taillored advices. – 301_Moved_Permanently Oct 27 '16 at 19:32
• Updated with what I have so far. Let me know what you think! Also thanks for the input so far from everyone. – user3547551 Oct 27 '16 at 19:42

An alternative (non-OOP) solution would do something like list_of_MOCS = [{'symbol_1':(bars_1,signals_1)},...,{'symbol_N':(bars_N,signals_N)}] so basically a list containing a map with the key being the ticker and value being a tuple of the two dataframes.

I thought, that a better alternative would be:

MOCS = {
'symbol_1': (bars_1, signals_1),
'symbol_2': (bars_2, signals_2),
...
'symbol_N': (bars_N, signals_N),
}


Especially given the fact that pd.DataFrame(MOCS) would yield a valid structure.

However, reading at your usage in generate_positions and expected usage in backtest_portfolio; and especially the fact that you will need to explode the data-structure anyway, I would keep the class approach and use collections.namedtuple as largely suggested in the comments. It provides both the advantages of a class (attributes access) and a tuple (immutable + index access).

I would however change generate_positions to create a dictionnary that will hold the structure of the resulting dataframe before building said dataframe. And incorporate that method directly into the constructor as it does not provide much added value on its own:

from collections import namedtuple

MarketOnCloseSecurity = namedtuple('MarketOnCloseSecurity', 'symbol bars signals')

class MarketOnClosePortfolio(Portfolio):
"""Encapsulates the notion of a portfolio of positions based
on a set of signals as provided by a Strategy.

Requires:
market_on_close_securities
initial_capital - The amount in cash at the start of the portfolio."""

def __init__(self, market_on_close_securities, initial_capital=100000.0):
self.market_on_close_securities = market_on_close_securities
self.initial_capital = float(initial_capital)

#loop through each MOCS (market_on_close_security) to calculate positions
securities = {
security.symbol: 100 * security.signals['signal'] # This strategy buys 100 shares
for security in market_on_close_securities
}
self.positions = pd.DataFrame(securities)

def backtest_portfolio(self):
...


I would also extend the namedtuple to provide extra utilities methods:

class MarketOnCloseSecurity(namedtuple('MarketOnCloseSecurity', 'symbol bars signals')):
return amount * self.signals['signal']

def close_price(self):
return self.bars['close_price'].astype(float)


So that you can have more meaningful actions in MarketOnClosePortfolio:

class MarketOnClosePortfolio(Portfolio):
"""Encapsulates the notion of a portfolio of positions based
on a set of signals as provided by a Strategy.

Requires:
market_on_close_securities
initial_capital - The amount in cash at the start of the portfolio."""

def __init__(self, market_on_close_securities, initial_capital=100000.0):
self.market_on_close_securities = market_on_close_securities
self.initial_capital = float(initial_capital)

securities = {