예제 #1
0
    def timeToClose(self, currentQuote, strategyMaker):
        """is it time to close (take-profit, save-loss, stop-loss triggered), or update stop-loss-value?"""
        avgPrice = self.relevantPrice(currentQuote)
        newStopValue = self.expectedTrailingStopValue(currentQuote)
        benefRatio = 0.0
        lossRatio = 0.0
        holdRatio = 0.0

        if(newStopValue is not None and self.trailingStopValue is not None):
            if((self.forBUY and newStopValue < 0.9999*self.trailingStopValue) or
               (not self.forBUY and 0.9999*newStopValue > self.trailingStopValue)):
               corelog.critical( "WARNING: stop value calculations are retrograde!" )
               import pdb; pdb.set_trace()
               newStopValue2 = self.expectedTrailingStopValue(currentQuote)

        # import pdb; pdb.set_trace()

        if(self.forBUY):
            delta = avgPrice - self.entryQuote.ask.o
            benefRatio = 100*delta/self.expGain
            lossRatio  = -100*delta/self.expLoss
            # whe losing, use lossRatio and make it negative
            holdRatio  = -lossRatio if(delta<0)else benefRatio

            if(avgPrice < self.saveLoss ):
                return ('save-loss', 'close', delta, lossRatio)
            elif(avgPrice > self.takeProfit):
                return ('take-profit', 'close', delta, benefRatio)
            elif(self.trailingStopValue is None and newStopValue is not None):
                return ('trailing-stop', 'trailing-stop', delta, holdRatio)
            elif(self.trailingStopValue is not None and newStopValue is not None and round(newStopValue,7) != round(self.trailingStopValue,7)):
                return ('trailing-stop', 'trailing-progress', delta,holdRatio)
            elif(self.trailingStopValue is not None and self.trailingStopValue>avgPrice):
                delta = self.trailingStopValue - self.entryQuote.ask.o
                return ('trailing-stop', 'close', delta, benefRatio)

        else:

            delta = self.entryQuote.bid.o - avgPrice
            benefRatio = 100*delta/self.expGain
            lossRatio  = -100*delta/self.expLoss
            holdRatio  = benefRatio if(delta>0)else -lossRatio

            if(avgPrice > self.saveLoss ):
                expLoss = self.saveLoss - self.entryQuote.ask.o
                return ('save-loss', 'close', delta, lossRatio)
            elif(avgPrice < self.takeProfit ):
                return ('take-profit', 'close', delta, benefRatio)
            elif(newStopValue is not None and self.trailingStopValue is None):
                return ('trailing-stop', 'trailing-stop', delta, holdRatio)
            elif(self.trailingStopValue is not None and newStopValue is not None and round(newStopValue,7) != round(self.trailingStopValue,7)):
                return ('trailing-stop', 'trailing-progress',delta,holdRatio)
            elif(self.trailingStopValue is not None and self.trailingStopValue < avgPrice):
                delta = self.entryQuote.bid.o - self.trailingStopValue
                return ('trailing-stop', 'close', delta, benefRatio)

        if(self.trailingStopNeedsReplacement):
            return ('trailing-stop', 'trailing-update', delta, holdRatio)

        return ('hold', 'hold', delta, holdRatio)
예제 #2
0
    def refresh(self, force=False, raiseX=True):
        if (self.simulation): return

        if (force or self.refreshIsDue()):
            try:
                whenT = time.time()
                accountResp = self.api.account.get(self.accountId)
                self.account = accountResp.get('account', '200')
                self.accountTime = time.time()
            except:
                corelog.critical("issue refreshing account ... skipping ...")
                if (force or raiseX): raise
