# Path: tia/analysis/model/trd.py
# class TradeBlotter(object):
#     """TradeBlotter class provides a way to ensure that a trade never causes a position to cross zero (and later need
#     split for long/short accouting). The methods provide the intent so the blotter can verify the expected state."""
# 
#     def __init__(self, tidgen=None):
#         self.ts = None
#         self._live_qty = 0
#         self.trades = []
#         if tidgen is None or isinstance(tidgen, int):
#             tidgen = itertools.count(tidgen or 1, 1)
#         self.tidgen = tidgen
# 
#     def is_open(self):
#         return self._live_qty != 0
# 
#     def next_tid(self):
#         return self.tidgen.next()
# 
#     def _order(self, qty, px, fees=0, **kwargs):
#         if not self.ts:
#             raise Exception('no timestamp has been set in the blotter')
#         trd = Trade(self.next_tid(), self.ts, qty, px, fees=fees, **kwargs)
#         self.trades.append(trd)
#         self._live_qty += qty
# 
#     def open(self, qty, px, fees=0, **kwargs):
#         if self.is_open():
#             raise Exception('open position failed: position already open')
#         if qty == 0:
#             raise Exception('open position failed: qty is 0')
#         self._order(qty, px, fees, **kwargs)
# 
#     def close(self, px, fees=0, **kwargs):
#         if not self.is_open():
#             raise Exception('close position failed: no position currently open')
#         qty = -self.trades[-1].qty
#         self._order(qty, px, fees, **kwargs)
# 
#     def try_close(self, px, fees=0, **kwargs):
#         if not self.is_open():
#             return
#         else:
#             return self.close(px, fees=fees, **kwargs)
# 
#     def decrease(self, qty, px, fees=0, **kwargs):
#         if not self.is_open():
#             raise Exception('decrease position failed: no position currently open')
#         if np.sign(self._live_qty) != -np.sign(qty):
#             msg = 'decrease position failed: trade quantity {0} is same sign as live quantity {1}'
#             raise Exception(msg.format(qty, self._live_qty))
#         self._order(qty, px, fees, **kwargs)
# 
#     def increase(self, qty, px, fees=0, **kwargs):
#         if not self.is_open():
#             raise Exception('increase position failed: no position currently open')
#         if np.sign(self._live_qty) != np.sign(qty):
#             msg = 'increase position failed: trade quantity {0} is different sign as live quantity {1}'
#             raise Exception(msg.format(qty, self._live_qty))
#         self._order(qty, px, fees, **kwargs)
# 
# Path: tia/analysis/util.py
# def per_level():
#     def _pl(fct):
#         return PerLevel(fct)
# 
#     return _pl
# 
# def per_series(result_is_frame=0):
#     def _ps(fct):
#         return PerSeries(fct, result_is_frame=result_is_frame)
# 
#     return _ps


import pandas as pd
import numpy as np
from tia.analysis.model.trd import TradeBlotter
from tia.analysis.util import per_level, per_series



__all__ = ['per_level', 'per_series', 'sma', 'ema', 'wilderma', 'ma', 'macd', 'rsi', 'true_range', 'dmi',
           'cross_signal', 'Signal']


@per_series()
def sma(arg, n):
    """ If n is 0 then return the ltd mean; else return the n day mean """
    if n == 0:
        return pd.expanding_mean(arg)
    else:
        return pd.rolling_mean(arg, n, min_periods=n)


@per_series()
def ema(arg, n):
    if n == 0:
        return pd.ewma(arg, span=len(arg), min_periods=1)
    else:
        return pd.ewma(arg, span=n, min_periods=n)



# Path: tia/analysis/model/trd.py
# class TradeBlotter(object):
#     """TradeBlotter class provides a way to ensure that a trade never causes a position to cross zero (and later need
#     split for long/short accouting). The methods provide the intent so the blotter can verify the expected state."""
# 
#     def __init__(self, tidgen=None):
#         self.ts = None
#         self._live_qty = 0
#         self.trades = []
#         if tidgen is None or isinstance(tidgen, int):
#             tidgen = itertools.count(tidgen or 1, 1)
#         self.tidgen = tidgen
# 
#     def is_open(self):
#         return self._live_qty != 0
# 
#     def next_tid(self):
#         return self.tidgen.next()
# 
#     def _order(self, qty, px, fees=0, **kwargs):
#         if not self.ts:
#             raise Exception('no timestamp has been set in the blotter')
#         trd = Trade(self.next_tid(), self.ts, qty, px, fees=fees, **kwargs)
#         self.trades.append(trd)
#         self._live_qty += qty
# 
#     def open(self, qty, px, fees=0, **kwargs):
#         if self.is_open():
#             raise Exception('open position failed: position already open')
#         if qty == 0:
#             raise Exception('open position failed: qty is 0')
#         self._order(qty, px, fees, **kwargs)
# 
#     def close(self, px, fees=0, **kwargs):
#         if not self.is_open():
#             raise Exception('close position failed: no position currently open')
#         qty = -self.trades[-1].qty
#         self._order(qty, px, fees, **kwargs)
# 
#     def try_close(self, px, fees=0, **kwargs):
#         if not self.is_open():
#             return
#         else:
#             return self.close(px, fees=fees, **kwargs)
# 
#     def decrease(self, qty, px, fees=0, **kwargs):
#         if not self.is_open():
#             raise Exception('decrease position failed: no position currently open')
#         if np.sign(self._live_qty) != -np.sign(qty):
#             msg = 'decrease position failed: trade quantity {0} is same sign as live quantity {1}'
#             raise Exception(msg.format(qty, self._live_qty))
#         self._order(qty, px, fees, **kwargs)
# 
#     def increase(self, qty, px, fees=0, **kwargs):
#         if not self.is_open():
#             raise Exception('increase position failed: no position currently open')
#         if np.sign(self._live_qty) != np.sign(qty):
#             msg = 'increase position failed: trade quantity {0} is different sign as live quantity {1}'
#             raise Exception(msg.format(qty, self._live_qty))
#         self._order(qty, px, fees, **kwargs)
# 
# Path: tia/analysis/util.py
# def per_level():
#     def _pl(fct):
#         return PerLevel(fct)
# 
#     return _pl
# 
# def per_series(result_is_frame=0):
#     def _ps(fct):
#         return PerSeries(fct, result_is_frame=result_is_frame)
# 
#     return _ps


# Path: tia/analysis/ta.py
import pandas as pd
import numpy as np
from tia.analysis.model.trd import TradeBlotter
from tia.analysis.util import per_level, per_series




__all__ = ['per_level', 'per_series', 'sma', 'ema', 'wilderma', 'ma', 'macd', 'rsi', 'true_range', 'dmi',
           'cross_signal', 'Signal']


@per_series()
def sma(arg, n):
    """ If n is 0 then return the ltd mean; else return the n day mean """
    if n == 0:
        return pd.expanding_mean(arg)
    else:
        return pd.rolling_mean(arg, n, min_periods=n)


@per_series()
def ema(arg, n):
    if n == 0:
        return pd.ewma(arg, span=len(arg), min_periods=1)
    else:
        return pd.ewma(arg, span=n, min_periods=n)



@per_series()