Currency Flow Meter

June 1, 2019

This routine generates visualizations of the strength of currency flows. It scores each major currency as an 'inflow' or an 'outflow' by comparing them against each of the other major currencies. If a currency has large inflow, the score will be positive (+7 maximum), and if a currency has large outflow, then the score will be negative (-7 minimum) - the closer the score is to 0, the more indecisive the indicator - the currency likely has not moved much. This gives us an idea of where the big money is moving across the foreign exchange markets. Thanks to Urban Forex for the idea & iOS product version.

Assumptions

  • Simple trend indicator will suffice in determining the direction of the flow

References:
[0] FX Meter from Urban Forex https://www.youtube.com/watch?v=daLYdzGg56s

In [1]:
import sys
sys.path.append('../04_systems/')
from framework import oanda
import pandas as pd
import oandapyV20
import oandapyV20.endpoints.instruments as instruments
from talib import EMA
import matplotlib.pyplot as plt
import seaborn as sns

Oanda API configuration & interfacing

In [2]:
def exampleAuth():
    accountID, access_token = None, None
    with open("../../config/practice-account.txt") as I:
        accountID = I.read().strip()
    with open("../../config/practice-token.txt") as I:
        access_token = I.read().strip()
    return accountID, access_token

def getOandaData(bar_count, granularity, instrument):
    """pulls specified data from Oanda api"""
    accountID, access_token = exampleAuth()
    client = oandapyV20.API(access_token=access_token)
    params = {
              "count": bar_count,
              "granularity": granularity
    }
    r = instruments.InstrumentsCandles(instrument=instrument,
                                      params=params)
    response = client.request(r)
    return response

Iteration routine to retrieve strength score

In [3]:
def getStrengthScore(granularity, inst_dict, ema):
    '''Input desired granularity and the desired list of currency pairs. Return the score between -7 and 7'''

    target = inst_dict['target']
    inst_list = inst_dict['list']
    str_score = int()
    bar_count = ema + 3
    for inst in inst_list:
        #data = getOandaData(20,'D','USD_CAD')
        #df = oanda.preprocessOanda(data)
        base = inst[4:]
        counter = inst[:-4]

        data = getOandaData(bar_count,granularity,inst)
        df = oanda.preprocessOanda(data)
        df['ema'] = EMA(df.close, timeperiod=ema)
        price = df['close'][-1]
        ema_val = df['ema'][-1]

        if price > ema_val:
            if base == target:
                str_score = str_score + 1
            elif counter == target:
                str_score = str_score - 1
            else:
                print('Error: Neither base or counter match target.')

        elif price < ema_val:
            if base == target:
                str_score = str_score - 1
            elif counter == target:
                str_score = str_score + 1
            else:
                print('Error: Neither base or counter match target.')

        else:
            print('Error: price vs ema. Price: ', price,' EMA: ', ema_val)

    return str_score

Retrieve the strength score by iterating through each basket of currencies