예제 #3
0
    def executeTrade(self, looper, pos,wait=1200,noMore=5):
        """Execute a trade for a position, and a looper.
           On success, returns a 2-tuple: position object identified after successful trade, trade id
           When trade-id is None, the position object is the same as originally thought, the trade hasn't happened yet
           On failure, the 2-tuple is not returned, but None is returned. Some other issue at the broker (or with the order) have occurred"""

        kwargs = {}
        kwargs['instrument'] = looper.instrumentName
        # kwargs['price']=pos.entryQuote.ask.o if(pos.forBUY) else pos.entryQuote.bid.o
        kwargs['units']=(pos.size if(pos.forBUY) else -pos.size)
        #kwargs['timeInForce']='GTC'
        # saveLoss / takeProfit - user minimal minimumTrailingStopDistance to not annoy the broker
        mtsd = looper.instrument.minimumTrailingStopDistance
        sl = pos.saveLoss;tp=pos.takeProfit

        def nicepadding(x,prec):
            x = str(x)
            if(x.find(".")>0):
                x += "00000"
                return x[0:(x.index(".")+1+prec)]
            return x

        kwargs['stopLossOnFill'] = {"price": nicepadding(sl, looper.displayPrecision)}
        kwargs['takeProfitOnFill'] = {"price": nicepadding(tp, looper.displayPrecision)}
        corelog.debug(kwargs)
        response = looper.api.order.market(
            looper.accountId,
            **kwargs
        )
        if(not(response.status == 201 or response.status == '201')):
            corelog.critical( "Position / Trade could not be executed...")
            corelog.critical(response.body)
        else:
            newTrades =[]
            prevTradeIDs = map(lambda t: t.id, looper.account.trades)

            while(len(newTrades)==0):
                time.sleep(wait/1000.0)
                looper.refreshPositions(self, force=True)
                newTrades = [ t for t in looper.account.trades if t.id not in prevTradeIDs and t.instrument == looper.instrumentName ]
                if(len(newTrades)==0):
                    noMore -= 1
                    if(noMore>0):
                        corelog.info("new trade not executed yet - waiting again...")
                    else:
                        corelog.warning("new trade not executed yet - but continuing...")
                        return pos, None

            newPos = self.makeFromExistingTrade(pos.entryQuote, looper.account, newTrades[0].id)
            # if(pos.trailingSpecs is not None):
            #     newPos.calibrateTrailingStopLossDesireForSteppedSpecs(pos.traillingSpecs,
            return newPos, newTrades[0].id
        return None
예제 #4
0
    def executeClose(self, looper, pos, size=None, wait=1200, noMore=5):
        """ when the close executes, this returns a pair (position, trade-id).
            If the position is actually closed, then the position is returned as None, so what is returned is (None, trade-id).
            If the close fails, None is returned """
        kwargs = {}
        if (size is not None):
            fsize = float(size)
            if (pos.size > fsize):
                kwargs["units"] = str(size)
            else:
                raise ValueError(
                    "Cannot use executeClose to with a size greater than current position: {} is great than current {}"
                    .format(size, pos.size))

        response = looper.api.trade.close(looper.accountId, pos.tradeID,
                                          **kwargs)
        if (response.status.code == "200" or response.status.code == 200):
            corelog.debug("Closing trade {} with {} was successful".format(
                pos.tradeID, kwargs))
        else:
            corelog.critical("Unable to close trade: {}\n{}".format(
                response.status, response.body))
            return None

        myTrade = None
        while (myTrade is None and noMore > 0):
            time.sleep(wait / 1000.0)
            looper.refreshPositions(self, force=True)
            myTrades = [
                t for t in looper.account.positions if t.id == pos.tradeID
            ]
            if (len(myTrades) > 0):
                if (float(myTrades[0].currentUnits) < float(pos.size)):
                    myTrade = myTrades[0]
            else:
                if (size is None):
                    # the position is not on the account (not open, but gone, closed) and we didn't pass a size, so it is all good.
                    break
                else:
                    noMore -= 1

        if (myTrade is not None):
            newPosVersion = self.makeFromExistingTrade(pos.entryQuote,
                                                       looper.account,
                                                       myTrade.id)
            return newPosVersion, myTrade.id
        else:
            return None, pos.tradeID