diff --git a/Base/Library/CONDccxt.py b/Base/Library/CONDccxt.py index 6cebc2f..da4b39c 100755 --- a/Base/Library/CONDccxt.py +++ b/Base/Library/CONDccxt.py @@ -202,7 +202,6 @@ def OrderProcessor(Orphan): else: # Give OliverTwist a response relay.JRLog.Write(f"{id}: Order failed with {relay.GetFailedReason(result)}",stdOut=False) - relay.JRLog.Write(f"{id} -> {cid}: {result}",stdOut=False) return 'Waiting' else: # Strike did not happen diff --git a/Base/Library/JRRoanda.py b/Base/Library/JRRoanda.py index 03c9e17..edbbed3 100644 --- a/Base/Library/JRRoanda.py +++ b/Base/Library/JRRoanda.py @@ -337,21 +337,21 @@ def PlaceOrder(self,**kwargs): if 'orderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['orderCreateTransaction']['id']) elif 'longOrderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['longOrderCreateTransaction']['id']) elif 'shortOrderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['shortOrderCreateTransaction']['id']) @@ -376,21 +376,21 @@ def PlaceOrder(self,**kwargs): if 'orderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['orderCreateTransaction']['id']) elif 'longOrderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['longOrderCreateTransaction']['id']) elif 'shortOrderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['shortOrderCreateTransaction']['id']) @@ -411,21 +411,21 @@ def PlaceOrder(self,**kwargs): if 'orderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['orderCreateTransaction']['id']) elif 'longOrderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['longOrderCreateTransaction']['id']) elif 'shortOrderCreateTransaction' in self.Results: if 'orderCancelTransaction' in self.Results: if Quiet!=True: - self.Log.Write("|- Order CANCELLED: "+self.Results['orderCancelTransaction']['reason']) + self.Log.Write("|- Order failed with: CANCELLED "+self.Results['orderCancelTransaction']['reason']) else: if Quiet!=True: self.Log.Write("|- Order Confirmation ID: "+self.Results['shortOrderCreateTransaction']['id']) diff --git a/Base/Library/JackrabbitRelay.py b/Base/Library/JackrabbitRelay.py index f8b2009..03e83ad 100755 --- a/Base/Library/JackrabbitRelay.py +++ b/Base/Library/JackrabbitRelay.py @@ -394,9 +394,11 @@ def GetFailedReason(self,res): if res==None: return None + srch='failed with:' + result=None try: - if res.find('PlaceOrder failed with:')>-1: + if res.find(srch)>-1: s=res.find('with:')+6 for e in range(s,len(res)): if res[e]=='\n': diff --git a/Base/OANDA-PlaceOrder b/Base/OANDA-PlaceOrder index 1976110..8842ec1 100755 --- a/Base/OANDA-PlaceOrder +++ b/Base/OANDA-PlaceOrder @@ -43,6 +43,11 @@ def GetPCTamount(relay,close): else: expire=(3650*86400) + # OverridePCTtable should probably be the default state for OliverTwist, since each trade is + # independant. For now though, I am going to not make this default as a safety protocol to keep trades + # linear and controlled. User can override this, but that really is the point. The user MUST take action + # to override the saety layers. + if "OverridePCTtable" not in relay.Active and "OverridePCTtable" not in relay.Order: bal=relay.GetBalance() mr=float(relay.Markets[relay.Asset]['marginRate']) @@ -263,8 +268,8 @@ def main(): relay.JRLog.Write(f'|- Minimum Amount: {minimum:.8f}') relay.JRLog.Write(f'|- Minimum Cost: {mincost:.8f}') else: - price=ticker['Ask'] if '%' in relay.Order['Units']: + price=(ticker['Ask']+ticker['Bid'])/2 amount=int(GetPCTamount(relay,price)) else: amount=int(relay.Order['Units'].split('.')[0]) diff --git a/Extras/CodeProofs/enforceFIFO b/Extras/CodeProofs/enforceFIFO new file mode 100755 index 0000000..570ee68 --- /dev/null +++ b/Extras/CodeProofs/enforceFIFO @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Jackrabbit Relay +# 2021 Copyright © Robert APM Darin +# All rights reserved unconditionally. + +import sys +sys.path.append('/home/GitHub/JackrabbitRelay/Base/Library') +import os +import json + +import JackrabbitRelay as JRR + +# Find the lowest lot size used in the list of open trades. This is a good way to make +# the entire process dynamic and fluid as lot size can be varied by any metric, +# including but not limited to, the amount of margin used. + +def LowestLotSize(relay,asset,units,step): + lowestSize=abs(units) + lotSize=abs(step) + + openTrades=relay.GetOpenTrades(symbol=asset) + + usedSize=[] + for trade in openTrades: + t=abs(int(trade['currentUnits'])) + if t not in usedSize: + usedSize.append(t) + t=abs(int(trade['initialUnits'])) + if t not in usedSize: + usedSize.append(t) + usedSize=sorted(usedSize) + + print(usedSize) + + nextSize = lowestSize # Start with the lowestSize + + while nextSize in usedSize: + nextSize+=lotSize + + # Shorts are negative so check direction + if units<0: + sign=-1 + else: + sign=1 + + print(f'EnforceFIFO: next unit size is {nextSize*sign}') + return nextSize*sign + +### +### Main code base. Place order on exchange +### + +relay=JRR.JackrabbitRelay() +if relay.GetArgsLen() > 3: + exchangeName=relay.GetExchange() + account=relay.GetAccount() + asset=relay.GetAsset() + units=int(relay.GetArgs(4)) +else: + print("An exchange, (sub)account, and an asset must be provided.") + sys.exit(1) + +ls=LowestLotSize(relay,asset,units,1) + +print(ls)