Você está na página 1de 19

7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

(/home)

views)Casa (/) Q & A Registro |

s.refinitiv.com/iam/login?
Crie gatilhos e sinais de análise técnica
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)

usando a API de dados Eikon 

Umer Nalla

Criado: 11 de março de 2020


APIs de dados Eikon (/articles-samples?
Atualizado: 8 de abril de 2020
tid_36%5B%5D=1898) API do Messenger BOT
(/articles-samples?tid_36%5B%5D=2171)
Análise técnica (/articles-samples?
tid_36%5B%5D=2172) RSI (/articles-
samples?tid_36%5B%5D=2187) Estocásticos
(/articles-samples?tid_36%5B%5D=2188)
SMA (/articles-samples?
tid_36%5B%5D=2189) APIs de dados Eikon
(https://community.developers.refinitiv.com/spaces/92/index.html)
Pitão (/articles-samples?
tid_23%5B%5D=1761)

Visão (/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api)

Fluxo de trabalho de análise técnica


De acordo com a Investopedia, 'Technical Analysis é uma disciplina de negociação empregada para
avaliar investimentos e identificar oportunidades de negociação, analisando tendências estatísticas
coletadas da atividade de negociação, como movimento e volume de preços' . Afirma ainda que "os
analistas técnicos se concentram nos padrões de movimentos de preços, sinais de negociação ... para
avaliar a força ou fraqueza de um título" .
De acordo com os vários artigos, etc., que li, três dos indicadores de AT mais usados são:
Médias Móveis Simples
Índice de Força Relativa
Oscilador Estocástico

Investidores e comerciantes que usam a Análise técnica como parte de sua estratégia de negociação
podem consultar os gráficos de AT regularmente para ajudar a determinar suas opções de
investimento.

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 1/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

Neste fluxo de trabalho, vou experimentar como posso usar esses indicadores para gerar sinais de
(/home)
negociação de compra ou venda. Existem vários artigos na internet que tentam a mesma coisa -
geralmente focando em um único indicador - e a maioria deles executa a análise de dados históricos,
apresenta os resultados históricos e pára por aí.
views) Q&A Registro |
No entanto, para esse fluxo de trabalho, quero dar um passo adiante, continuando a executar a análise
continuamente em um intervalo configurado - por exemplo, a cada minuto, hora, dia (observei o uso de
s.refinitiv.com/iam/login?
dados de ticks em tempo real, mas isso foi apontado exceto que isso não faz muito sentido do ponto
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
de vista da análise técnica - porque os ticks não ocorrem em intervalos regulares).

