Exemple #1
0
    def send_order(self, order: Order):
        # check if order is val
        if order.amount == 0:
            self.logger.error("trying to send order without amount")
            return
        [posId,
         order_type] = TradingBot.position_id_and_type_from_order_id(order.id)
        if order_type == OrderType.ENTRY:
            [unused, direction] = TradingBot.split_pos_Id(posId)
            if direction == PositionDirection.LONG and order.amount < 0:
                self.logger.error("sending long entry with negative amount")
            if direction == PositionDirection.SHORT and order.amount > 0:
                self.logger.error("sending short entry with positive amount")

        self.logger.debug("added order %s" % (order.print_info()))

        order.tstamp = self.current_bars[0].tstamp
        if order not in self.account.open_orders:  # bot might add it himself temporarily.
            self.account.open_orders.append(order)
Exemple #2
0
    def __open_position(self, direction, bars, swing, open_positions):
        directionFactor = 1
        oppDirection = PositionDirection.SHORT
        extreme = bars[1].low
        capFunc = min
        if direction == PositionDirection.SHORT:
            directionFactor = -1
            oppDirection = PositionDirection.LONG
            extreme = bars[1].high
            capFunc = max
        oppDirectionFactor = directionFactor * -1

        expectedEntrySplipagePerc = 0.0015
        expectedExitSlipagePerc = 0.0015

        data: Data = self.channel.get_data(bars[1])

        if self.close_on_opposite:
            for pos in open_positions.values():
                if pos.status == PositionStatus.OPEN and \
                        TradingBot.split_pos_Id(pos.id)[1] == oppDirection:
                    # execution will trigger close and cancel of other orders
                    self.order_interface.send_order(
                        Order(orderId=TradingBot.generate_order_id(
                            pos.id, OrderType.SL),
                              amount=-pos.amount,
                              stop=None,
                              limit=None))

        if self.init_stop_type == 1:
            stop = extreme
        elif self.init_stop_type == 2:
            stop = extreme + (extreme - bars[1].close) * 0.5
        else:
            stop = capFunc(swing, (extreme + bars[1].close) / 2)
        stop = stop + oppDirectionFactor  # buffer

        entry = bars[0].open
        signalId = self.get_signal_id(bars)

        #case long: entry * (1 + oppDirectionFactor*self.min_stop_diff_perc / 100) >= stop
        if 0 <= directionFactor*(entry * (1 + oppDirectionFactor*self.min_stop_diff_perc / 100) - stop) \
                or not self.ignore_on_tight_stop:
            stop = capFunc(
                stop,
                entry *
                (1 + oppDirectionFactor * self.min_stop_diff_perc / 100))

            amount = self.calc_pos_size(
                risk=self.risk_factor,
                exitPrice=stop *
                (1 + oppDirectionFactor * expectedExitSlipagePerc),
                entry=entry *
                (1 + directionFactor * expectedEntrySplipagePerc),
                atr=data.atr)

            posId = TradingBot.full_pos_id(signalId, direction)
            pos = Position(id=posId,
                           entry=entry,
                           amount=amount,
                           stop=stop,
                           tstamp=bars[0].tstamp)
            open_positions[posId] = pos
            self.order_interface.send_order(
                Order(orderId=TradingBot.generate_order_id(
                    posId, OrderType.ENTRY),
                      amount=amount,
                      stop=None,
                      limit=None))
            self.order_interface.send_order(
                Order(orderId=TradingBot.generate_order_id(
                    posId, OrderType.SL),
                      amount=-amount,
                      stop=stop,
                      limit=None))
            if self.tp_fac > 0:
                ref = entry - stop
                if self.tp_use_atr:
                    ref = math.copysign(data.atr, entry - stop)
                tp = entry + ref * self.tp_fac
                self.order_interface.send_order(
                    Order(orderId=TradingBot.generate_order_id(
                        posId, OrderType.TP),
                          amount=-amount,
                          stop=None,
                          limit=tp))
            pos.status = PositionStatus.OPEN
