def test_last_time(cl_object): ''' Test 'last_time' function from HArea ''' resist = HArea(price=0.70151, pips=5, instrument='AUD_USD', granularity='D', settingf='../../data/settings.ini') lt = resist.last_time(clist=cl_object.clist, position='above') assert lt == datetime.datetime(2019, 7, 21, 21, 0)
def test_get_cross_time(cl_object, clist_ix, price, dt): ''' Test 'get_cross_time' function from HArea for a single candle that crosses the 'resist' object ''' resist = HArea(price=price, pips=5, instrument='AUD_USD', granularity='D', settingf='../../data/settings.ini') cross_time = resist.get_cross_time(candle=cl_object.clist[clist_ix]) assert cross_time == dt
def hlist_factory(): '''Returns a list of HArea objects''' hlist = [] for p in np.arange(0.67116, 0.82877, 0.042): area = HArea(price=p, pips=30, instrument=instrument, granularity=granularity, settingf='../../data/settings.ini') hlist.append(area) return hlist
def set_lasttime(self): ''' Function to set the lasttime class attribute returns ------- Nothing ''' c_logger.debug("Running set_lasttime") # instantiate an HArea object representing the self.SR in order to calculate the lasttime # price has been above/below SR resist = HArea(price=self.trade.SR, pips=self.settings.getint('harea', 'hr_pips'), instrument=self.trade.pair, granularity=self.trade.timeframe, settings=self.settings) self.lasttime = self.clist_period.get_lasttime(resist) c_logger.debug("Done set_lasttime")
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)
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")
def calc_SR(self, adateObj): ''' Function to calculate S/R lines Parameters ---------- datetime object used for identifying S/R areas Return ------ HAreaList object ''' # calculate price range for calculating S/R ul, ll = self.get_max_min(adateObj) tb_logger.info("Running calc_SR for estimated range: {0}-{1}".format( ll, ul)) prices = [] bounces = [] # contains the number of pivots per price level score_per_bounce = [] tot_score = [] # the increment of price in number of pips is double the hr_extension prev_p = None p = float(ll) while p <= float(ul): tb_logger.debug("Processing S/R at {0}".format(round(p, 4))) # each of 'p' will become a S/R that will be tested for bounces # set entry to price+self.settings.getint('trade_bot','i_pips') entry = add_pips2price(self.pair, p, self.settings.getint('trade_bot', 'i_pips')) # set S/L to price-self.settings.getint('trade_bot','i_pips') SL = substract_pips2price( self.pair, p, self.settings.getint('trade_bot', 'i_pips')) t = Trade(id='{0}.{1}.detect_sr.{2}'.format( self.pair, adateObj.isoformat(), round(p, 5)), start=adateObj.strftime('%Y-%m-%d %H:%M:%S'), pair=self.pair, timeframe=self.timeframe, type='short', entry=entry, SR=p, SL=SL, RR=1.5, strat='counter_b1', settingf=self.settingf, settings=self.settings) # reduce period that Counter uses so the S/R # are calculated with the most recent pivots newperiod = self.settings.get('trade_bot', 'period_range') self.settings.set('counter', 'period', newperiod) c = Counter(trade=t, init_feats=True, settings=self.settings) if len(c.pivots.plist) == 0: mean_pivot = 0 else: mean_pivot = round(c.score_pivot, 2) prices.append(round(p, 5)) bounces.append(len(c.pivots.plist)) tot_score.append(c.total_score) score_per_bounce.append(mean_pivot) # increment price to following price. # Because the increment is made in pips # it does not suffer of the JPY pairs # issue p = add_pips2price(self.pair, p, 2 * self.settings.getint('trade_bot', 'i_pips')) if prev_p is None: prev_p = p else: increment_price = round(p - prev_p, 5) prev_p = p data = { 'price': prices, 'bounces': bounces, 'scores': score_per_bounce, 'tot_score': tot_score } df = pd.DataFrame(data=data) ### establishing bounces threshold as the args.th quantile # selecting only rows with at least one pivot and tot_score>0, # so threshold selection considers only these rows # and selection is not biased when range of prices is wide dfgt1 = df.loc[(df['bounces'] > 0)] dfgt2 = df.loc[(df['tot_score'] > 0)] bounce_th = dfgt1.bounces.quantile( self.settings.getfloat('trade_bot', 'th')) score_th = dfgt2.tot_score.quantile( self.settings.getfloat('trade_bot', 'th')) print("Selected number of pivot threshold: {0}".format(bounce_th)) print("Selected tot score threshold: {0}".format(score_th)) # selecting records over threshold dfsel = df.loc[(df['bounces'] > bounce_th) | (df['tot_score'] > score_th)] # repeat until no overlap between prices ret = self.__calc_diff(dfsel, increment_price) dfsel = ret[0] tog_seen = ret[1] while tog_seen is True: ret = self.__calc_diff(dfsel, increment_price) dfsel = ret[0] tog_seen = ret[1] # iterate over DF with selected SR to create a HAreaList halist = [] for index, row in dfsel.iterrows(): resist = HArea(price=row['price'], pips=self.settings.getint('pivots', 'hr_pips'), instrument=self.pair, granularity=self.timeframe, no_pivots=row['bounces'], tot_score=row['tot_score'], settingf=self.settingf, settings=self.settings) halist.append(resist) halist = HAreaList(halist=halist, settingf="data/settings.ini", settings=self.settings) tb_logger.info("Run done") return halist