2016-12-22 20:15:07 +04:00
|
|
|
import numpy as np
|
2016-12-23 14:18:33 +04:00
|
|
|
import math
|
2016-12-22 20:15:07 +04:00
|
|
|
from pyFTS import *
|
|
|
|
|
2016-12-23 14:18:33 +04:00
|
|
|
|
2017-01-26 16:19:34 +04:00
|
|
|
class Transformation(object):
|
2017-05-02 18:32:03 +04:00
|
|
|
"""
|
|
|
|
Data transformation used to pre and post processing of the FTS
|
|
|
|
"""
|
2017-01-26 16:19:34 +04:00
|
|
|
|
|
|
|
def __init__(self, parameters):
|
|
|
|
self.isInversible = True
|
|
|
|
self.parameters = parameters
|
2017-01-27 14:26:47 +04:00
|
|
|
self.minimalLength = 1
|
2017-01-26 16:19:34 +04:00
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
def apply(self,data,param,**kwargs):
|
2017-01-26 16:19:34 +04:00
|
|
|
pass
|
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
def inverse(self,data, param,**kwargs):
|
2017-01-26 16:19:34 +04:00
|
|
|
pass
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return self.__class__.__name__ + '(' + str(self.parameters) + ')'
|
|
|
|
|
|
|
|
|
|
|
|
class Differential(Transformation):
|
2017-05-02 18:32:03 +04:00
|
|
|
"""
|
|
|
|
Differentiation data transform
|
|
|
|
"""
|
2017-01-26 16:19:34 +04:00
|
|
|
def __init__(self, parameters):
|
|
|
|
super(Differential, self).__init__(parameters)
|
|
|
|
self.lag = parameters
|
2017-01-27 14:26:47 +04:00
|
|
|
self.minimalLength = 2
|
2017-01-26 16:19:34 +04:00
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
def apply(self, data, param=None,**kwargs):
|
2017-01-26 16:19:34 +04:00
|
|
|
if param is not None:
|
|
|
|
self.lag = param
|
2017-01-30 03:59:50 +04:00
|
|
|
|
|
|
|
if not isinstance(data, (list, np.ndarray, np.generic)):
|
|
|
|
data = [data]
|
|
|
|
|
|
|
|
if isinstance(data, (np.ndarray, np.generic)):
|
|
|
|
data = data.tolist()
|
|
|
|
|
2017-01-26 16:19:34 +04:00
|
|
|
n = len(data)
|
|
|
|
diff = [data[t - self.lag] - data[t] for t in np.arange(self.lag, n)]
|
|
|
|
for t in np.arange(0, self.lag): diff.insert(0, 0)
|
2017-01-27 14:26:47 +04:00
|
|
|
return diff
|
2017-01-26 16:19:34 +04:00
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
def inverse(self,data, param, **kwargs):
|
|
|
|
|
2017-05-15 21:06:26 +04:00
|
|
|
interval = kwargs.get("point_to_interval",False)
|
2017-01-30 03:59:50 +04:00
|
|
|
|
|
|
|
if isinstance(data, (np.ndarray, np.generic)):
|
|
|
|
data = data.tolist()
|
|
|
|
|
|
|
|
if not isinstance(data, list):
|
|
|
|
data = [data]
|
|
|
|
|
2017-07-04 19:18:07 +04:00
|
|
|
if not isinstance(param, list):
|
|
|
|
param = [param]
|
|
|
|
|
2017-01-26 16:19:34 +04:00
|
|
|
n = len(data)
|
2017-01-30 03:59:50 +04:00
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
if not interval:
|
|
|
|
inc = [data[t] + param[t] for t in np.arange(0, n)]
|
|
|
|
else:
|
2017-05-15 21:06:26 +04:00
|
|
|
inc = [[data[t][0] + param[t], data[t][1] + param[t]] for t in np.arange(0, n)]
|
2017-01-30 03:59:50 +04:00
|
|
|
|
|
|
|
if n == 1:
|
|
|
|
return inc[0]
|
|
|
|
else:
|
|
|
|
return inc
|
2016-12-23 14:18:33 +04:00
|
|
|
|
|
|
|
|
2017-07-05 22:35:22 +04:00
|
|
|
class Scale(Transformation):
|
|
|
|
def __init__(self, min=0, max=1):
|
|
|
|
super(Scale, self).__init__([min, max])
|
|
|
|
self.data_max = None
|
|
|
|
self.data_min = None
|
|
|
|
self.transf_max = max
|
|
|
|
self.transf_min = min
|
|
|
|
|
|
|
|
def apply(self, data, param=None,**kwargs):
|
|
|
|
if self.data_max is None:
|
|
|
|
self.data_max = np.nanmax(data)
|
|
|
|
self.data_min = np.nanmin(data)
|
|
|
|
data_range = self.data_max - self.data_min
|
|
|
|
transf_range = self.transf_max - self.transf_min
|
|
|
|
if isinstance(data, list):
|
|
|
|
tmp = [(k + (-1 * self.data_min)) / data_range for k in data]
|
|
|
|
tmp2 = [ (k * transf_range) + self.transf_min for k in tmp]
|
|
|
|
else:
|
|
|
|
tmp = (data + (-1 * self.data_min)) / data_range
|
|
|
|
tmp2 = (tmp * transf_range) + self.transf_min
|
|
|
|
|
|
|
|
return tmp2
|
|
|
|
|
|
|
|
def inverse(self, data, param, **kwargs):
|
|
|
|
data_range = self.data_max - self.data_min
|
|
|
|
transf_range = self.transf_max - self.transf_min
|
|
|
|
if isinstance(data, list):
|
|
|
|
tmp2 = [(k - self.transf_min) / transf_range for k in data]
|
|
|
|
tmp = [(k * data_range) + self.data_min for k in tmp2]
|
|
|
|
else:
|
|
|
|
tmp2 = (data - self.transf_min) / transf_range
|
|
|
|
tmp = (tmp2 * data_range) + self.data_min
|
|
|
|
return tmp
|
|
|
|
|
|
|
|
|
2017-04-20 22:07:34 +04:00
|
|
|
class AdaptiveExpectation(Transformation):
|
2017-05-02 18:32:03 +04:00
|
|
|
"""
|
|
|
|
Adaptive Expectation post processing
|
|
|
|
"""
|
2017-04-20 22:07:34 +04:00
|
|
|
def __init__(self, parameters):
|
|
|
|
super(AdaptiveExpectation, self).__init__(parameters)
|
|
|
|
self.h = parameters
|
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
def apply(self, data, param=None,**kwargs):
|
2017-04-20 22:07:34 +04:00
|
|
|
return data
|
|
|
|
|
2017-05-14 04:37:10 +04:00
|
|
|
def inverse(self, data, param,**kwargs):
|
2017-04-20 22:07:34 +04:00
|
|
|
n = len(data)
|
|
|
|
|
|
|
|
inc = [param[t] + self.h*(data[t] - param[t]) for t in np.arange(0, n)]
|
|
|
|
|
|
|
|
if n == 1:
|
|
|
|
return inc[0]
|
|
|
|
else:
|
|
|
|
return inc
|
|
|
|
|
|
|
|
|
2016-12-23 14:18:33 +04:00
|
|
|
def boxcox(original, plambda):
|
|
|
|
n = len(original)
|
|
|
|
if plambda != 0:
|
|
|
|
modified = [(original[t] ** plambda - 1) / plambda for t in np.arange(0, n)]
|
|
|
|
else:
|
|
|
|
modified = [math.log(original[t]) for t in np.arange(0, n)]
|
|
|
|
return np.array(modified)
|
2017-01-20 19:51:20 +04:00
|
|
|
|
|
|
|
|
|
|
|
def Z(original):
|
|
|
|
mu = np.mean(original)
|
|
|
|
sigma = np.std(original)
|
|
|
|
z = [(k - mu)/sigma for k in original]
|
|
|
|
return z
|
2017-01-23 17:00:27 +04:00
|
|
|
|
|
|
|
|
|
|
|
# retrieved from Sadaei and Lee (2014) - Multilayer Stock ForecastingModel Using Fuzzy Time Series
|
|
|
|
def roi(original):
|
|
|
|
n = len(original)
|
|
|
|
roi = []
|
|
|
|
for t in np.arange(0, n-1):
|
|
|
|
roi.append( (original[t+1] - original[t])/original[t] )
|
|
|
|
return roi
|
2017-01-25 18:17:07 +04:00
|
|
|
|
|
|
|
def smoothing(original, lags):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def aggregate(original, operation):
|
|
|
|
pass
|