Além disso, quando um sinal de negociação é gerado, usarei um BOT de bate-papo para postar os
detalhes do sinal em uma sala de bate-papo notificando os usuários - economizando o esforço de
interrogar frequentemente os gráficos.
Eu tenho acesso ao aplicativo de área de trabalho Refinitiv Eikon, por isso usarei sua API de dados, que
pode acessar dados históricos, de referência e de streaming em tempo real. Também utilizarei funções
de conversão de simbologia para converter ISINs em RIC (Reuters Instrument Codes) para solicitar os
vários dados. Além disso, usarei a API BOT (http://developers.refinitiv.com/messenger-api) do Refinitiv
Messenger (http://developers.refinitiv.com/messenger-api) para postar uma mensagem em uma sala
de chat do Refinitiv (Eikon) Messenger - sem dúvida, isso pode ser facilmente substituído por alguma
outra forma de mensagem. 

Antes de prosseguirmos, devo mencionar que sou relativamente novo na Eikon Data API e no próprio
Python - para que você possa encontrar algumas maneiras 'não muito pitonicas' de fazer as coisas. Se
você encontrar alguns casos que fazem fronteira com o sacrilégio (no mundo Python), avise-me e
tentarei alterar o código incorreto (estou trabalhando na lower_case_with_underscores convenção de
nomenclatura - mas como desenvolvedor Java / C ++ há muito tempo, ainda não existe !).

TA-Lib: Biblioteca de análise técnica


Quando comecei, estava usando vários scripts / trechos de Python que encontrei on-line para calcular
meus indicadores e depois me perguntando o quão precisos eles podem ser. Depois de gastar
(desperdiçando?) Um tempo considerável testando e se preocupando com a veracidade desses
trechos, um colega (obrigado Jason!) Mencionou que já existia um wrapper Python - ta-lib
(https://github.com/mrjbq7/ta-lib) - para a conhecida Biblioteca de Análise Técnica - TA- Lib (https://ta-
lib.org/hdr_doc.html) . É claro - sendo este Python, haveria uma biblioteca para ele (lembre-se - Python
noob)!

Importar nossas bibliotecas


Acho que devo mencionar as versões de algumas das principais bibliotecas que instalei - caso você
tenha algum problema:

eikon - 1.1.3 a0
pandas - 1.0.0
numpy - 1.18.1
talib - 0.4.17
matplotlib - 3.1.3

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 2/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

Eu usei uma versão alfa da eikon biblioteca porque queria testá-la e também por causa da pandas.np
deprecation warnings  . Se você tiver o v1.1.2 oficial instalado, (/home)
ele ainda deve funcionar bem e você
pode apenas import warnings usar warnings.filterwarnings("ignore") a biblioteca e usá-lo para
suprimi-los.
views) Q&A Registro |
Se você estiver trabalhando no Windows e decidir construir os binários TA-Lib (em vez de fazer o
s.refinitiv.com/iam/login?
download dos binários pré-criados), preste atenção às instruções sobre como mover a pasta (caso
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
contrário, você pode estar coçando a cabeça por que ela não será construída corretamente) !

Para enviar mensagens para o RM Chatroom Eu estou usando o existente API Mensageiro BOT 
exemplo MessengerChatBot.Python (https://github.com/Refinitiv-API-
Samples/Example.MessengerChatBot.Python) de Github - detalhes são fornecidos no site.

Snippets de código-chave
Como há uma quantidade considerável de código envolvida, vou omitir grande parte do código aqui e
principalmente mostrar apenas trechos de código-chave - consulte o repositório
(https://github.com/Refinitiv-API-Samples/Workflow.EikonAPI.Python.TechnicalAnalysis) do Github
(https://github.com/Refinitiv-API-Samples/Workflow.EikonAPI.Python.TechnicalAnalysis)  para obter o
código-fonte completo.

Então, deixe-me continuar com o código - na seguinte ordem:


várias funções auxiliares para a AT, cronograma e plotagem de gráficos
a seção de controle principal
terminando com o ciclo de análise em andamento.

Médias Móveis Simples


Essa função usa a função TA-Lib SMA para calcular a Média Móvel Simples usando o preço de
fechamento por dois períodos - que você notará posteriormente são 14 no curto período e 200 no
longo período. Como você verá mais adiante, o intervalo do período em si pode variar, por exemplo,
minutos, diariamente, mensalmente, a cada hora - assim, por exemplo, calcule o SMA por 14 e 200
dias.
Com as SMAs calculadas, ele usa a seguinte lógica para gerar sinais de Compra e Venda:
Se o curto período da SMA passar pelo longo período da SMA, esse é um sinal de compra
Se o curto período da SMA passar pelo longo período da SMA, esse é um sinal de venda

def SMA(close,sPeriod,lPeriod):
shortSMA = ta.SMA(close,sPeriod)
longSMA = ta.SMA(close,lPeriod)
smaSell = ((shortSMA <= longSMA) & (shortSMA.shift(1) >= longSMA.shift(1)))
smaBuy = ((shortSMA >= longSMA) & (shortSMA.shift(1) <= longSMA.shift(1)))
return smaSell,smaBuy,shortSMA,longSMA

As séries smaSell e smaBuy conterão a data / hora e um sinalizador para indicar um sinal, por
exemplo, para um intervalo diário

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 3/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

Date (/home)
2018-02-15 False
2018-02-16 False
2018-02-19 True
views) 2018-02-20
Q&A False
Registro |

s.refinitiv.com/iam/login?
Índice de Força Relativa
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
O cálculo do RSI geralmente é feito por um período de 14 dias - então, mais uma vez, eu introduzo o
preço de fechamento do instrumento na função RSI TA-Lib. A metodologia comum é estabelecer 
limites altos e baixos do RSI em 70 e 30. A idéia é que, se o limite mais baixo for ultrapassado, o ativo
estará se vendendo demais e devemos comprar. Por outro lado, se o limite superior for ultrapassado, o
ativo estará sobrecomprado e deveremos vender.

def RSI(close,timePeriod):
rsi = ta.RSI(close,timePeriod)
rsiSell = (rsi>70) & (rsi.shift(1)<=70)
rsiBuy = (rsi<30) & (rsi.shift(1)>=30)
return rsiSell,rsiBuy, rsi

De acordo com minha função SMA, minha função RSI também retorna uma série contendo data / hora
e um sinalizador para indicar sinais de compra / venda

Estocásticos
A função TA-Lib Stoch retorna duas linhas slowk e slowd que podem ser usadas para gerar os
indicadores de compra / venda. Um sinal de cruzamento ocorre quando as duas linhas cruzam na
região de sobrecompra (geralmente acima de 80) ou região de sobrevenda (geralmente abaixo de 20).
Quando uma linha slowk cruza abaixo da linha slowd na região de sobrecompra, é considerada um
indicador de venda. Por outro lado, quando uma linha slowk crescente cruza acima da linha slowd na
região de sobrevenda, é considerada um indicador de compra.

def Stoch(close,high,low):
slowk, slowd = ta.STOCH(high, low, close)
stochSell = ((slowk < slowd) & (slowk.shift(1) > slowd.shift(1))) & (slowd > 80)
stochBuy = ((slowk > slowd) & (slowk.shift(1) < slowd.shift(1))) & (slowd < 20)
return stochSell,stochBuy, slowk,slowd

Temos um sinal comercial - envie-o para a sala de bate-papo!


Preciso de uma maneira de informar aos usuários que um sinal de troca foi gerado pela análise
técnica. Então, vou usar a API do Messenger BOT para enviar mensagens para outros usuários do
Refinitiv Messenger. Estou propondo novamente o exemplo existente do MessengerChatBot.Python
(https://github.com/Refinitiv-API-Samples/Example.MessengerChatBot.Python) do GitHub.

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 4/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

# Key code snippets - see Github for full source (/home)


def sendSignaltoChatBot(myRIC, signalTime, indicators):
indicatorList = ','.join(indicators.values)
message = f"TA signal(s) Generated : {indicatorList} at {signalTime} for {myRIC}"
views) # QConnect,
&A login and |send message to chatbot
Registro
rdp_token = RDPTokenManagement( bot_username, bot_password, app_key)
access_token = cdr.authen_rdp(rdp_token)
s.refinitiv.com/iam/login?
if access_token:
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
# Join associated Chatroom
joined_rooms = cdr.join_chatroom(access_token, chatroom_id)
if joined_rooms:

cdr.post_message_to_chatroom(access_token, joined_rooms, chatroom_id, message)

Execute a análise técnica


Inicialmente, farei uma execução histórica da AT, depois da qual utilizarei esta função para executar as
3 metodologias de AT acima nos dados que obtiver como parte da Análise Técnica em andamento.

Vou repetir parte desse código posteriormente no principal loop histórico de execução do TA - apenas
para facilitar a leitura.

def runAllTA(myRIC, data):

price = data['CLOSE']
high = data['HIGH']
low = data['LOW']

# Simple Moving Average calcs


smaSell,smaBuy,shortSMA,longSMA = SMA(price,shortPeriod,longPeriod)
# Do the RSI calcs
rsiSell,rsiBuy,rsi = RSI(price,shortPeriod)
# and now the stochastics
stochSell,stochBuy,slowk,slowd = Stoch(price, high, low)

# Now collect buy and sell Signal timestamps into a single df


sigTimeStamps = pd.concat([smaSell, smaBuy, stochSell, stochBuy, rsiSell, rsiBuy],axis=1)
sigTimeStamps.columns=['SMA Sell','SMA Buy','Stoch Sell','Stoch Buy','RSI Sell','RSI Buy']
signals = sigTimeStamps.loc[sigTimeStamps['SMA Sell'] | sigTimeStamps['Stoch Sell'] |
sigTimeStamps['RSI Sell'] | sigTimeStamps['SMA Buy'] |
sigTimeStamps['Stoch Buy'] | sigTimeStamps['RSI Buy']]

# Compare final signal Timestamp with latest data TimeStamp


if (data.index[-1]==signals.index[-1]):
final = signals.iloc[-1]
# filter out the signals set to True and send to ChatBot
signal = final.loc[final]
signalTime = signal.name.strftime("%Y-%m-%dT%H:%M:%S")
indicators = signal.loc[signal].index
sendSignaltoChatBot(myRIC, signalTime, indicators)

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 5/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

Se o registro de data e hora do sinal TA final corresponder ao registro de data e hora mais recente -
então temos um ou mais novos sinais de negociação - informe (/home)
os usuários do Chatroom por meio do
Chat BOT.

Funções auxiliares de temporização


views) Q&A Registro |
Também preciso de algumas funções auxiliares para calcular alguns valores de tempo com base no
s.refinitiv.com/iam/login?
intervalo selecionado - o principal é ...
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)