In [4]:
def getRelativeStrength(granularity,ema):
    '''Call getStrengthScore for each currency based on ema parameter and return the score'''

    aud_dict = {'target':'AUD', 'list':['AUD_USD','AUD_CAD','AUD_CHF','GBP_AUD','AUD_JPY','AUD_NZD','EUR_AUD']}
    cad_dict = {'target':'CAD', 'list':['AUD_CAD','USD_CAD','CAD_CHF','CAD_JPY','GBP_CAD','EUR_CAD','NZD_CAD']}
    chf_dict = {'target':'CHF', 'list':['AUD_CHF','CAD_CHF','USD_CHF','EUR_CHF','GBP_CHF','CHF_JPY','NZD_CHF']}
    eur_dict = {'target':'EUR', 'list':['EUR_AUD','EUR_CAD','EUR_CHF','EUR_GBP','EUR_USD','EUR_JPY','EUR_NZD']}
    gbp_dict = {'target':'GBP', 'list':['GBP_AUD','GBP_CAD','GBP_CHF','EUR_GBP','GBP_JPY','GBP_NZD','GBP_USD']}
    jpy_dict = {'target':'JPY', 'list':['AUD_JPY','CAD_JPY','CHF_JPY','EUR_JPY','GBP_JPY','USD_JPY','NZD_JPY']}
    nzd_dict = {'target':'NZD', 'list':['AUD_NZD','NZD_CAD','NZD_CHF','EUR_NZD','GBP_NZD','NZD_JPY','NZD_USD']}
    usd_dict = {'target':'USD', 'list':['AUD_USD','USD_CAD','USD_CHF','EUR_USD','GBP_USD','USD_JPY','NZD_USD']}

    aud_score = getStrengthScore(granularity, inst_dict=aud_dict, ema=ema)
    cad_score = getStrengthScore(granularity, inst_dict=cad_dict, ema=ema)
    chf_score = getStrengthScore(granularity, inst_dict=chf_dict, ema=ema)
    eur_score = getStrengthScore(granularity, inst_dict=eur_dict, ema=ema)
    gbp_score = getStrengthScore(granularity, inst_dict=gbp_dict, ema=ema)
    jpy_score = getStrengthScore(granularity, inst_dict=jpy_dict, ema=ema)
    nzd_score = getStrengthScore(granularity, inst_dict=nzd_dict, ema=ema)
    usd_score = getStrengthScore(granularity, inst_dict=usd_dict, ema=ema)

    score_df = pd.DataFrame({'instrument':['AUD','CAD','CHF','EUR','GBP','JPY','NZD','USD'],
                             'score':[aud_score,cad_score,chf_score,eur_score,gbp_score,jpy_score,nzd_score,usd_score]})
    return score_df
In [7]:
daily20_score_df = getRelativeStrength(granularity='D',ema=20)
daily10_score_df = getRelativeStrength(granularity='D',ema=10)
fourhourly20_score_df = getRelativeStrength(granularity='H4',ema=20)
fourhourly10_score_df = getRelativeStrength(granularity='H4',ema=10)

Visualize each of the results

In [8]:
sns.set(style='whitegrid')

plt.subplot(221)
plt.title('Daily Flow Using 20 Period Smoothing')
plt.xlabel('Currency')
plt.ylabel('Strength Score')
plt.bar(x=daily20_score_df.instrument,height=daily20_score_df.score)

plt.subplot(222)
plt.title('Daily Flow Using 10 Period Smoothing')
plt.xlabel('Currency')
plt.ylabel('Strength Score')
plt.bar(x=daily10_score_df.instrument,height=daily10_score_df.score)

plt.subplot(223)
plt.title('H4 Flow Using 20 Period Smoothing')
plt.xlabel('Currency')
plt.ylabel('Strength Score')
plt.bar(x=fourhourly20_score_df.instrument,height=fourhourly20_score_df.score)

plt.subplot(224)
plt.title('H4 Flow Using 10 Period Smoothing')
plt.xlabel('Currency')
plt.ylabel('Strength Score')
plt.bar(x=fourhourly10_score_df.instrument,height=fourhourly10_score_df.score)

plt.show()
In [9]:
plt.title('Daily Flow Using 20 Period Smoothing')
plt.xlabel('Currency')
plt.ylabel('Strength Score')
plt.bar(x=daily20_score_df.instrument,height=daily20_score_df.score)
plt.show()

Trade ideas

  • Find long trend trades for those with high scores, assuming it will continue
  • Find short trend trades for those with lowest scores, assuming trend will continue
  • Similarly, find the strongest and weakest cross pair assuming the strong differential will continue
  • Look for mean reversion opportunities on crosses with scores close to 0

Todo

  • save history for each timestep iteration to get a change score
  • production: color mapping, sorting, historical view, currency rank view
  • historical system backtesting