Exemple #3
0
    def open_orders(self, is_new_bar, directionFilter, bars, account, open_positions):
        if (not is_new_bar) or len(bars) < 5:
            return  # only open orders on beginning of bar

        if not self.entries_allowed(bars):
            self.logger.info(" no entries allowed")
            return

        atr = clean_range(bars, offset=0, length=self.channel.max_look_back * 2)
        risk = self.risk_factor

        # test for SFP:
        # High > HH der letzten X
        # Close < HH der vorigen X
        # ? min Wick size?
        # initial SL

        data: Data = self.channel.get_data(bars[1])
        maxLength = min(len(bars), self.range_length)
        minRejLength = min(len(bars),self.min_rej_length)
        highSupreme = 0
        hhBack = 0
        hh = bars[2].high
        swingHigh = 0
        gotHighSwing = False
        for idx in range(2, maxLength):
            if bars[idx].high < bars[1].high:
                highSupreme = idx - 1
                if hh < bars[idx].high:
                    hh = bars[idx].high
                    hhBack = idx
                elif self.min_swing_length < hhBack <= idx - self.min_swing_length:
                    gotHighSwing = True
                    swingHigh = hh  # confirmed
            else:
                break

        lowSupreme = 0
        llBack = 0
        ll = bars[2].low
        swingLow = 0
        gotLowSwing = False
        for idx in range(2, maxLength):
            if bars[idx].low > bars[1].low:
                lowSupreme = idx - 1
                if ll > bars[idx].low:
                    ll = bars[idx].low
                    llBack = idx
                elif self.min_swing_length < llBack <= idx - self.min_swing_length:
                    gotLowSwing = True
                    swingLow = ll  # confirmed
            else:
                break

        rangeMedian = (bars[maxLength - 1].high + bars[maxLength - 1].low) / 2
        alpha = 2 / (maxLength + 1)
        for idx in range(maxLength - 2, 0, -1):
            rangeMedian = rangeMedian * alpha + (bars[idx].high + bars[idx].low) / 2 * (1 - alpha)

        expectedEntrySplipagePerc = 0.0015
        expectedExitSlipagePerc = 0.0015

        signalId = "sfp+" + str(bars[0].tstamp)

        # SHORT
        longSFP = self.entries != 1 and gotHighSwing and bars[1].close + data.buffer < swingHigh
        longRej = self.entries != 2 and bars[1].high > hh > bars[1].close + data.buffer and \
                    highSupreme > minRejLength and bars[1].high - bars[1].close > (bars[1].high - bars[1].low) / 2

        # LONG
        shortSFP = self.entries != 1 and gotLowSwing and bars[1].close - data.buffer > swingLow
        shortRej = self.entries != 2 and bars[1].low < ll < bars[1].close - data.buffer and lowSupreme > minRejLength \
                   and bars[1].close - bars[1].low > (bars[1].high - bars[1].low) / 2

        self.logger.info("---- analyzing: %s: %.1f %.1f %.0f | %s %.0f %i or %i %.0f %.0f | %s %.0f %i or %i %.0f %.0f " %
                         (str(datetime.fromtimestamp(bars[0].tstamp)), data.buffer, atr, rangeMedian,
                          gotHighSwing, swingHigh, hhBack, highSupreme, hh ,bars[1].high - bars[1].close,
                          gotLowSwing, swingLow, llBack, lowSupreme, ll ,bars[1].close - bars[1].low ))
        
        if (longSFP or longRej) and (bars[1].high - bars[1].close) > atr * self.min_wick_fac \
                and directionFilter <= 0 and bars[1].high > rangeMedian + atr * self.range_filter_fac:
            # close existing short pos
            if self.close_on_opposite:
                for pos in open_positions.values():
                    if pos.status == PositionStatus.OPEN and TradingBot.split_pos_Id(pos.id)[1] == PositionDirection.LONG:
                        # execution will trigger close and cancel of other orders
                        self.order_interface.send_order(
                            Order(orderId=TradingBot.generate_order_id(pos.id, OrderType.SL),
                                  amount=-pos.amount, stop=None, limit=None))

            if self.init_stop_type == 1:
                stop = bars[1].high
            elif self.init_stop_type == 2:
                stop = bars[1].high + (bars[0].high - bars[0].close) * 0.5
            else:
                stop = max(swingHigh, (bars[1].high + bars[1].close) / 2)
            stop = stop + 1  # buffer

            entry = bars[0].open
            amount = self.calc_pos_size(risk=risk, exitPrice=stop * (1 + expectedExitSlipagePerc),
                                        entry=entry * (1 - expectedEntrySplipagePerc), data=data)

            posId = TradingBot.full_pos_id(signalId, PositionDirection.SHORT)
            pos = Position(id=posId, entry=entry, amount=amount, stop=stop,
                                             tstamp=bars[0].tstamp)
            open_positions[posId]= pos
            self.order_interface.send_order(Order(orderId=TradingBot.generate_order_id(posId, OrderType.ENTRY),
                                                  amount=amount, stop=None, limit=None))
            self.order_interface.send_order(Order(orderId=TradingBot.generate_order_id(posId, OrderType.SL),
                                                  amount=-amount, stop=stop, limit=None))
            if self.tp_fac > 0:
                tp = entry - (stop - entry) * self.tp_fac
                self.order_interface.send_order(Order(orderId=TradingBot.generate_order_id(posId, OrderType.TP),
                                                      amount=-amount, stop=None, limit=tp))
            pos.status= PositionStatus.OPEN

        if (shortSFP or shortRej) and (bars[1].close - bars[1].low) > atr * self.min_wick_fac \
                and directionFilter >= 0 and bars[1].low < rangeMedian - self.range_filter_fac:
            # close existing short pos
            if self.close_on_opposite:
                for pos in open_positions.values():
                    if pos.status == PositionStatus.OPEN and TradingBot.split_pos_Id(pos.id)[1] == PositionDirection.SHORT:
                        # execution will trigger close and cancel of other orders
                        self.order_interface.send_order(
                            Order(orderId=TradingBot.generate_order_id(pos.id, OrderType.SL),
                                  amount=-pos.amount, stop=None, limit=None))

            if self.init_stop_type == 1:
                stop = bars[1].low
            elif self.init_stop_type == 2:
                stop = bars[1].low + (bars[0].low - bars[0].close) * 0.5
            else:
                stop = min(swingLow, (bars[1].low + bars[1].close) / 2)
            stop = stop - 1  # buffer

            entry = bars[0].open
            amount = self.calc_pos_size(risk=risk, exitPrice=stop * (1 - expectedExitSlipagePerc),
                                        entry=entry * (1 + expectedEntrySplipagePerc), data=data)

            posId = TradingBot.full_pos_id(signalId, PositionDirection.LONG)
            pos = Position(id=posId, entry=entry, amount=amount, stop=stop,
                                             tstamp=bars[0].tstamp)
            pos.status= PositionStatus.TRIGGERED
            open_positions[posId]= pos
            self.order_interface.send_order(Order(orderId=TradingBot.generate_order_id(posId, OrderType.ENTRY),
                                                  amount=amount, stop=None, limit=None))
            self.order_interface.send_order(Order(orderId=TradingBot.generate_order_id(posId, OrderType.SL),
                                                  amount=-amount, stop=stop, limit=None))
            if self.tp_fac > 0:
                tp = entry + (entry - stop) * self.tp_fac
                self.order_interface.send_order(Order(orderId=TradingBot.generate_order_id(posId, OrderType.TP),
                                                      amount=-amount, stop=None, limit=tp))