# Calculate Start and End time for our historical data request window
def startEnd(interval):

end = datetime.now()
start = {
'minute': lambda end: end - relativedelta(days=5),
'hour': lambda end: end - relativedelta(months=2),
'daily': lambda end: end - relativedelta(years=2),
'weekly': lambda end: end - relativedelta(years=5),
'monthly': lambda end: end - relativedelta(years=10),
}[interval](end)
return start.strftime("%Y-%m-%dT%H:%M:%S"),end.strftime("%Y-%m-%dT%H:%M:%S")

Funções de plotagem
Embora não seja essencial para o fluxo de trabalho, eu queria traçar alguns gráficos para fornecer uma
representação visual dos vários indicadores de AT - para que possamos tentar visualmente vincular as
instâncias em que um preço aumenta ou diminui de acordo com o sinal de negociação de AT - por
exemplo, quando o curto SMA cruza o longo SMA, vemos uma tendência de alta no preço após esse
momento?

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 6/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

# As per before, key code snips only... (/home)

# Use a formatter to remove weekends from date axis


# to smooth out the line.
views) class QMyFormatter(Formatter):
&A Registro |
def __init__(self, dates, fmt='%Y-%m-%d'):
self.dates = dates
s.refinitiv.com/iam/login?
self.fmt = fmt
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
def __call__(self, x, pos=0):
'Return the label for time x at position pos'
ind = int(round(x))

