# Path: alephnull/protocol.py
# class BarData(object):
#     """
#     Holds the event data for all sids for a given dt.
# 
#     This is what is passed as `data` to the `handle_data` function.
# 
#     Note: Many methods are analogues of dictionary because of historical
#     usage of what this replaced as a dictionary subclass.
#     """
# 
#     def __init__(self):
#         self._data = {}
#         self._contains_override = None
# 
#     def __contains__(self, name):
#         if self._contains_override:
#             if self._contains_override(name):
#                 return name in self._data
#             else:
#                 return False
#         else:
#             return name in self._data
# 
#     def has_key(self, name):
#         """
#         DEPRECATED: __contains__ is preferred, but this method is for
#         compatibility with existing algorithms.
#         """
#         return name in self
# 
#     def __setitem__(self, name, value):
#         self._data[name] = value
# 
#     def __getitem__(self, name):
#         return self._data[name]
# 
#     def __delitem__(self, name):
#         del self._data[name]
# 
#     def __iter__(self):
#         for sid, data in self._data.iteritems():
#             # Allow contains override to filter out sids.
#             if sid in self:
#                 if len(data):
#                     yield sid
# 
#     def iterkeys(self):
#         # Allow contains override to filter out sids.
#         return (sid for sid in self._data.iterkeys() if sid in self)
# 
#     def keys(self):
#         # Allow contains override to filter out sids.
#         return list(self.iterkeys())
# 
#     def itervalues(self):
#         return (value for sid, value in self.iteritems())
# 
#     def values(self):
#         return list(self.itervalues())
# 
#     def iteritems(self):
#         return ((sid, value) for sid, value
#                 in self._data.iteritems()
#                 if sid in self)
# 
#     def items(self):
#         return list(self.iteritems())
# 
#     def __len__(self):
#         return len(self.keys())
# 
# class SIDData(object):
# 
#     def __init__(self, initial_values=None):
#         if initial_values:
#             self.__dict__ = initial_values
# 
#     def __getitem__(self, name):
#         return self.__dict__[name]
# 
#     def __setitem__(self, name, value):
#         self.__dict__[name] = value
# 
#     def __len__(self):
#         return len(self.__dict__)
# 
#     def __contains__(self, name):
#         return name in self.__dict__
# 
#     def __repr__(self):
#         return "SIDData({0})".format(self.__dict__)


import pandas as pd
from pandas import Series, DataFrame
from alephnull.protocol import BarData, SIDData



def roll(logic):
    def wrap(func):
        def modified_func(self, data):
            positions = self.portfolio.positions
            frames = {}
            for sym in data.keys():
                frames[sym] = DataFrame({k: Series(v.__dict__) for
                                         k, v in data[sym].iteritems()})

            all_ = pd.concat(frames, axis=1).T
            try:
                all_ = all_.groupby(axis=0, level=0).apply(logic).reset_index(
                    level=(0, 2), drop=True)
            except:
                all_ = all_.groupby(axis=0, level=0).apply(logic)


            #Todo: handle multiple contract returns
            all_ = all_.groupby(axis=0, level=0).agg(lambda x: x.max())

            #Todo: Data should be reconstructed into BarData object
            data = all_.T.to_dict()

            front_months = [(sym, all_.ix[sym]['contract']) for sym in all_.index]
            back_months = [sym for sym in self.perf_tracker.get_portfolio().positions
                           if sym not in front_months]


# Path: alephnull/protocol.py
# class BarData(object):
#     """
#     Holds the event data for all sids for a given dt.
# 
#     This is what is passed as `data` to the `handle_data` function.
# 
#     Note: Many methods are analogues of dictionary because of historical
#     usage of what this replaced as a dictionary subclass.
#     """
# 
#     def __init__(self):
#         self._data = {}
#         self._contains_override = None
# 
#     def __contains__(self, name):
#         if self._contains_override:
#             if self._contains_override(name):
#                 return name in self._data
#             else:
#                 return False
#         else:
#             return name in self._data
# 
#     def has_key(self, name):
#         """
#         DEPRECATED: __contains__ is preferred, but this method is for
#         compatibility with existing algorithms.
#         """
#         return name in self
# 
#     def __setitem__(self, name, value):
#         self._data[name] = value
# 
#     def __getitem__(self, name):
#         return self._data[name]
# 
#     def __delitem__(self, name):
#         del self._data[name]
# 
#     def __iter__(self):
#         for sid, data in self._data.iteritems():
#             # Allow contains override to filter out sids.
#             if sid in self:
#                 if len(data):
#                     yield sid
# 
#     def iterkeys(self):
#         # Allow contains override to filter out sids.
#         return (sid for sid in self._data.iterkeys() if sid in self)
# 
#     def keys(self):
#         # Allow contains override to filter out sids.
#         return list(self.iterkeys())
# 
#     def itervalues(self):
#         return (value for sid, value in self.iteritems())
# 
#     def values(self):
#         return list(self.itervalues())
# 
#     def iteritems(self):
#         return ((sid, value) for sid, value
#                 in self._data.iteritems()
#                 if sid in self)
# 
#     def items(self):
#         return list(self.iteritems())
# 
#     def __len__(self):
#         return len(self.keys())
# 
# class SIDData(object):
# 
#     def __init__(self, initial_values=None):
#         if initial_values:
#             self.__dict__ = initial_values
# 
#     def __getitem__(self, name):
#         return self.__dict__[name]
# 
#     def __setitem__(self, name, value):
#         self.__dict__[name] = value
# 
#     def __len__(self):
#         return len(self.__dict__)
# 
#     def __contains__(self, name):
#         return name in self.__dict__
# 
#     def __repr__(self):
#         return "SIDData({0})".format(self.__dict__)


# Path: alephnull/roll_method.py
import pandas as pd
from pandas import Series, DataFrame
from alephnull.protocol import BarData, SIDData




def roll(logic):
    def wrap(func):
        def modified_func(self, data):
            positions = self.portfolio.positions
            frames = {}
            for sym in data.keys():
                frames[sym] = DataFrame({k: Series(v.__dict__) for
                                         k, v in data[sym].iteritems()})

            all_ = pd.concat(frames, axis=1).T
            try:
                all_ = all_.groupby(axis=0, level=0).apply(logic).reset_index(
                    level=(0, 2), drop=True)
            except:
                all_ = all_.groupby(axis=0, level=0).apply(logic)


            #Todo: handle multiple contract returns
            all_ = all_.groupby(axis=0, level=0).agg(lambda x: x.max())

            #Todo: Data should be reconstructed into BarData object
            data = all_.T.to_dict()

            front_months = [(sym, all_.ix[sym]['contract']) for sym in all_.index]
            back_months = [sym for sym in self.perf_tracker.get_portfolio().positions
                           if sym not in front_months]


            offsets = {}