diff --git a/market_trade/core/indicators.py b/market_trade/core/indicators.py new file mode 100644 index 0000000..7294d36 --- /dev/null +++ b/market_trade/core/indicators.py @@ -0,0 +1,159 @@ +import pandas as pd +import datetime +import numpy as np + +import market_trade.core.CoreTraidMath as CoreTraidMath +import market_trade.core.CoreDraw as CoreDraw + +class coreIndicator(): + def __init__(self, + data=pd.DataFrame(), + options={}, + showMode='None', + ): + ''' + showMode = None/Ind/PartOf + ''' + self.data=data + self.showMode=showMode + self.options=options + self.overlayInd=None #True/False + self.ans=None + self.figDict=None + + def getAns(self,data=None): + if type(data)!=type(None): + self.data=data + self.ans=self.getCalculate() + if self.showMode=='Ind' or self.showMode=='PartOf': + self.figDict=self.getFigDict() + if self.showMode=='Ind': + self.getFig() + return self.ans + def getFig(self,row=1): + CoreDraw.coreDraw(self.figDict,True) + def getCalculate(self): + return "Error" + def getFigDict(self): + return "Error" + +class indicatorAgrigator(): + ''' + Тема чисто для отладки + jj=indicatorAgrigator().runAll([o1,o2],df_candle[:30]) + #jj.createIndFromList([o1,o2]) + #jj.calculateInd(df_candle[:30]) + + ''' + def __init__(self): + self.indList=None + self.data=None + def createInd(self,classDict): + return classDict['name']( + options=classDict['params'], + showMode=classDict['showMode'] + ) + + + def createIndFromList(self,indList): + self.indList=indList + ans=[] + for i in self.indList: + ans.append(self.createInd(i)) + self.indList=ans + return ans + + def calculateInd(self,data): + self.data=data + for i in self.indList: + #i.getAns(data) + i.data=self.data + i.ans=i.getCalculate() + i.figDict=i.getFigDict() + #i.getFig() + def agrigateFig(self): + req=[[]] + + for i in self.indList: + if i.overlayInd==True: + req[0].append(i) + else: + req.append([i]) + CoreDraw.agrigateFig(req,True) + def runAll(self,indList,df,needDraw=False): + self.createIndFromList(indList) + self.calculateInd(df) + if needDraw: + self.agrigateFig() + +class ind_BB(coreIndicator): + + def getCalculate(self): + self.overlayInd=True + ans={} + opMA={'dataType':'ohcl', + 'action':'findMean', + 'actionOptions':{ + 'MeanType':self.options['MeanType'], + 'valueType':self.options['valueType'], + 'window':self.options['window'] + } + } + ans['BB']=CoreTraidMath.CoreMath(self.data,opMA).ans + opSTD={'dataType':'ohcl', + 'action':'findSTD', + 'actionOptions':{'valueType':self.options['valueType'],'window':self.options['window']} + } + ans['STD']=CoreTraidMath.CoreMath(self.data,opSTD).ans + ans['pSTD']=ans['BB']+ans['STD']*self.options['kDev'] + ans['mSTD']=ans['BB']-ans['STD']*self.options['kDev'] + ans['x']=np.array(self.data['date'][self.options['window']-1:].to_list()) + return ans + def getFigDict(self,row=1): + req=[] + + req.append({ + 'vtype':'Scatter', + 'df':pd.DataFrame( + {'value':self.ans['BB'],'date':self.ans['x']}) , + 'row':row, + 'col':1, + 'name':'BB' + + }) + req.append({ + 'vtype':'Scatter', + 'df':pd.DataFrame( + {'value':self.ans['pSTD'],'date':self.ans['x']}) , + 'row':row, + 'col':1, + 'name':'pSTD' + + }) + req.append({ + 'vtype':'Scatter', + 'df':pd.DataFrame( + {'value':self.ans['mSTD'],'date':self.ans['x']}) , + 'row':row, + 'col':1, + 'name':'mSTD' + + }) + + return req + +class ind_OCHL(coreIndicator): + def getCalculate(self): + self.overlayInd=True + def getFigDict(self,row=1): + req=[] + + req.append({ + 'vtype':'OCHL', + 'df':self.data, + 'row':1, + 'col':1, + 'name':'OHCL' + + }) + return req \ No newline at end of file diff --git a/market_trade/core/signals.py b/market_trade/core/signals.py new file mode 100644 index 0000000..c0af03b --- /dev/null +++ b/market_trade/core/signals.py @@ -0,0 +1,194 @@ +import pandas as pd +import datetime +import numpy as np + +import market_trade.core.CoreTraidMath as CoreTraidMath +import market_trade.core.CoreDraw as CoreDraw +from tqdm import tqdm + +from market_trade.core.indicators import * + + +class coreSignalTrande(): + def __init__(self, + data=pd.DataFrame(), + dataType='candel', + mode='online', + batchSize=None, + indParams=None, + signalParams=None, + # needFig=False, + # showOnlyIndex=False, + # drawFig=False, + # equalityGap=0 + ): + + self.data = data.reset_index(drop=True) + self.onlineData = data.reset_index(drop=True) + self.dataType = dataType + self.mode = mode + self.ans = None + self.softAnalizList = np.asarray([]) + self.hardAnalizList = np.asarray([]) + self.analizMetrics = {} + self.indParams = indParams + self.signalParams = signalParams + self.batchSize = batchSize + # self.needFig=needFig + # self.showOnlyIndex=showOnlyIndex + # self.drawFig=drawFig + # self.equalityGap=equalityGap + + # Роутер получения ответа + def getAns(self, data): + # ans='Error: unknown Mode!' + ans = None + print("Start processing...") + if self.mode == 'online': + ans = self.getOnlineAns(data.reset_index(drop=True)) + elif self.mode == 'retro': + ans = self.getRetroAns(data) + elif self.mode == 'retroFast': + ans = self.getRetroFastAns(data) + print("Processing DONE!") + return ans + + # Ретро режим, где расширяется окно добавлением новых элементов + def getRetroAns(self, data): + ans = np.asarray([]) + for i in tqdm(range(self.batchSize, len(data) - 1)): + # self.onlineData=self.data[0:i] + window_data = data[0:i] + window_data.reset_index(drop=True) + ans = np.append(ans, (self.getOnlineAns(window_data))) + self.ans = ans + self.getAnaliz() + self.getMetrix() + return ans + + # Ретро режим, где двигается окно + def getRetroFastAns(self, data): + # print('d - ',data) + ans = np.asarray([]) + for i in tqdm(range(len(data) - 1 - self.batchSize)): + # self.onlineData=self.data[i:i+self.batchSize] + window_data = data[i:i + self.batchSize] + # print('win - ',window_data) + window_data.reset_index(drop=True) + # print('win - ',window_data) + ans = np.append(ans, (self.getOnlineAns(window_data))) + self.ans = ans + self.getAnaliz() + self.getMetrix() + return ans + + # Метод, который будет переопределять каждый дочерний класс + def getOnlineAns(self): + return 'Error' + + def getAnaliz(self): + print("Start analiz...") + for i in (range(len(self.ans))): + sourceValue = self.data[self.signalParams['source']][i + self.batchSize] + targetValue = self.data[self.signalParams['target']][i + self.batchSize + 1] + if (targetValue) > sourceValue: + if self.ans[i] == 1: + self.softAnalizList = np.append(self.softAnalizList, 1) + self.hardAnalizList = np.append(self.hardAnalizList, 1) + elif self.ans[i] == -1: + self.softAnalizList = np.append(self.softAnalizList, -1) + self.hardAnalizList = np.append(self.hardAnalizList, -1) + else: + self.softAnalizList = np.append(self.softAnalizList, 0) + self.hardAnalizList = np.append(self.hardAnalizList, -1) + + elif (targetValue) < sourceValue: + if self.ans[i] == 1: + self.softAnalizList = np.append(self.softAnalizList, -1) + self.hardAnalizList = np.append(self.hardAnalizList, -1) + elif self.ans[i] == -1: + self.softAnalizList = np.append(self.softAnalizList, 1) + self.hardAnalizList = np.append(self.hardAnalizList, 1) + else: + self.softAnalizList = np.append(self.softAnalizList, 0) + self.hardAnalizList = np.append(self.hardAnalizList, -1) + else: + if self.ans[i] == 1: + self.softAnalizList = np.append(self.softAnalizList, -1) + self.hardAnalizList = np.append(self.hardAnalizList, -1) + elif self.ans[i] == -1: + self.softAnalizList = np.append(self.softAnalizList, -1) + self.hardAnalizList = np.append(self.hardAnalizList, -1) + else: + self.softAnalizList = np.append(self.softAnalizList, 0) + self.hardAnalizList = np.append(self.hardAnalizList, 1) + print("Analiz DONE!") + return 0 + + def getMeteixDict(self, d): + ''' + 1 - (сбывшиеся + несбывшиеся) \ (сбывшиеся + несбывшиеся +0) + 2 - (сбывшиеся - несбывшиеся) \ (сбывшиеся + несбывшиеся +0) + ''' + return { + + '1': (d['1'] + d['-1']) / (d['1'] + d['-1'] + d['0']), + '2': (d['1'] - d['-1']) / (d['1'] + d['-1'] + d['0']), + + } + + def getMetrix(self): + + softAnalizCount = {'-1': 0, '0': 0, '1': 0} + hardAnalizCount = {'-1': 0, '0': 0, '1': 0} + for i in range(len(self.softAnalizList)): + softAnalizCount[str(int(self.softAnalizList[i]))] += 1 + hardAnalizCount[str(int(self.hardAnalizList[i]))] += 1 + self.analizMetrics = {'softAnaliz': self.getMeteixDict(softAnalizCount), + 'hardAnaliz': self.getMeteixDict(hardAnalizCount) + } + + +class signal_BB(coreSignalTrande): + + def __init__(self, + data=pd.DataFrame(), + dataType='candel', + mode='online', + batchSize=None, + indParams=None, + signalParams=None, + ): + super().__init__( + data=data, + dataType=dataType, + mode=mode, + batchSize=batchSize, + indParams=indParams, + signalParams=signalParams, + ) + + if self.indParams == None: + indParams = {'MeanType': 'SMA', 'window': 15, 'valueType': 'low', 'kDev': 2} + else: + indParams = self.indParams + self.BB = ind_BB( + data=data, + options=indParams, + ) + + def getOnlineAns(self, data): + ans = 0 + # print(data) + + self.BB.getAns(data) + # print(BB) + lastValue = data[self.signalParams['source']].to_list()[-1] + if lastValue > self.BB.ans['pSTD'][-1]: + ans = -1 + elif lastValue < self.BB.ans['mSTD'][-1]: + ans = +1 + else: + ans = 0 + + return ans