if ind>=len(self.dates) or ind<0: return ''
return self.dates[ind].strftime(self.fmt)

# Plot the Close price and short and long Simple Moving Averages
def plotSMAs(ric,close,sma14,sma200,sell,buy):
x = close.index
plt.rcParams["figure.figsize"] = (28,8)
fig, ax = plt.subplots(facecolor='0.25')
ax.plot(np.arange(len(x)),close, label='Close',color='y')
ax.plot(np.arange(len(x)),sma14,label="SMA 14", color='g')
ax.plot(np.arange(len(x)),sma200,label="SMA 200", color='tab:purple')
plt.show()

# Plot the Close price in the top chart and RSI in the lower chart
def plotRSI(ric,close,rsi):
plt.rcParams["figure.figsize"] = (28,12)
fig = plt.figure(facecolor='0.25')
gs1 = gridspec.GridSpec(2, 1)
# RSI chart
ax = fig.add_subplot(gs1[1])
ax.xaxis.set_major_formatter(formatter)
ax.plot(np.arange(len(rsi.index)), rsi.values,color='b')
plt.axhline(y=70, color='w',linestyle='--')
plt.axhline(y=30, color='w',linestyle='--')
# Close Price chart
axc = fig.add_subplot(gs1[0])
axc.plot(np.arange(len(rsi.index)), close, color='y')
plt.show()

# Plot Close price in top chart and in the slowk + slowd lines in lower chart
def plotStoch(ric,close,slowK,slowD):
plt.rcParams["figure.figsize"] = (28,12)
fig = plt.figure(facecolor='0.25')
gs1 = gridspec.GridSpec(2, 1)
ax = fig.add_subplot(gs1[1])
# Stochastic lines chart
ax.plot(np.arange(len(slowk.index)), slowk.values,label="Slow K",color='m')
ax.plot(np.arange(len(slowk.index)), slowd.values,label="Slow D",color='g')
plt.axhline(y=80, color='w',linestyle='--')
plt.axhline(y=20, color='w',linestyle='--')
# Closing price chart
axc = fig.add_subplot(gs1[0])
axc.plot(np.arange(len(close.index)), close, color='y')
plt.show()

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 7/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

Então, essas são as funções auxiliares fora do caminho - vamos(/home)


para a seção de controle principal

Conectando-se ao aplicativo Eikon


views) Q&A
Para conectar-me àRegistro |
minha instância em execução do Eikon (ou Espaço de Trabalho), preciso fornecer
minha Chave do Aplicativo.
s.refinitiv.com/iam/login?
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
ek.__version__
ek.set_app_key('<your app key>')

