From 6c2682d841a614b9a8870b4cadccc6f7fcc427eb Mon Sep 17 00:00:00 2001 From: Rose Heart Date: Tue, 24 Oct 2023 22:52:48 +0000 Subject: [PATCH] Bug fixes. Code optimizations. Added deviation tracking to OANDA PlaceOrder. Provides grid trading functionality to TradingView indicators/strategies. Version update. Changes to be committed: modified: Base/Conditional.oanda modified: Base/JackrabbitLocker modified: Base/JackrabbitOliverTwist modified: Base/JackrabbitRelay modified: Base/Library/JRRoanda.py modified: Base/Library/JackrabbitRelay.py modified: Base/OANDA-PlaceOrder modified: Extras/CodeProofs/oandaOpenTrades --- Base/Conditional.oanda | 14 ++++++------- Base/JackrabbitLocker | 2 +- Base/JackrabbitOliverTwist | 2 +- Base/JackrabbitRelay | 2 +- Base/Library/JRRoanda.py | 19 +++++++++++++++++ Base/Library/JackrabbitRelay.py | 2 +- Base/OANDA-PlaceOrder | 35 +++++++++++++++++++++++++++++++ Extras/CodeProofs/oandaOpenTrades | 1 + 8 files changed, 66 insertions(+), 11 deletions(-) diff --git a/Base/Conditional.oanda b/Base/Conditional.oanda index 5cf616f..2b19dd0 100755 --- a/Base/Conditional.oanda +++ b/Base/Conditional.oanda @@ -75,7 +75,7 @@ def GetOrderID(res): # Calculate Price -def CalculatePriceExit(order,ts,dir,price): +def CalculatePriceExit(order,ts,dir,price,onePip): # Figure out TakeProfit or Stoploss if ts=='TakeProfit': if '%' in order[ts]: @@ -86,9 +86,9 @@ def CalculatePriceExit(order,ts,dir,price): # Pips elif 'p' in order[ts].lower(): if dir=='long': - val=price+(float(order[ts].lower().replace('p','').strip())*0.0001) + val=price+(float(order[ts].lower().replace('p','').strip())*onePip) else: - val=price-(float(order[ts].lower().replace('p','').strip())*0.0001) + val=price-(float(order[ts].lower().replace('p','').strip())*onePip) else: val=float(order[ts]) elif ts=='StopLoss': @@ -100,9 +100,9 @@ def CalculatePriceExit(order,ts,dir,price): # Pips elif 'p' in order[ts].lower(): if dir=='long': - val=price-(float(order[ts].lower().replace('p','').strip())*0.0001) + val=price-(float(order[ts].lower().replace('p','').strip())*onePip) else: - val=price+(float(order[ts].lower().replace('p','').strip())*0.0001) + val=price+(float(order[ts].lower().replace('p','').strip())*onePip) else: val=float(order[ts]) @@ -199,11 +199,11 @@ def main(): if 'TakeProfit' not in relay.Order: relay.Order['TakeProfit']='10p' # Calculate Take Profit - tp=round(CalculatePriceExit(relay.Order,'TakeProfit',dir,price),5) + tp=round(CalculatePriceExit(relay.Order,'TakeProfit',dir,price,relay.Broker.onePip),5) # Figure out StopLoss, if there is one if 'StopLoss' in relay.Order: - sl=round(CalculatePriceExit(relay.Order,'StopLoss',dir,price),5) + sl=round(CalculatePriceExit(relay.Order,'StopLoss',dir,price,relay.Broker.onePip),5) # find trade open time parts=orderDetail[0]['time'].split('.') diff --git a/Base/JackrabbitLocker b/Base/JackrabbitLocker index 4eac076..1b4fe66 100755 --- a/Base/JackrabbitLocker +++ b/Base/JackrabbitLocker @@ -28,7 +28,7 @@ import json import JRRsupport -Version="0.0.0.1.455" +Version="0.0.0.1.460" BaseDirectory='/home/JackrabbitRelay2/Base' ConfigDirectory='/home/JackrabbitRelay2/Config' LogDirectory="/home/JackrabbitRelay2/Logs" diff --git a/Base/JackrabbitOliverTwist b/Base/JackrabbitOliverTwist index bd44a8d..1942be9 100755 --- a/Base/JackrabbitOliverTwist +++ b/Base/JackrabbitOliverTwist @@ -38,7 +38,7 @@ import subprocess import JRRsupport import JackrabbitRelay as JRR -Version="0.0.0.1.455" +Version="0.0.0.1.460" BaseDirectory='/home/JackrabbitRelay2/Base' DataDirectory='/home/JackrabbitRelay2/Data' ConfigDirectory='/home/JackrabbitRelay2/Config' diff --git a/Base/JackrabbitRelay b/Base/JackrabbitRelay index 96ea918..39d20e8 100755 --- a/Base/JackrabbitRelay +++ b/Base/JackrabbitRelay @@ -16,7 +16,7 @@ import json import JRRsupport -Version="0.0.0.1.455" +Version="0.0.0.1.460" BaseDirectory='/home/JackrabbitRelay2/Base' ConfigDirectory='/home/JackrabbitRelay2/Config' LogDirectory="/home/JackrabbitRelay2/Logs" diff --git a/Base/Library/JRRoanda.py b/Base/Library/JRRoanda.py index e18626c..4e9ab56 100644 --- a/Base/Library/JRRoanda.py +++ b/Base/Library/JRRoanda.py @@ -68,6 +68,18 @@ def __init__(self,Exchange,Config,Active,DataDirectory=None): self.Currency=None self.Markets=self.GetMarkets() + self.onePip=None + + # Set the value of one pip + + def SetPipValue(self,asset): + # Value needed to calculate 1 pip for this pair + if self.onePip==None: + if abs(float(self.Markets[asset.replace('_','/')]['pipLocation']))==2: + self.onePip=0.01 + else: + self.onePip=0.0001 + # Handle the retry functionality and send the request to the broker. def API(self,function,**kwargs): @@ -169,6 +181,7 @@ def GetPositions(self,**kwargs): for pos in self.Results['positions']: asset=pos['instrument'].replace('_','/') if symbol==asset: + self.SetPipValue(symbol) if 'averagePrice' in pos['long']: units=int(pos['long']['units']) position=float(pos['long']['averagePrice'])*units @@ -189,6 +202,7 @@ def GetOHLCV(self,**kwargs): limit=str(kwargs.get('limit')) params={"granularity":timeframe.upper(), "count":limit } candles=[] + self.SetPipValue(symbol) res=v20Instruments.InstrumentsCandles(instrument=symbol,params=params) self.Results=self.API("GetOHLCV",request=res) @@ -208,6 +222,7 @@ def GetOHLCV(self,**kwargs): def GetTicker(self,**kwargs): symbol=kwargs.get('symbol').replace('/','_') params={"instruments":symbol } + self.SetPipValue(symbol) res=v20Pricing.PricingInfo(accountID=self.AccountID,params=params) self.Results=self.API("GetTicker",request=res) @@ -230,6 +245,7 @@ def GetTicker(self,**kwargs): def GetOrderBook(self,**kwargs): symbol=kwargs.get('symbol').replace('/','_') + self.SetPipValue(symbol) req=v20Instruments.InstrumentsOrderBook(instrument=symbol,params={}) self.Results=self.API("GetOrderBook",request=req,noError=True) @@ -255,6 +271,7 @@ def GetOpenOrders(self,**kwargs): if symbol==order['instrument']: oList.append(order) + self.SetPipValue(symbol) return oList # As references in GetPosition, a position may consist of one or more actual @@ -263,6 +280,7 @@ def GetOpenOrders(self,**kwargs): def GetOpenTrades(self,**kwargs): symbol=kwargs.get('symbol').replace('/','_') params={"instrument":symbol } + self.SetPipValue(symbol) req=v20Trades.TradesList(accountID=self.AccountID,params=params) self.Results=self.API("GetOpenTrades",request=req) @@ -420,6 +438,7 @@ def PlaceOrder(self,**kwargs): def GetMinimum(self,**kwargs): symbol=kwargs.get('symbol') + self.SetPipValue(symbol) minimum=1 mincost=self.GetTicker(symbol=symbol)['Ask'] diff --git a/Base/Library/JackrabbitRelay.py b/Base/Library/JackrabbitRelay.py index 680728f..9f37e24 100755 --- a/Base/Library/JackrabbitRelay.py +++ b/Base/Library/JackrabbitRelay.py @@ -104,7 +104,7 @@ def Success(self,f,s): class JackrabbitRelay: def __init__(self,framework=None,payload=None,exchange=None,account=None,asset=None,secondary=None,NoIdentityVerification=False,Usage=None): # All the default locations - self.Version="0.0.0.1.455" + self.Version="0.0.0.1.460" self.NOhtml='NO!

