def test_merge_pre(ix, pair, timeframe, id, start, end, date_pre, date_post,
                   clean_tmp):
    '''
    Test function 'merge_pre' to merge the 'pre' Segment
    '''

    oanda = OandaAPI(instrument=pair,
                     granularity=timeframe,
                     settingf='../../data/settings.ini')

    oanda.run(start=start, end=end)

    candle_list = oanda.fetch_candleset()

    cl = CandleList(candle_list,
                    instrument=pair,
                    id=id,
                    settingf='../../data/settings.ini')

    pl = cl.get_pivotlist(
        th_bounces=cl.settings.getfloat('pivots', 'th_bounces'))

    pivot = pl.plist[ix]
    # Check pivot.pre.start() before running 'merge_pre'
    assert date_post == pivot.pre.start()

    # run 'merge_pre' function
    pivot.merge_pre(slist=pl.slist,
                    n_candles=cl.settings.getint('pivots', 'n_candles'),
                    diff_th=cl.settings.getint('pivots', 'diff_th'))

    # Check pivot.pre.start() after running 'merge_pre'
    assert date_pre == pivot.pre.start()
Exemple #2
0
    def __initclist(self):
        '''
        Private function to initialize the CandleList object that goes from self.trade.start
        to self.period

        This will set the self.clist_period class attribute
        '''
        delta_period = periodToDelta(self.settings.getint('counter', 'period'),
                                     self.trade.timeframe)
        delta_1 = periodToDelta(1, self.trade.timeframe)
        start = self.trade.start - delta_period  # get the start datetime for this CandleList period
        end = self.trade.start + delta_1  # increase self.start by one candle to include self.start

        oanda = OandaAPI(url=self.settings.get('oanda_api', 'url'),
                         instrument=self.trade.pair,
                         granularity=self.trade.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        oanda.run(start=start.isoformat(), end=end.isoformat())

        candle_list = oanda.fetch_candleset()

        cl = CandleList(candle_list,
                        settingf=self.settingf,
                        settings=self.settings,
                        instrument=self.trade.pair,
                        granularity=self.trade.timeframe,
                        id=self.trade.id,
                        type=self.trade.type)

        self.clist_period = cl
Exemple #3
0
    def fetch_candlelist(self):
        '''
        This function returns a CandleList object for this Trade

        Returns
        -------

        A CandleList object

        '''
        oanda = OandaAPI(instrument=self.pair,
                         granularity=self.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        if isinstance(self.start, datetime) is True:
            astart = self.start
        else:
            astart = try_parsing_date(self.start)

        if isinstance(self.end, datetime) is True:
            anend = self.end
        else:
            anend = try_parsing_date(self.end)

        oanda.run(start=astart.isoformat(), end=anend.isoformat())

        candle_list = oanda.fetch_candleset()
        cl = CandleList(candle_list,
                        type=self.type,
                        settingf=self.settingf,
                        settings=self.settings)

        return cl
    def __initclist(self):
        '''
        Private function to initialize the CandleList object that goes from self.start
        to self.period

        This will set the self.clist_period class attribute
        '''

        delta_period=periodToDelta(self.period, self.timeframe)
        delta_1=periodToDelta(1, self.timeframe)
        start = self.start - delta_period # get the start datetime for this CandleList period
        end = self.start + delta_1 # increase self.start by one candle to include self.start

        oanda = OandaAPI(url=config.OANDA_API['url'],
                         instrument=self.pair,
                         granularity=self.timeframe,
                         alignmentTimezone=config.OANDA_API['alignmentTimezone'],
                         dailyAlignment=config.OANDA_API['dailyAlignment'])

        oanda.run(start=start.isoformat(),
                  end=end.isoformat(),
                  roll=True
                  )

        candle_list = oanda.fetch_candleset(vol_cutoff=0)

        cl = CandleList(candle_list, self.pair, granularity=self.timeframe, id=self.id, type=self.type)

        self.clist_period=cl
Exemple #5
0
    def __initclist(self, timeframe, end, pair):
        '''
        Private function to initialize the CandleList object that goes from trade.start
        to self.settings.getint('counter', 'period')

        Parameters
        ----------
        timeframe : Timeframe
        end : Datetime object that will be the end of this CandleList
        pair : pair

        Returns
        -------
        Candlelist or
        None if Oanda API query was not successful
        '''

        delta_period = periodToDelta(self.settings.getint('trade_bot', 'period_range'),
                                     timeframe)
        delta_1 = periodToDelta(1, timeframe)
        start = end - delta_period  # get the start datetime for this CandleList period
        end = end + delta_1  # increase end by one candle to include end

        tb_logger.debug("Fetching candlelist for period: {0}-{1}".format(start, end))

        oanda = OandaAPI(url=self.settings.get('oanda_api', 'url'),
                         instrument=pair,
                         granularity=timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        if self.ser_data_obj is None:
            tb_logger.info("Fetching data from API")
            resp = oanda.run(start=start.isoformat(),
                             end=end.isoformat())
        else:
            tb_logger.info("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=start,
                                                 end=end)
            resp = 200

        if resp == 200:
            candle_list = oanda.fetch_candleset()

            cl = CandleList(candle_list,
                            settingf=self.settingf,
                            settings=self.settings,
                            instrument=pair,
                            granularity=timeframe,
                            ser_data_obj=self.ser_data_obj,
                            id="test",
                            type="short")
            cl.calc_rsi()
            return cl
        else:
            t_logger.warn("API query was not OK. No CandleList created ")
            return None
    def __initclist(self):
        '''
        Private function to initialize the CandleList object that goes from self.trade.start
        to self.settings.getint('counter', 'period')

        This will set the self.clist_period class attribute

        Returns
        -------
        None if Oanda API query was not successful
        '''

        delta_period = periodToDelta(self.settings.getint('counter', 'period'),
                                     self.trade.timeframe)
        delta_1 = periodToDelta(1, self.trade.timeframe)
        start = self.trade.start - delta_period  # get the start datetime for this CandleList period
        end = self.trade.start + delta_1  # increase self.start by one candle to include self.start

        c_logger.debug("Fetching candlelist for period: {0}-{1}".format(
            start, end))

        oanda = OandaAPI(url=self.settings.get('oanda_api', 'url'),
                         instrument=self.trade.pair,
                         granularity=self.trade.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        resp = None
        if self.ser_data_obj is None:
            c_logger.debug("Fetching data from API")
            resp = oanda.run(start=start.isoformat(), end=end.isoformat())
        else:
            c_logger.debug("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=start, end=end)
            resp = 200

        if resp == 200:
            candle_list = oanda.fetch_candleset()

            cl = CandleList(candle_list,
                            settingf=self.settingf,
                            settings=self.settings,
                            instrument=self.trade.pair,
                            granularity=self.trade.timeframe,
                            id=self.trade.id,
                            ser_data_obj=self.ser_data_obj,
                            type=self.trade.type)

            self.clist_period = cl
        else:
            c_logger.warn(
                "API query was not OK. 'self.clist_period' will be None ")
            self.clist_period = None
Exemple #7
0
    def get_max_min(self, adateObj):
        '''
        Function to get the price range for identifying S/R by checking the max
        and min price for CandleList starting in
        'adateObj'- self.settings.getint('trade_bot', 'period_range') and ending in 'adateObj'

        Parameters
        ----------
        datetime object used for identifying
        S/R areas

        Returns
        -------
        max, min floats
        '''

        oanda = OandaAPI(instrument=self.pair,
                         granularity=self.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        delta_period = periodToDelta(self.settings.getint('trade_bot', 'period_range'),
                                     self.timeframe)
        delta_1 = periodToDelta(1, self.timeframe)

        start = adateObj - delta_period  # get the start datetime for this CandleList period
        end = adateObj + delta_1  # increase self.start by one candle to include self.start

        if self.ser_data_obj is None:
            tb_logger.info("Fetching data from API")
            oanda.run(start=start.isoformat(),
                      end=end.isoformat())
        else:
            tb_logger.info("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=start,
                                                 end=end)
        candle_list = oanda.fetch_candleset()
        cl = CandleList(candle_list,
                        instrument=self.pair,
                        id='test',
                        granularity=self.timeframe,
                        settingf=self.settingf,
                        settings=self.settings)

        max = cl.get_highest()
        min = cl.get_lowest()

        # add a number of pips to max,min to be sure that we
        # also detect the extreme pivots
        max = add_pips2price(self.pair, max, self.settings.getint('trade_bot', 'add_pips'))
        min = substract_pips2price(self.pair, min, self.settings.getint('trade_bot', 'add_pips'))

        return max, min
Exemple #8
0
def test_indecision_c(pair, timeframe, time, is_it):
    oanda = OandaAPI(instrument=pair,
                     granularity=timeframe,
                     settingf="../../data/settings.ini")

    oanda.run(start=time, count=1)

    candle_list = oanda.fetch_candleset()
    candle_list[0].set_candle_features()
    result = candle_list[0].indecision_c()

    assert is_it == result
Exemple #9
0
def test_OandaAPI_vol():
    '''
    Test a simple query to Oanda's REST API using a H12 timeframe and using
    a volume cutoff for 'fetch_candleset' function
    '''

    oanda = OandaAPI(instrument='NZD_JPY',
                     granularity='H12',
                     settingf='../../data/settings.ini')

    oanda.run(start='2011-09-02T21:00:00', end='2011-09-06T22:00:00')

    candle_list = oanda.fetch_candleset(vol_cutoff=20)

    assert len(candle_list) == 6
Exemple #10
0
def test_fetch_one_candle():
    oanda = OandaAPI(instrument='AUD_USD',
                     granularity='D',
                     settingf='../../data/settings.ini')

    oanda.run(start='2015-01-25T22:00:00', count=1)

    candle_list = oanda.fetch_candleset()
    assert candle_list[0].highBid == 0.79329
    assert candle_list[0].openBid == 0.7873
    assert candle_list[0].lowBid == 0.7857
    assert candle_list[0].representation == 'bidask'
    assert candle_list[0].lowAsk == 0.786
    assert candle_list[0].complete == True
    assert candle_list[0].openAsk == 0.7889
Exemple #11
0
def cl_object():
    '''Returns a CandleList object'''

    oanda = OandaAPI(instrument='AUD_USD',
                     granularity='D',
                     settingf='../../data/settings.ini')

    oanda.run(start='2019-03-06T23:00:00', end='2020-01-03T23:00:00')

    candle_list = oanda.fetch_candleset()

    cl = CandleList(candle_list,
                    instrument='AUD_USD',
                    granularity='D',
                    settingf='../../data/settings.ini')
    return cl
Exemple #12
0
def clO():
    """Returns a CandleList object"""

    oanda = OandaAPI(instrument='AUD_USD',
                     granularity='D',
                     settingf='../../data/settings.ini')

    oanda.run(start='2019-03-06T23:00:00', end='2020-01-24T23:00:00')

    candle_list = oanda.fetch_candleset()
    cl = CandleList(candle_list,
                    instrument='AUD_USD',
                    id='test_AUD_USD_clist',
                    granularity='D',
                    settingf='../../data/settings.ini')
    return cl
def cl_object(clean_tmp):
    '''Returns CandleList object'''

    oanda = OandaAPI(instrument='AUD_USD',
                     granularity='D',
                     settingf='../../data/settings.ini')

    oanda.run(start='2015-06-24T22:00:00', end='2019-06-21T22:00:00')

    candle_list = oanda.fetch_candleset()

    cl = CandleList(candle_list,
                    instrument='AUD_USD',
                    id='AUD_USD_testclist',
                    type='long',
                    settingf='../../data/settings.ini')
    return cl
Exemple #14
0
def test_set_candle_features(pair, timeframe, time, colour, upper_wick,
                             lower_wick):
    '''
    Test function to set basic candle features based on price
    i.e. self.colour, upper_wick, etc...
    '''
    oanda = OandaAPI(instrument=pair,
                     granularity=timeframe,
                     settingf="../../data/settings.ini")

    oanda.run(start=time, count=1)

    candle_list = oanda.fetch_candleset()
    candle_list[0].set_candle_features()
    assert candle_list[0].colour == colour
    assert candle_list[0].upper_wick == upper_wick
    assert candle_list[0].lower_wick == lower_wick
Exemple #15
0
def test_calc_itrend(pair, start, end, t_type, itrend, settings_obj,
                     clean_tmp):

    settings_obj.set('it_trend', 'th_bounces', '0.02')
    settings_obj.set('it_trend', 'n_candles', '12')

    oanda = OandaAPI(instrument=pair, granularity='D', settings=settings_obj)

    oanda.run(start=start.isoformat(), end=end.isoformat())

    candle_list = oanda.fetch_candleset()
    cl = CandleList(candle_list,
                    instrument=pair,
                    id='test_clist',
                    granularity='D',
                    settings=settings_obj)

    assert itrend == cl.calc_itrend(t_type=t_type)
    def calc_pips_c_trend(self):
        '''
        Function to calculate the pips_c_trend

        Returns
        -------
        Float with number of pips for the trend_i
        '''

        oanda = OandaAPI(url=self.settings.get('oanda_api', 'url'),
                         instrument=self.trade.pair,
                         granularity=self.trade.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        resp = None
        if self.ser_data_obj is None:
            c_logger.debug("Fetching data from API")
            resp = oanda.run(start=self.trend_i.isoformat(),
                             end=self.trade.start.isoformat())
        else:
            c_logger.debug("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=self.trend_i,
                                                 end=self.trade.start)
            resp = 200

        if resp == 200:

            candle_list = oanda.fetch_candleset()

            cl = CandleList(candle_list,
                            settingf=self.settingf,
                            settings=self.settings,
                            instrument=self.trade.pair,
                            granularity=self.trade.timeframe,
                            id=self.trade.id,
                            type=self.trade.type)

            pips_c_trend = cl.get_length_pips() / cl.get_length_candles()

            return round(pips_c_trend, 1)
        else:
            c_logger.warn(
                "API query was not OK. 'pips_c_trend' could not be calculated")
def pl_object():
    '''Returns PivotList object'''

    oanda = OandaAPI(instrument='AUD_USD',
                     granularity='D',
                     settingf='../../data/settings.ini')

    oanda.run(start='2019-03-08T22:00:00', end='2019-08-09T22:00:00')

    candle_list = oanda.fetch_candleset()

    cl = CandleList(candle_list,
                    instrument='AUD_USD',
                    id='AUD_USD_test',
                    type='long',
                    settingf='../../data/settings.ini')

    pl = cl.get_pivotlist(
        th_bounces=cl.settings.getfloat('pivots', 'th_bounces'))

    return pl
    def set_valley(self):
        '''
        Function to calculate the length of the valley
        between bounce_1st & bounce_2nd

        Returns
        -------
        It will set the 'valley' attribute of the class
        '''

        oanda = OandaAPI(url=config.OANDA_API['url'],
                         instrument=self.pair,
                         granularity=self.timeframe,
                         alignmentTimezone=config.OANDA_API['alignmentTimezone'],
                         dailyAlignment=config.OANDA_API['dailyAlignment'])

        oanda.run(start=self.bounce_2nd.time.isoformat(),
                  end=self.bounce_1st.time.isoformat())

        candle_list = oanda.fetch_candleset(vol_cutoff=0)

        self.valley = len(candle_list)
def test_adjust_pivottime(ix, pair, timeframe, id, start, end, new_b,
                          clean_tmp):
    oanda = OandaAPI(instrument=pair,
                     granularity=timeframe,
                     settingf='../../data/settings.ini')

    oanda.run(start=start, end=end)

    candle_list = oanda.fetch_candleset()

    cl = CandleList(candle_list,
                    instrument=pair,
                    id=id,
                    settingf='../../data/settings.ini')

    pl = cl.get_pivotlist(
        th_bounces=cl.settings.getfloat('pivots', 'th_bounces'))

    p = pl.plist[ix]
    newt = p.adjust_pivottime(clistO=cl)

    assert new_b == newt
    def fetch_candlelist(self):
        '''
        This function returns a CandleList object for this Trade

        Returns
        -------

        A CandleList object

        '''
        oanda = OandaAPI(instrument=self.pair,
                         granularity=self.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        if isinstance(self.start, datetime) is True:
            astart = self.start
        else:
            astart = try_parsing_date(self.start)

        if isinstance(self.end, datetime) is True:
            anend = self.end
        else:
            anend = try_parsing_date(self.end)

        if self.ser_data_obj is None:
            t_logger.debug("Fetching data from API")
            oanda.run(start=astart.isoformat(), end=anend.isoformat())
        else:
            t_logger.debug("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=astart, end=anend)

        candle_list = oanda.fetch_candleset()
        cl = CandleList(candle_list,
                        type=self.type,
                        settingf=self.settingf,
                        settings=self.settings)

        return cl
Exemple #21
0
def test_get_lasttime():
    oanda = OandaAPI(instrument='AUD_CHF',
                     granularity='H12',
                     settingf='../../data/settings.ini')

    resist = HArea(price=1.00721,
                   pips=45,
                   instrument='AUD_CHF',
                   granularity='H12',
                   settingf='../../data/settings.ini')

    oanda.run(start='2004-11-07T10:00:00', end='2010-04-30T09:00:00')

    candle_list = oanda.fetch_candleset()
    cl = CandleList(candle_list,
                    instrument='AUD_CHF',
                    id='test_AUD_CHF_clist',
                    granularity='H12',
                    type='short',
                    settingf='../../data/settings.ini')

    lasttime = cl.get_lasttime(resist)
    assert lasttime == datetime.datetime(2007, 11, 9, 10, 0)
Exemple #22
0
                   instrument=args.instrument,
                   granularity=args.granularity,
                   alignmentTimezone='Europe/London',
                   dailyAlignment=22,
                   start=args.start,
                   end=args.end
                   )
else:
    oanda=OandaAPI(url='https://api-fxtrade.oanda.com/v1/candles?',
                   instrument=args.instrument,
                   granularity=args.granularity,
                   alignmentTimezone='Europe/London',
                   dailyAlignment=22,
                   start=args.start)

candle_list=oanda.fetch_candleset()

trade_type=str(args.trade_type)
cl=CandleList(candle_list, type=trade_type)
cl.calc_binary_seq(merge=True)
cl.calc_number_of_0s(norm=True)
cl.calc_number_of_doubles0s(norm=True)
cl.calc_longest_stretch()

for k in cl.seq:
    print("\t{0}: {1}".format(k,cl.seq[k]))

print("Number of 0s (merged): %.2f" % cl.number_of_0s['merge'])
print("Double0s (highlow): {0}".format(cl.highlow_double0s))
print("Double0s (openclose): {0}".format(cl.openclose_double0s))
print("Stretch:")
Exemple #23
0
    def run(self, discard_sat=True, pickled_file=None):
        '''
        This function will run the Bot from start to end
        one candle at a time

        Parameter
        ---------
        discard_sat : Bool
                      If this is set to True, then the Trade wil not
                      be taken if IC falls on a Saturday. Default: True
        pickled_file : str
                       Path used to dump the pickled representation of the dict
                       of HAreaList generated by store_SRlist (if self.settings.
                       getboolean('trade_bot', 'store_SRlist' is True
                       Or path used to load the pickled representation (if
                       self.settings.getboolean('trade_bot', 'load_SRlist' is
                       True)

        Returns
        -------
        TradeList object with Trades taken. None if no trades
        were taken
        '''
        tb_logger.info("Running...")

        oanda = OandaAPI(instrument=self.pair,
                         granularity=self.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)
        delta = None
        nhours = None
        if self.timeframe == "D":
            nhours = 24
            delta = datetime.timedelta(hours=24)
        else:
            p1 = re.compile('^H')
            m1 = p1.match(self.timeframe)
            if m1:
                nhours = int(self.timeframe.replace('H', ''))
                delta = datetime.timedelta(hours=int(nhours))

        startO = pd.datetime.strptime(self.start, '%Y-%m-%d %H:%M:%S')
        endO = pd.datetime.strptime(self.end, '%Y-%m-%d %H:%M:%S')

        dict_SRlist = {}
        if self.settings.getboolean('trade_bot', 'load_SRlist') is True:
            tb_logger.info("Loading dict of HAreaLists from pickled "
                           "file: {0}".format(pickled_file))
            pickled_fh = open(pickled_file, 'rb')
            dict_SRlist = pickle.load(pickled_fh)

        SRlst = None
        loop = 0
        tlist = []
        tend = None
        while startO <= endO:
            if tend is not None:
                # this means that there is currently an active trade
                if startO <= tend:
                    startO = startO + delta
                    loop += 1
                    continue
                else:
                    tend = None
            tb_logger.info("Trade bot - analyzing candle: {0}".format(startO.isoformat()))
            if loop == 0:
                # no iteration has occurred yet, so invoke .calc_SR for the first time
                if self.settings.getboolean('trade_bot', 'load_SRlist') is True:
                    SRlst= dict_SRlist[startO]
                else:
                    SRlst = self.calc_SR(adateObj=startO)
                res = SRlst.print()
                dict_SRlist[startO] = SRlst
                tb_logger.info("Identified HAreaList for time {0}:".format(startO.isoformat()))
                tb_logger.info("{0}".format(res))
            elif loop >= self.settings.getint('trade_bot',
                                              'period'):
                # An entire cycle has occurred. Invoke .calc_SR
                if self.settings.getboolean('trade_bot', 'load_SRlist') is True:
                    SRlst = dict_SRlist[startO]
                else:
                    SRlst = self.calc_SR(adateObj=startO)
                res = SRlst.print()
                dict_SRlist[startO] = SRlst
                tb_logger.info("Identified HAreaList for time {0}:".format(startO.isoformat()))
                tb_logger.info("{0}".format(res))
                loop = 0

            # fetch candle for current datetime
            if self.ser_data_obj is None:
                tb_logger.info("Fetching data from API")
                oanda.run(start=startO.isoformat(),
                          count=1)
            else:
                tb_logger.info("Fetching data from File")
                oanda.data = self.ser_data_obj.slice(start=startO,
                                                     count=1)

            candle_list = oanda.fetch_candleset()
            c_candle = candle_list[0] # this is the current candle that
                                      # is being checked

            # c_candle.time is not equal to startO
            # when startO is non-working day, for example
            delta1hr = datetime.timedelta(hours=1)
            if (c_candle.time != startO) and (abs(c_candle.time-startO) > delta1hr):
                loop += 1
                tb_logger.info("Analysed dt {0} is not the same than APIs returned dt {1}."
                               " Skipping...".format(startO, c_candle.time))
                startO = startO + delta
                continue

            #check if there is any HArea overlapping with c_candle
            HAreaSel, sel_ix = SRlst.onArea(candle=candle_list[0])

            if HAreaSel is not None:
                c_candle.set_candle_features()
                # guess the if trade is 'long' or 'short'
                type, SL = self.__get_trade_type(ic=c_candle, delta=delta)
                prepare_trade = False
                if c_candle.indecision_c(ic_perc=self.settings.getint('general', 'ic_perc')) is True:
                    prepare_trade = True
                elif type == 'short' and c_candle.colour == 'red':
                    prepare_trade = True
                elif type == 'long' and c_candle.colour == 'green':
                    prepare_trade = True

                # discard if IC falls on a Saturday
                if c_candle.time.weekday() == 5 and discard_sat is True:
                    tb_logger.info("Possible trade at {0} falls on Sat. Skipping...".format(c_candle.time))
                    prepare_trade = False

                if prepare_trade is True:
                    t = self.prepare_trade(
                        type=type,
                        SL=SL,
                        ic=c_candle,
                        harea_sel=HAreaSel,
                        delta=delta)
                    t.strat = 'counter'
                    t.tot_SR = len(SRlst.halist)
                    t.rank_selSR = sel_ix
                    # calculate t.entry-t.SL in number of pips
                    # and discard if it is over threshold
                    diff = abs(t.entry-t.SL)
                    number_pips = float(calculate_pips(self.pair, diff))
                    if number_pips > self.settings.getint('trade_bot', 'SL_width_pips'):
                        loop += 1
                        startO = startO + delta
                        continue
                    if self.settings.getboolean('trade_bot', 'run_trades') is True:
                        t.run_trade(expires=2)
                        if t.entered is True:
                            if not hasattr(t, 'end'):
                                tb_logger.info("Trade.end will be n.a. Check if this trade hit the SL/TP in"
                                               "the analysed timeframe. Skipping...")
                                tend = None
                            else:
                                tlist.append(t)
                                tend = t.end
                    else:
                        tlist.append(t)
            startO = startO+delta
            loop += 1

        tb_logger.info("Run done")

        if self.settings.getboolean('trade_bot', 'store_SRlist') is True:
            tb_logger.info("Dumping dict of HAreaLists to pickled "
                           "file: {0}".format(pickled_file))
            pickled_lst_f = open(pickled_file, 'wb')
            pickle.dump(dict_SRlist, pickled_lst_f)
            pickled_lst_f.close()

        if len(tlist) == 0:
            return None
        else:
            tl = TradeList(tlist=tlist,
                           settingf=self.settingf,
                           settings=self.settings,
                           ser_data_obj=self.ser_data_obj
                           )

            if self.settings.getboolean('trade_bot', 'run_trades') is True:
                # analyse trades
                tl.analyze()
            return tl
    def __get_time4candles(self, n, anchor_point,roll=True):
        '''
        This private function takes a a number of candles
        and returns a Datetime corresponding to
        this number of candles

        Parameters
        ----------
        n : int
            Number of candles
        anchor_point : datetime
            Datetime used as the anchor (end point from which it will go back 'n' candles) for calculation
        roll : boolean
               if True, then if will try to go back in time in order to get exactly 'n' number of candles.
               Default: True

        Returns
        -------
        Datetime.datetime
        '''

        delta_from_start = None
        delta_one = None
        if self.timeframe == "D":
            delta_from_start = datetime.timedelta(hours=24 * n)
            delta_one = datetime.timedelta(hours=24)
        else:
            fgran = self.timeframe.replace('H', '')
            delta_from_start = datetime.timedelta(hours=int(fgran) * n)
            delta_one = datetime.timedelta(hours=int(fgran))

        # calculate the cutoff for the first threshold using the number of candles
        oanda = OandaAPI(url=config.OANDA_API['url'],
                         instrument=self.pair,
                         granularity=self.timeframe,
                         alignmentTimezone=config.OANDA_API['alignmentTimezone'],
                         dailyAlignment=config.OANDA_API['dailyAlignment'])

        start = anchor_point - delta_from_start
        if roll is True:
            if start< config.START_HIST[self.pair]:
                #return the first candle in the record if start goes back before the start of the record
                return config.START_HIST[self.pair]
            else :
                end = anchor_point.isoformat()

                oanda.run(start=start.isoformat(),
                          end=end,
                          roll=True)

                candle_list = oanda.fetch_candleset()

                # if len of candle_list is below n then go back one candle at a time
                while len(candle_list) < n:
                        start = start - delta_one
                        oanda.run(start=start.isoformat(),
                                  end=end,
                                  roll=True)
                        candle_list = oanda.fetch_candleset()


                return start
        else:
            return start
    def calc_rsi(self):
        '''
        Calculate the RSI for a certain candle list
        '''
        cl_logger.debug("Running calc_rsi")

        start_time = self.clist[0].time
        end_time = self.clist[-1].time

        delta_period = None
        if self.granularity == "D":
            delta_period = timedelta(hours=24 * self.settings.getint('candlelist', 'period'))
        else:
            fgran = self.granularity.replace('H', '')
            delta_period = timedelta(hours=int(fgran) * self.settings.getint('candlelist', 'period'))

        start_calc_time = start_time - delta_period

        #fetch candle set from start_calc_time
        oanda = OandaAPI(instrument=self.instrument,
                         granularity=self.granularity,
                         settingf=self.settingf,
                         settings=self.settings)
        '''
        Get candlelist from start_calc_time to (start_time-1)
        This 2-step API call is necessary in order to avoid
        maximum number of candles errors
        '''
        if self.ser_data_obj is None:
            cl_logger.debug("Fetching data from API")
            oanda.run(start=start_calc_time.isoformat(),
                      end=start_time.isoformat())
        else:
            cl_logger.debug("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=start_calc_time,
                                                 end=start_time)

        cl1 = oanda.fetch_candleset()

        '''Get candlelist from start_time to end_time'''
        if self.ser_data_obj is None:
            cl_logger.debug("Fetching data from API")
            oanda.run(start=start_time.isoformat(),
                      end=end_time.isoformat())
        else:
            cl_logger.debug("Fetching data from File")
            oanda.data = self.ser_data_obj.slice(start=start_time,
                                                 end=end_time)

        cl2 = oanda.fetch_candleset()

        if cl1[-1].time == cl2[0].time:
            del cl1[-1]

        candle_list = cl1 + cl2

        series = [c.closeAsk for c in candle_list]

        df = pd.DataFrame({'close': series})
        chg = df['close'].diff(1)

        gain = chg.mask(chg < 0, 0)
        loss = chg.mask(chg > 0, 0)

        rsi_period = self.settings.getint('candlelist', 'rsi_period')
        avg_gain = gain.ewm(com=rsi_period - 1, min_periods=rsi_period).mean()
        avg_loss = loss.ewm(com=rsi_period - 1, min_periods=rsi_period).mean()

        rs = abs(avg_gain / avg_loss)

        rsi = 100 - (100 / (1 + rs))

        rsi4cl = rsi[-len(self.clist):]
        # set rsi attribute in each candle of the CandleList
        ix = 0
        for c, v in zip(self.clist, rsi4cl):
            self.clist[ix].rsi = round(v, 2)
            ix += 1

        cl_logger.debug("Done calc_rsi")
    def run_trade(self, expires=None):
        '''
        Run the trade until conclusion from a start date
        '''

        t_logger.info("Run run_trade with id: {0}".format(self.id))

        entry = HArea(price=self.entry,
                      instrument=self.pair,
                      pips=self.settings.getint('trade', 'hr_pips'),
                      granularity=self.timeframe,
                      ser_data_obj=None,
                      settings=self.settings)
        SL = HArea(price=self.SL,
                   instrument=self.pair,
                   pips=self.settings.getint('trade', 'hr_pips'),
                   granularity=self.timeframe,
                   ser_data_obj=None,
                   settings=self.settings)
        TP = HArea(price=self.TP,
                   instrument=self.pair,
                   pips=self.settings.getint('trade', 'hr_pips'),
                   granularity=self.timeframe,
                   ser_data_obj=None,
                   settings=self.settings)

        period = None
        if self.timeframe == "D":
            period = 24
        else:
            period = int(self.timeframe.replace('H', ''))

        # generate a range of dates starting at self.start and ending numperiods later in order to assess the outcome
        # of trade and also the entry time

        self.start = datetime.strptime(str(self.start), '%Y-%m-%d %H:%M:%S')
        numperiods = self.settings.getint('trade', 'numperiods')
        # date_list will contain a list with datetimes that will be used for running self
        date_list = [
            datetime.strptime(str(self.start.isoformat()), '%Y-%m-%dT%H:%M:%S')
            + timedelta(hours=x * period) for x in range(0, numperiods)
        ]

        count = 0
        self.entered = False

        for d in date_list:
            count += 1
            if expires is not None:
                if count > expires and self.entered is False:
                    self.outcome = 'n.a.'
                    break
            oanda = OandaAPI(instrument=self.pair,
                             granularity=self.timeframe,
                             settingf=self.settingf,
                             settings=self.settings)

            if self.ser_data_obj is None:
                t_logger.debug("Fetching data from API")
                oanda.run(start=d.isoformat(), count=1)
            else:
                t_logger.debug("Fetching data from File")
                oanda.data = self.ser_data_obj.slice(start=d, count=1)

            cl = oanda.fetch_candleset()[0]
            if self.entered is False:
                entry_time = entry.get_cross_time(
                    candle=cl,
                    granularity=self.settings.get('trade', 'granularity'))
                if entry_time != 'n.a.':
                    t_logger.info("Trade entered")
                    # modify self.start to the datetime
                    # that Trade has actually entered
                    self.start = d
                    self.entry_time = entry_time.isoformat()
                    self.entered = True
            if self.entered is True:
                # will be n.a. is cl does not cross SL
                failure_time = SL.get_cross_time(candle=cl,
                                                 granularity=self.settings.get(
                                                     'trade', 'granularity'))
                # sometimes there is a jump in the price and SL is not crossed
                is_gap = False
                if (self.type == "short" and cl.lowAsk > SL.price) or (
                        self.type == "long" and cl.highAsk < SL.price):
                    is_gap = True
                    failure_time = d
                if (failure_time is not None
                        and failure_time != 'n.a.') or is_gap is True:
                    self.outcome = 'failure'
                    self.end = failure_time
                    self.pips = float(
                        calculate_pips(self.pair,
                                       abs(self.SL - self.entry))) * -1
                    t_logger.info("S/L was hit")
                    break
                # will be n.a. if cl does not cross TP
                success_time = TP.get_cross_time(candle=cl,
                                                 granularity=self.settings.get(
                                                     'trade', 'granularity'))
                # sometimes there is a jump in the price and TP is not crossed
                is_gap = False
                if (self.type == "short" and cl.highAsk < TP.price) or (
                        self.type == "long" and cl.lowAsk > TP.price):
                    is_gap = True
                    success_time = d

                if (success_time is not None
                        and success_time != 'n.a.') or is_gap is True:
                    self.outcome = 'success'
                    t_logger.info("T/P was hit")
                    self.end = success_time
                    self.pips = float(
                        calculate_pips(self.pair, abs(self.TP - self.entry)))
                    break
        try:
            assert getattr(self, 'outcome')
        except:
            t_logger.warning("No outcome could be calculated")
            self.outcome = "n.a."
            self.pips = 0

        t_logger.info("Done run_trade")
Exemple #27
0
    def __get_trade_type(self, ic, delta):
        '''
        Function to guess what is the trade type (short or long)
        for this possible trade. It will also adjust the SL price
        to the most recent highest high/lowest low

        Parameters
        ----------
        ic : Candle object
             Indecision candle for this trade
        delta : Timedelta object corresponding to
                the time that needs to be increased

        Returns
        -------
        str: Trade type (long or short)
        float: adjusted SL
        '''

        oanda = OandaAPI(instrument=self.pair,
                         granularity=self.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)

        # n x delta controls how many candles to go back in time
        # to check
        start = ic.time - 20 * delta
        end = ic.time

        oanda.run(start=start.isoformat(), end=end.isoformat())

        candle_list = oanda.fetch_candleset()
        clObj = CandleList(candle_list,
                           instrument=self.pair,
                           id='fit_reg',
                           granularity=self.timeframe,
                           settingf=self.settingf,
                           settings=self.settings)
        # fit a regression line in order to check its slope
        # and guess the trade type
        (fitted_model, regression_model_mse) = clObj.fit_reg_line()

        slope = fitted_model.coef_[0][0]

        if slope < 0:
            type = 'long'
        elif slope > 0:
            type = 'short'

        # adjust SL
        if type == 'short':
            part = 'high{0}'.format(self.settings.get('general', 'bit'))
        elif type == 'long':
            part = 'low{0}'.format(self.settings.get('general', 'bit'))

        SL = None
        for c in reversed(candle_list):
            price = getattr(c, part)
            if SL is None:
                SL = price
                continue
            if type == 'short':
                if price > SL:
                    SL = price
            if type == 'long':
                if price < SL:
                    SL = price

        return type, SL
Exemple #28
0
    def run(self):
        '''
        This function will run the Bot from start to end
        one candle at a time

        Returns
        -------
        TradeList object with Trades taken. None if no trades
        were taken
        '''

        tb_logger.info("Runnning...")

        oanda = OandaAPI(instrument=self.pair,
                         granularity=self.timeframe,
                         settingf=self.settingf,
                         settings=self.settings)
        delta = None
        nhours = None
        if self.timeframe == "D":
            nhours = 24
            delta = datetime.timedelta(hours=24)
        else:
            p1 = re.compile('^H')
            m1 = p1.match(self.timeframe)
            if m1:
                nhours = int(self.timeframe.replace('H', ''))
                delta = datetime.timedelta(hours=int(nhours))

        startO = pd.datetime.strptime(self.start, '%Y-%m-%d %H:%M:%S')
        endO = pd.datetime.strptime(self.end, '%Y-%m-%d %H:%M:%S')

        SRlst = None
        loop = 0
        tlist = []
        tend = None
        while startO <= endO:
            if tend is not None:
                # this means that there is currently an active trade
                if startO <= tend:
                    startO = startO + delta
                    continue
                else:
                    tend = None
            tb_logger.info("Trade bot - analyzing candle: {0}".format(
                startO.isoformat()))

            if loop == 0:
                # no iteration has occurred yet, so invoke .calc_SR for the first time
                SRlst = self.calc_SR(adateObj=startO)
                res = SRlst.print()
                tb_logger.info("Identified HAreaList for time {0}:".format(
                    startO.isoformat()))
                tb_logger.info("{0}".format(res))
            elif loop == self.settings.getint('trade_bot', 'period'):
                # An entire cycle has occurred. Invoke .calc_SR
                SRlst = self.calc_SR(adateObj=startO)
                res = SRlst.print()
                tb_logger.info("Identified HAreaList for time {0}:".format(
                    startO.isoformat()))
                tb_logger.info("{0}".format(res))
                loop = 0
            # fetch candle for current datetime
            oanda.run(start=startO.isoformat(), count=1)

            candle_list = oanda.fetch_candleset()
            c_candle = candle_list[0]  # this is the current candle that
            # is being checked

            #check if there is any HArea overlapping with c_candle
            HAreaSel = SRlst.onArea(candle=candle_list[0])

            if HAreaSel is not None:
                c_candle.set_candle_features()
                # guess the if trade is 'long' or 'short'
                type, SL = self.__get_trade_type(ic=c_candle, delta=delta)
                prepare_trade = False
                if c_candle.indecision_c(ic_perc=self.settings.getint(
                        'general', 'ic_perc')) is True:
                    prepare_trade = True
                elif type == 'short' and c_candle.colour == 'red':
                    prepare_trade = True
                elif type == 'long' and c_candle.colour == 'green':
                    prepare_trade = True

                if prepare_trade is True:
                    t = self.prepare_trade(type=type,
                                           SL=SL,
                                           ic=c_candle,
                                           harea_sel=HAreaSel,
                                           delta=delta)
                    t.strat = 'counter'
                    # calculate t.entry-t.SL in number of pips
                    # and discard if it is over threshold
                    diff = abs(t.entry - t.SL)
                    number_pips = float(calculate_pips(self.pair, diff))
                    if number_pips > self.settings.getint(
                            'trade_bot', 'SL_width_pips'):
                        loop += 1
                        startO = startO + delta
                        continue
                    t.run_trade(expires=2)
                    if t.entered is True:
                        tlist.append(t)
                        tend = t.end
            startO = startO + delta
            loop += 1

        tb_logger.info("Run done")

        if len(tlist) == 0:
            return None
        else:
            tl = TradeList(tlist=tlist,
                           settingf=self.settingf,
                           settings=self.settings)
            tl.analyze()
            # analyse trades
            return tl
Exemple #29
0
    def get_cross_time(self, candle, granularity='M30'):
        '''
        This function is used get the time that the candle
        crosses (go through) HArea

        Parameters
        ----------
        candle :   Candle object that crosses the HArea
        granularity : To what granularity we should descend

        Returns
        ------
        datetime object with crossing time.
                 n.a. if crossing time could not retrieved. This can happens
                 when there is an artefactual jump in Oanda's data
        '''
        if candle.lowAsk <= self.price <= candle.highAsk:

            delta = None
            if self.granularity == "D":
                delta = timedelta(hours=24)
            else:
                fgran = self.granularity.replace('H', '')
                delta = timedelta(hours=int(fgran))

            cstart = candle.time
            cend = cstart + delta

            oanda = None
            if self.settingf is None and self.settings is None:
                raise Exception(
                    "No 'settings' nor 'settingf' defined for this object")
            elif self.settingf is None and self.settings is not None:
                oanda = OandaAPI(
                    instrument=self.instrument,
                    granularity=granularity,  # 'M30' in this case
                    settings=self.settings)
            elif self.settingf is not None and self.settings is None:
                oanda = OandaAPI(
                    instrument=self.instrument,
                    granularity=granularity,  # 'M30' in this case
                    settingf=self.settingf)
            elif self.settingf is not None and self.settings is not None:
                oanda = OandaAPI(
                    instrument=self.instrument,
                    granularity=granularity,  # 'M30' in this case
                    settingf=self.settingf)

            oanda.run(start=cstart.isoformat(), end=cend.isoformat())

            candle_list = oanda.fetch_candleset()
            seen = False
            for c in candle_list:
                if c.lowAsk <= self.price <= c.highAsk:
                    seen = True
                    return c.time

            if seen is False:
                return 'n.a.'
        else:
            return 'n.a.'