Algum código de inicialização


I need to calculate the start and end date for my price query - based on the chosen periodicity/interval,
as well as specify the periods for moving averages.

Also, as I will be requesting the price of each instrument individually, I create a container to hold all the
price data for the full basket of instruments.

Finally, I set some display properties for the Pandas dataframe.

myInterval = 'daily' # 'minute', 'hour', 'daily', 'weekly', 'monthly'


myStart, myEnd = startEnd(myInterval)
timestampLen = timeStampLength(myInterval)
print(f'Interval {myInterval} from {myStart} to {myEnd} : Timestamp Length {timestampLen}')
shortPeriod = 14
longPeriod = 200
basket={}
# Do we want to plot charts?
plotCharts = True
# Dataframe display setting
pd.set_option("display.max_rows", 999)
pd.set_option('precision', 3)

Interval daily from 2018-03-11T11:08:38 to 2020-03-11T11:08:38 : Timestamp Length 10

TA Analysis summary output


Once the initial historical TA has been run, I want to present a summary table of the signal over that
period.

For this, I am going to use a Dataframe to output the results in a readable format.

I am also creating some blank columns which I will use for padding the dataframe later.

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 8/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

outputDF = pd.DataFrame(columns=['RIC','Name','ISIN','Close','Periodicity','Intervals
(/home) Up',
'Intervals Down','Unchanged','1wk %ch','1M %ch','YTD %ch','6M %c
h',
'1yr %ch','SMA Sell','SMA Buy','Stoch Sell','Stoch Buy','RSI Sel
views) l', 'RSI
Q&ABuy' ]) Registro |
blankSignalCols = ['N/A']*6
blankNonSignalCols = [' ']*13
s.refinitiv.com/iam/login?
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
Convert my ISIN symbols to RICs

Whilst Eikon can accept various Symbology types for certain interactions, I need to specify RICs
(Reuters Instrument Code) for much of the data I intend to access.

Therefore, I could just start with a bunch of RICs - but not everyone works with RICs - so here is an
example of symbology conversion at work.

myISINs = [
'GB0002634946',
'GB00B1YW4409'
]
myRICs = ek.get_symbology(myISINs, from_symbol_type='ISIN', to_symbol_type='RIC')

Just for your reference, the get_symbology function can accept from and to symbol types of
CUSIP
ISIN
SEDOL
RIC
ticker
lipperID
IMO
In addition, you can also convert to the 'OAPermID' type.

Snapshot some summary data values


Once I have run the TA I want to present a summary table reflecting the price changes for each
instrument over various periods such as a week, month, year etc - along with the TA results.

So, for this, I am using the get_data method to obtain various Percent price change values as well the
name of the corporate entity and the most recent Closing price

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 9/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

listRICs = list(myRICs.RIC) (/home)


pcts, err = ek.get_data(
instruments = listRICs,
fields = [
views) Q &'TR.CommonName',
A Registro |
'TR.CLOSEPRICE',
'TR.PricePctChgWTD',
s.refinitiv.com/iam/login?
'TR.PricePctChgMTD',
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
'TR.PricePctChgYTD',
'TR.PricePctChg6M',
'TR.PricePctChg1Y',

]
)
pcts.set_index('Instrument',inplace=True)

In the above call, I am requesting each instrument's per cent Price change for Week, Month and Year to
Date - and the 6m and 1yr period as well.

Putting it all together for our initial 'historical' analysis run


I can now go ahead and request my historical data and perform the Technical Analysis.

As well as interval data at the minute, hour, daily etc Eikon product can also provide tick data - i.e.
individual trades as well as Bid//Ask changes. However, there are some differences in the data set for
tick data compared to the other intervals:
Historical tick data will be indexed on the date+time of every tick - and therefore the index can
vary across instruments
Intervalised data will be indexed according to the interval e.g. every minute, hour etc and therefore
use the same index values across multiple instruments
I can get high, low prices for interval data (which is needed for the Stochastic TA) but not for tick
data
As you can see, since the tick data is not interval based, it does not make sense from a TA point of view.
For interval data, I can specify multiple RICs in the get_timeseries call and get back a single
dataframe with the prices for all the RICs. However, to make the code easier to read, I will loop through
the RICs and request each one individually rather than slightly increased subsequent complication
involved if I have to use a single dataframe containing all the data.
I have split the following section of code into smaller chunks for ease of reading and annotations.
For each RIC code in our list, the first thing I do is use the  get_timeseries  function to request a subset
of fields at the specified Interval for the previously calculated time period.

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 10/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