NO!

' self.BaseDirectory='/home/JackrabbitRelay2/Base' self.ConfigDirectory='/home/JackrabbitRelay2/Config' diff --git a/Base/OANDA-PlaceOrder b/Base/OANDA-PlaceOrder index c45f60f..6dd6c9a 100755 --- a/Base/OANDA-PlaceOrder +++ b/Base/OANDA-PlaceOrder @@ -94,6 +94,33 @@ def GetTicket(relay,asset,tid,amount): return amount +# We don't want any order "over-stacking", unless Clustering is set to yes, so we +# verify that an order isn't within range of anothwer order. Its a lazy way of +# creating an "unbounded" grid. + +def AlreadyBought(relay,asset,price,pipDistance): + openTrades=relay.GetOpenTrades(symbol=asset) + roundedPrice=round(price,5) + for trade in openTrades: + buyPrice=round(float(trade['price']),5) + if roundedPrice>=(buyPrice-pipDistance) and roundedPrice<=(buyPrice+pipDistance): + return True + return False + +# Convert a percebtage of pips to a number + +def ConvertPctPips2Value(relay,str): + # Percentage + if '%' in str: + val=float(str.replace('%','').strip())/100 + # Pips + elif 'p' in str.lower(): + val=float(str.lower().replace('p','').strip())*relay.Broker.onePip + else: + val=float(str) + + return val + ### ### Main code base. Place order on exchange ### @@ -213,6 +240,14 @@ def main(): else: amount=-minimum + # Check if this payload has a deviation. If so, validate it. + # AlreadyBought(relay,asset,price,pipDistance) + + if 'Deviation' in relay.Order: + devPips=ConvertPctPips2Value(relay,relay.Order['Deviation']) + if AlreadyBought(relay,relay.Order['Asset'],ticker['Bid'],devPips): + relay.JRLog.Error("Deviation", f"{relay.Order['Deviation']}: Required condition not met") + # Check and manage FIFO rule if 'EnforceFIFO' in relay.Active or 'EnforceFIFO' in relay.Order: if 'Step' in relay.Order: diff --git a/Extras/CodeProofs/oandaOpenTrades b/Extras/CodeProofs/oandaOpenTrades index 1abe8c1..5c29797 100755 --- a/Extras/CodeProofs/oandaOpenTrades +++ b/Extras/CodeProofs/oandaOpenTrades @@ -27,6 +27,7 @@ oo=relay.GetOpenTrades(symbol=asset) tpnl=0 for o in oo: + print(o) iu=int(o['currentUnits']) price=float(o['price']) upl=float(o['unrealizedPL'])