new files for indicators and signals
This commit is contained in:
parent
3525d05a11
commit
20f8b1a682
159
market_trade/core/indicators.py
Normal file
159
market_trade/core/indicators.py
Normal file
@ -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
|
||||||
194
market_trade/core/signals.py
Normal file
194
market_trade/core/signals.py
Normal file
@ -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
|
||||||
Loading…
x
Reference in New Issue
Block a user