for ISIN, symb in myRICs.iterrows(): (/home)


myRIC=symb['RIC']
data = ek.get_timeseries(myRIC,
fields = ['CLOSE','HIGH','LOW'],
views) Q &start_date=myStart,
A Registro |
end_date=myEnd,
interval = myInterval)
s.refinitiv.com/iam/login?
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
price = data['CLOSE']
high = data['HIGH']
low = data['LOW']

basket[myRIC]=data # Save each instrument's raw data for later use

Next, I calculate values for Price Up, Down and no change movements for the analysis period. Then I
call the various TA functions to calculate the indicators and generate the signals (& plot charts if
enabled).

# Count Price Up, Down and No change


upCnt = (price < price.shift(1)).value_counts().loc[True]
downCnt = (price > price.shift(1)).value_counts().loc[True]
try:
ncCnt = (price == price.shift(1)).value_counts().loc[True]
except KeyError as e:
ncCnt = 0

# Do the Simple Moving Average calcs


smaSell,smaBuy,shortSMA,longSMA = SMA(price,shortPeriod,longPeriod)
if plotCharts:
plotSMAs(myRIC,price,shortSMA,longSMA,smaSell,smaBuy)

# Do the RSI calcs


rsiSell,rsiBuy,rsi = RSI(price,shortPeriod)
if plotCharts:
plotRSI(myRIC,price,rsi)

# Stochastic calcs
stochSell,stochBuy,slowk,slowd = Stoch(price, high, low)
if plotCharts:
plotStoch(myRIC,price,slowk,slowd)

# Get the Percent Change data for thisRIC


pct = pcts.loc[myRIC]

Finally, I use the data and signals etc to generate a dataframe displaying a Summary Table of the
various stats + any signals generated for our configured TA time period and interval.

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 11/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

# Now we build the summary table (/home)


# starting with the non-trade signal related stuff
nonSignalData = [myRIC,
pct['Company Common Name'],
views) Q&A Registro |ISIN,
pct['Close Price'],
s.refinitiv.com/iam/login? myInterval,
upCnt,downCnt,ncCnt,
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
pct['WTD Price PCT Change'],
pct['MTD Price PCT Change'],
pct['YTD Price PCT Change'],

pct['6-month Price PCT Change'],
pct['1-year Price PCT Change']]

# Now build the Signal buy and sell columns for each TA indicator
sigTimeStamps = pd.concat([smaSell, smaBuy, stochSell, stochBuy, rsiSell, rsiBuy],axis=1)
sigTimeStamps.columns=['SMA Sell','SMA Buy','Stoch Sell','Stoch Buy','RSI Sell','RSI Buy']
signals = sigTimeStamps.loc[sigTimeStamps['SMA Sell'] | sigTimeStamps['Stoch Sell'] |
sigTimeStamps['RSI Sell'] | sigTimeStamps['SMA Buy'] |
sigTimeStamps['Stoch Buy'] | sigTimeStamps['RSI Buy']]

# If any trade signals were generated for our time period


# add them to the summary table
signalCnt = len(signals)
if (signalCnt):
first = True
for index,row in signals.iterrows():
sigDate = str(index)[0:timestampLen]
signalList = [sigDate if item else "" for item in row]
# First row to contain non-signal stuff, subsequent rows only trade signals
tempRow = nonSignalData.copy() if first else blankNonSignalCols.copy()
tempRow.extend(signalList)
s = pd.Series(tempRow, index=outputDF.columns)
outputDF = outputDF.append(s,ignore_index=True)
first=False
else: # No signals so just the non-signal related stuff
tempRow = nonSignalData.copy()
tempRow.extend(blankSignalCols)
outputDF = outputDF.append(tempRow)

outputDF.head(5)
outputDF.tail(5)

Once that is done, I simply display the head and tail of the Summary Table.
Before we get to the table, let us have a quick look at the charts I plotted and compare them to the
subset of TA signals in the table displayed further down. 

Here I have included

the SMA, RSI and Stochastic charts for the final RIC - III.L
the head of the outputDF  dataframe - showing the first few trading signals for BAE Systems
(BAES.L)
the tail of the  outputDF  dataframe which represents the final few signals for 3I Group (III.L).

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 12/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

Simple Moving Average chart for 3I Group PLC - III.L


(/home)

views) Q&A Registro |

s.refinitiv.com/iam/login?
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)

Towards the end of the Simple Moving Average chart, you can see that the SMA14 crosses down
through the SMA200 line which is a sell indicator - and if you refer to the tail end of the Summary table
below you will see an SMA Sell indicator for the 5th of March 2020.

Relative Strength Index chart for 3I Group PLC - III.L

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 13/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

(/home)

views) Q&A Registro |

s.refinitiv.com/iam/login?
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)

Here I am plotting the Close price in the upper chart and the RSI value in the lower chart. Just at the tail
end, you can see that the RSI value crosses below the lower threshold twice around the end of Feb /
start of March - which corresponds to the RSI Buy indicators on 2020-02-27 and 2020-03-05 in the
Summary table below

Stochastics chart for 3I Group PLC - III.L

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 14/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

(/home)

views) Q&A Registro |

s.refinitiv.com/iam/login?
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)

Once again I am plotting the Close price on top and the Stochastics slowk and slowd lines in the lower
chart. You can see that the slowk line crosses above the slowd line in the oversold region (below 20) on
two occasions - i.e. buy indicators reflected in the summary table below with Stochastic Buy entries
for 2020-02-28 and 2020-03-03.

Historical Summary table


After the initial Technical Analysis run using the historical data, I output a historical Summary table with
some basic stats as well as the history of the Trade signals for the configured Interval and Time Period.

For the basic stats, I display the Percent change for various periods such as Week to Day, Month to Day,
6 months - to provide an indication of just how the particular stock has been trading over those periods.
I also display the number of intervals where the price has gone up, down or no change as potentially
useful reference points.

The rightmost columns of the table contain the Buy and Sell signals occurrences for the 3 TA
methodologies - one row for each date/time that triggered a signal - you may occasionally see more
than one signal in a single row. For example, whilst I was testing both RSI and Stoch indicated Buy
https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 15/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

signals on 11th October 2018 for the 3i Group (III.L) - concerning this, you may find the Reuters 3 yr
(/home)
chart for III (https://www.reuters.com/companies/III.L/charts) interesting...

Head of the Summary table - showing the first few trading signals for BAE Systems (BAES.L)
views) Q&A Registro |
Intervals Intervals 1wk 1M YTD 6M 1yr
RIC Name ISIN
s.refinitiv.com/iam/login?
Close Periodicity Unchanged
Up Down %ch %ch %ch %ch %ch
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
BAE
BAES.L Systems GB0002634946551 daily 231 268 7 -7.77-9.47-2.48-3.0318.5

PLC

                         

                         

                         

                         

The tail of the Summary table - showing the most recent trading signals for 3I Group (III.L)

Intervals Intervals 1wk 1M YTD 6M 1yr SMA


RIC Name ISIN Close Periodicity Unchanged
Up Down %ch %ch %ch %ch %ch Sell
3i
III.L Group GB00B1YW4409863 daily 237 262 7 -7.29-14.4-21.4-23.5-8.45 
PLC
                           

                           

                           

                           

2020
                         
03-0

Note how the final few signals compare with the crossover points on the corresponding charts.

Ongoing Technical Analysis


Now that I have the historical analysis out of the way, I will move onto the ongoing 'real-time' analysis.
In other words, the code that I can keep running to perform the TA on an ongoing basis at the
configured interval.

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 16/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

while True: (/home)


gotoSleep(myInterval)
for myRIC in listRICs:
historical = basket[myRIC]
views) Q &latest
A = Registro
ek.get_timeseries(myRIC,fields
| = ['CLOSE','HIGH','LOW'],
count = 1, interval = myInterval)
# Delete earliest data point
s.refinitiv.com/iam/login?
historical.drop(historical.index[0])
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
# Append latest data point
historical = historical.append(latest)
runAllTA(myRIC, historical)

# Udpate basket with latest values
basket[myRIC] = historical

I put the script to sleep for our configured interval, and when it wakes I request the latest data points for
each RIC.

The simplest approach would be to just make the above get_timeseries calls with a revised
start_date and end_date parameters. However, this would be quite wasteful of resources and so I
will request just the latest data point for my configured interval.

To do this, I make the call with count=1 (rather than Start/End times) to get just the latest data point. I
then drop the earliest data point from our historical data points and append the latest one.

I can then invoke the Technical Analysis with the most recent data included.

Closing Summary
I could now leave this script running with my preferred interval and it will send messages to the
chatroom, each time the Technical Analysis yields a Buy or Sell signal, like the ones shown below:

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 17/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY
Note: For the purpose of the above screen capture, I did a run with the interval set to 'minute' - in an attempt to generate signals sooner rather
than later.
(/home)
For a trader who uses Simple Moving Average, Relative Strength Indices and/or Stochastic charts to
help inform their trading decisions - this could mean they don't need to actively sit there eyeballing
charts allQ day
views) & A long. Registro |
I hope you found this exercise useful and no doubt there are many possible improvements/refinements
s.refinitiv.com/iam/login?
that could be made to both the code and the simple TA methodology I have used. A few examples to
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)
consider are:
In the Summary table extract above I can see that on 2020-03-05, SMA based TA is indicating a
Sell whereas the RSI based TA is indicating a Buy - which suggests that further refinements are
required
An RSI related article I read, suggested that once the line crosses a threshold it may be better to
wait till it crosses back in the opposite direction before generating a signal - so for example, if the
crosses below %30, wait till it crosses back up above 30% before generating a Buy signal.
In my summary output table, I show the '% change' for a week, month, year etc - which could
be relevant for my 'daily' interval-based TA - but not so much if say I used an 'hourly' interval. My
colleague (Jason again) suggested that a better approach could be to show '% change' values for
say, Hour t, Hour t+1, t+5, t+10 etc according to my chosen interval.
Another improvement could be to show up/down markers on the plot lines highlighting the
crossover points.
As you can expect, there is no shortage of material on Technical Analysis to be found on the internet.

NOTE: I do not endorse the above workflow as something that should be used for active trading - it is
purely an educational example.

References
Eikon Data API (https://developers.refinitiv.com/eikon-apis/eikon-data-api)
Refinitiv Messenger API (https://developers.refinitiv.com/messenger-api)

MessengerChatBot (https://github.com/Refinitiv-API-Samples/Example.MessengerChatBot.Python) -
Python Example for Messenger API

TA-Lib (https://ta-lib.org/hdr_doc.html) - Open Source Technical Analysis Library


ta-lib (https://github.com/mrjbq7/ta-lib) - Python wrapper for above TA-Lib

 
 

DOWNLOADS

 Workflow.EikonAPI.Python.TechnicalAnalysis  GitHub
(https://github.com/Refinitiv-API-Samples/Workflow.EikonAPI.Python.TechnicalAnalysis)

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 18/19
7/24/2020 Create Technical Analysis triggers and signals using the Eikon Data API | DEVELOPER COMMUNITY

 Example.MessengerChatBot.Python  GitHub
(/home)
(https://github.com/Refinitiv-API-Samples/Example.MessengerChatBot.Python)

ADD YOUR
views) Q&A COMMENT
Registro |

s.refinitiv.com/iam/login?
You need to Login to add a comment.
UvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWFwaQ%3D%3D)

Already have a user name and password? Click here to login now (/iam/login? 
th=L2FydGljbGUvY3JlYXRlLXRlY2huaWNhbC1hbmFseXNpcy10cmlnZ2Vycy1hbmQtc2lnbmFscy11c2luZy1laWtvbi1kYXRhLWF

here (https://login.thomsonreuters.com/iamui/UI/createUser?app_id=DevPlatform&realm=DevPlatform) to register and log

+ Add Comment

Feedback (https://developers.refinitiv.com/feedback?previous=node/90202)

Technical Requirements (/technical-requirements)


(http://refinitiv.com/)

Copyright (https://www.refinitiv.com/en/policies/copyright-notice)

Cookie Policy (https://www.refinitiv.com/en/policies/privacy-statement#cookies)

Privacy Statement (https://www.refinitiv.com/en/policies/privacy-statement)

Terms of Use (/terms-use)

Do not sell my info (https://privacyportalde-


cdn.onetrust.com/dsarwebform/5f7a2da0-bed0-45e8-ac2c-
c1f297e2efdc/1234b4c9-a981-4092-b398-cb80005998cf.html)

https://developers.refinitiv.com/article/create-technical-analysis-triggers-and-signals-using-eikon-data-api 19/19