Oanda REST API scripts

This forum consists of sub-forums dedicated to alternative platforms to Empty4. PM me, if you have your own favourite and I will add a sub-forum for it.
TickJob
Posts: 4
Joined: Wed Jul 15, 2015 10:01 pm

Oanda REST API scripts

Post by TickJob »

Hi mcbustider,
Thank you very much to provide me so much useful information to learn. I will try them out.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

You're most welcome - enjoy the journey! :hi:
QuantHH
Posts: 3
Joined: Sun Nov 06, 2016 2:55 pm

Oanda REST API scripts

Post by QuantHH »

Thanks for the hint script and the description.

Is there a way to close all profitable trades, when the value of the trade is a certain value, independently of the number of pips or the spread of the currency pair. For example I may close all profitable trades for the USD/GBP pair which value is equal or greater than 1,0 $USD. ( pip value may be smaller than 1$)


Regards
QHH
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

QuantHH » Sun Nov 06, 2016 5:18 pm wrote:Thanks for the hint script and the description.

Is there a way to close all profitable trades, when the value of the trade is a certain value, independently of the number of pips or the spread of the currency pair. For example I may close all profitable trades for the USD/GBP pair which value is equal or greater than 1,0 $USD. ( pip value may be smaller than 1$)


Regards
QHH
Hi, QHH,

Thanks for your interest in the scripts and I hope you can find some use for them.

Since I wrote these, Oanda have started a new API, called Oanda V20. If you have opened an account with them recently, you'll need the new OandapyV20 wrapper.

All my Oanda accounts are legacy accounts, which can still be accessed by using the old Oandapy module.

I've not been using the Oanda APIs of late, as I've been concentrating on learning how to program EAs on Empty4.

However, before I stopped using the Python scripts, I wrote the following script.

I set this to run every minute using Crontab on my Ubuntu VPS.

Basically, the functionality to close profitable trades can be found in the tradeMaster(side) function.

You are looking to loop through the open trades of each pair and compare the price of each open trade (tradePrice) against the current market (Bid[0] or Ask[0]) price (newPrice).

The script uses the priceDifference variable to check if the tradePrice is further than 2 pips in profit away from market value. If it is, it will set stop loss to 2 pips and trailing stop to 5 pips.

No reason why you couldn't adapt that functionality to close all profitable trades straight away.

If you run the script in a terminal, you should be able to work out what's going on, as I make console logs throughout the script.

Use the BREAKPOINT() functions in the script to create a pause, which waits for you to press enter to continue.

Tested on Python 2.7

Hope this is some use for you!

Cheers, Nige

Code: Select all

#!/usr/bin/python2.7
import time
import datetime
import oandapy
import urllib
import decimal
from decimal import *
import httplib, json
import sys,os, os.path, inspect
import __main__

workingAccount=xxxxxx
oilDelta=5
masterLotSizeIncreaseThreshold=10
oilLotSizeIncreaseThreshold=70
tradeDelta=10
buyCurrencyList = ["GBP_AUD","AUD_JPY"]
sellCurrencyList  = ["GBP_JPY"]

#oanda = oandapy.API(environment="practice", access_token="xxxxxxxyyyyyyy-zzzzzzzzzzyyyyyyyxxxxxxx")
oanda = oandapy.API(environment="live", access_token="xxxxxxyyyyyy-yyyyyyyxxxcxxxzzzz")

currencyList = []
tradeAccountList=[]

account_id=workingAccount
offset=0
amendedOffset=0


now = datetime.datetime.now()
startNow = datetime.datetime.now()
hour=int(startNow.strftime("%H"))
minute=str(startNow.strftime("%M"))
month=str(startNow.strftime("%m"))
date=str(startNow.strftime("%d"))
year=str(startNow.strftime("%y"))



basePath='/home/mcbusrider/Dropbox/accounts/'
#basePath='/home/mum/Desktop/'
directory=basePath
filename=str(workingAccount)+"_account_trading_log.txt"
if not os.path.exists(directory):
  os.makedirs(directory)

dest_filename=directory+filename

newline="--------------------------------------------------------------------------------"

print dest_filename
#sys.stdout = open(dest_filename, 'w')

path="/home/mcbusrider/Dropbox/scripts/"

def BREAKPOINT():
	raw_input("Press Enter to continue...")
def startTime():
	print newline
	print "START OF SCRIPT:"+str(startNow)
	hour=int(startNow.strftime("%H"))
	print"hour = :"+str(hour)
	minute=int(startNow.strftime("%M"))
	print"minute = :"+str(minute)
	print newline


def endTime():
	print newline
	now = datetime.datetime.now()
	print "Working account: "+str(workingAccount)
	print "END OF SCRIPT:"+str(now)
	print newline

startTime()


'''if hour<7 or hour>21:
	tradeDelta=100
elif hour>17:
	tradeDelta=50
else:'''
#tradeDelta=10
print "hour=="+str(hour)+", so tradeDelta is set to: "+str(tradeDelta)

saveTradeDelta=tradeDelta

## Start of Buy Order section
masterBalance=0
masterNAV=0
masterNAVFree=0
masterUsedMargin=0
masterFreeMargin=0
masterRPL=0
masterUPL=0
masterOpenTrades=0
oldBid=0
oldAsk=0
pair=""
side=""
newPrice=0

openTrades=0
defaultSize = 1
size=defaultSize
lotSizeIncreaseThreshold=1.76
accountSize={}
accountNAVFree={}
accountBalance={}
accountRPL={}
accountOpenTrades={}
accountUPL={}
accountFreeMargin={}
accountUsedMargin={}
accountNAV={}

stagger=.001
offset=stagger
account_id = workingAccount
now = datetime.datetime.now()







def tradeMaster(side): 
	placeTrade=False
	twentyTrade=False
	losingTrade=False
	pair=each



	print "testPosition: line 99"
	response = oanda.get_prices(instruments=pair)
	prices = response.get("prices")	
	print "prices: "+str(prices)


	spread = prices[0].get("ask")-prices[0].get("bid")
	if pair == "AUD_JPY" or pair == "CAD_JPY" or pair == "CHF_JPY" or pair == "EUR_JPY" or pair == "GBP_JPY" or pair == "NZD_JPY" or pair == "USD_JPY" or pair =="SGD_JPY" or pair == "WTICO_USD" or pair == "ZAR_JPY"  or pair == "TRY_JPY" or pair == "BCO_USD":	
		spread=spread*100
	else:
		spread=spread*10000
	print "spread: "+str(spread)
	tradeDelta=saveTradeDelta+spread
	print "tradeDelta: "+str(tradeDelta)
	if pair=="WTICO_USD" or pair=="BCO_USD":
		tradeDelta=tradeDelta*oilDelta+spread
		lotSizeIncreaseThreshold=oilLotSizeIncreaseThreshold
	else:
		lotSizeIncreaseThreshold=masterLotSizeIncreaseThreshold
	print "setting lotSizeIncreaseThreshold to: "+str(lotSizeIncreaseThreshold)
	print "setting tradeDelta to saveTradeDelta + spread: "+str(tradeDelta)
	#raw_input("press enter...")



	if side=="sell":
		newPrice = prices[0].get("ask")
	else:
		newPrice = prices[0].get("bid")
		
	trades_response = oanda.get_trades(account_id,instrument=pair,count=500)
	trades = trades_response.get("trades")
	print "trades:"+str(trades)
	placeTrade=False
	leastDifference=200000
	for i in trades:
		if placeTrade==False:
			tradePrice = i.get("price")
			print "tradePrice="+str(tradePrice)
			tradeId = i.get("id")
			print "tradeId="+str(tradeId)
			tradeInstrument=i.get("instrument")
			print "tradeInstrument:"+str(tradeInstrument)
			side = i.get("side")
			print "side: "+str(side)	
			stopLoss = i.get("stopLoss")
			print "stopLoss: "+str(stopLoss)
			print "newPrice: "+str(newPrice)
			print "checking "+str(pair)+" trades only."
		
			if side=="sell":
				priceDifference=tradePrice-newPrice
			else:
				priceDifference=newPrice-tradePrice
			print "priceDifference: "+str(priceDifference)	
			if pair == "AUD_JPY" or pair == "CAD_JPY" or pair == "CHF_JPY" or pair == "EUR_JPY" or pair == "GBP_JPY" or pair == "NZD_JPY" or pair == "USD_JPY" or pair =="SGD_JPY" or pair == "WTICO_USD" or pair == "ZAR_JPY"  or pair == "TRY_JPY" or pair == "BCO_USD":	
				priceDifference=priceDifference*100
				print "pair = multiply by 10 to give pip value..."
				offset=.02
			else:
				priceDifference=priceDifference*10000
				print "pair = multiply by 100 to give pip value..."
				offset=.0002
			print "amended pip value: priceDifference="+str(priceDifference)

			if priceDifference<2:
				print "This is a losing trade..."
				if priceDifference<0:
					priceDifference=-priceDifference
				print "This trade: price difference is :"+str(priceDifference)
				if priceDifference<leastDifference:
					print"This trade is the closest to market value so far: amending leastDifference to: "+str(priceDifference)
					leastDifference=priceDifference
				losingTrade=True
			else:
				print "This is a winning trade: calling amend trade function"
				if stopLoss==0:
					if side=="buy":
						response = oanda.modify_trade(account_id,tradeId,stopLoss=(tradePrice+offset),trailingStop=5)
					else:
						response = oanda.modify_trade(account_id,tradeId,stopLoss=(tradePrice-offset),trailingStop=5)
		
				#time.sleep(.1)


			#if leastDifference<tradeDelta:
			#"FOUND TRADE < tradeDelta, so no point checking rest of trades.  HOWEVER, still need to check all trades in this pair, to close any profit trades.  If changed in future, to exit loop, set PlaceTrade=True"
			#placeTrade=True		
			#time.sleep(.1)
		else:
			continue
	print "checking "+str(pair)+" done."
	print "leastDifference="+str(leastDifference)
	print "changing offset value, if appropriate...)"
	print "side: "+str(side)
	print "leastDifference: "+str(leastDifference)
	if leastDifference>tradeDelta:
		print "least difference>tradeDelta ("+str(leastDifference)+"), so placing "+str(side)+" trade for "+str(pair)+" at market value"

		print "CHECKING BALANCE..."

		response = oanda.get_account(account_id)
		#time.sleep(0.1)
		print "Account Info: "+str(response)


		balance = response.get("balance")
		accountBalance[account_id]=balance
		print "balance: "+str(balance)	

		UPL = response.get("unrealizedPl")
		accountUPL[account_id]=UPL
		print "Unrealized Profit Loss(UPL): "+str(UPL)

		usedMargin = response.get("marginUsed")
		accountUsedMargin[account_id]=usedMargin
		print "usedMargin: "+str(usedMargin)

		freeMargin = response.get("marginAvail")
		accountFreeMargin[account_id]=freeMargin
		print "freeMargin: "+str(freeMargin)


		NAV = balance+UPL
		accountNAV[account_id]=NAV
		print "NAV: "+str(NAV)

		NAVfree=NAV/100*60
		accountNAVFree[account_id]=NAVfree
		print "NAVfree: "+str(NAVfree)


		lotSizeIncreaseThreshold=lotSizeIncreaseThreshold+(NAV/(lotSizeIncreaseThreshold*200))
		if freeMargin<(usedMargin+(usedMargin/100*10)):
			lotSizeIncreaseThreshold=lotSizeIncreaseThreshold*2			
		size=int(NAV/lotSizeIncreaseThreshold)
		if size==0:
			size=1
		print "size for "+str(pair)+" trade: "+str(size)
		print "PLACING ORDER for "+str(pair)
		response = oanda.create_order(account_id, 
    		instrument=pair,
   		units=size,
   		side=side,
    		type='market',
    		price=newPrice
		)
	else:
		print "TRADE NOT ALLOWED - TRADE TOO CLOSE TO MARKET VALUE"
	return


side="buy"
for each in buyCurrencyList:
	tradeMaster(side)


side="sell"
for each in sellCurrencyList:
	tradeMaster(side)

startTime()
endTime()


workingAccount
Your Oanda legacy account number, expressed as an Int (number with no quote marks around it!)

masterLotSizeIncreaseThreshold
This increases the lot size by 1 unit every x units of account currency NAV.

Similar to Steve's "sizePerDollop" variable.

For example, if your account is in USD and your NAV is $200 with a masterLotSizeIncreaseThreshold of 10, the lotSize for each trade the script places will be 20:

lotSize=NAV/masterLotSizeIncreaseThreshold

Or

$200 NAV/$10 masterLotSizeIncreaseThreshold=20 units per trade

I calculate NAV like this:

NAV = balance+UPL

(UPL= Unrealized Profit Loss)

tradeDelta
Minimum distance in pips between trades. The script checks all open trades in each pair and will not open another trade if the Ask[0]/Bid [0] prices are less than this value in pips away from any trades in this pair.

For example: a GBP_JPY trade is open at 128.5
tradeDelta is 10
No trades will be opened by the script between 128.4 and 128.6 (+- 10 pips either side of open trade)

oilDelta/oilLotSizeIncreaseThreshold
Allows you to set different values if you are trading BCO_USD or WTICO_USD. You could easily expand this functionailty for other commodities, eg Copper, Silver etc.

If you want to save the text generated by the program to a log file, uncomment out line 53.
You'll need to change the directory and filename variables to fit your own system.
Last edited by mcbusrider on Mon Nov 07, 2016 5:43 pm, edited 7 times in total.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

The latest script adds the spread into the equation when it works out how far from Bid[0] or Ask[0] price to place new trades.

With regards to adding a basket closure or working out how much each trade or a series of trades was profiting, I just worked on closing each profitable trade, so I never added basket trading functionality. It's entirely feasible to add it, but not something I've done personally.

I was trading such small trades (<20 units each trade) that it seemed pointless adding up the profits, I just set the script to modify any trade that was more than 2 points in the green by setting a 2 pip stop loss with a 5 pip trailing stop.

This let the winners run. I just kept the losers open to see what would happen.

Trading such small trade sizes lets you keep trades open for as long as you like without too much drama on the drawdown side of things - the interest was a bit of a killer after a while but it was still making a fair amount of money most days.

If things started to get too crazy on drawdown, I'd just soak up some of the profits by manually closing the worst losing trades.

The trading went OK this year; I used some of the account balance to sort a load of dental work out :smile:

I'll probably look to get back to using the Oanda REST API's at some point in the future, but right now I'm enjoying learning MQL4.

Despite the unreliability and quirks of the platform, pretty much every broker lets you use Empty4, so it seems the logical progression to target that program.

It's a shame that Empty4 has a 1,000 unit (0.01 lot) lower limit for trades. Oanda lets you go down to 1 unit through REST API, but not through Empty4.

I just want to make sure that I'm not solely dependant on one broker.
QuantHH
Posts: 3
Joined: Sun Nov 06, 2016 2:55 pm

Oanda REST API scripts

Post by QuantHH »

Hello

Thanks once more for the information and the script, is not exactly what I am looking to do, but it provides me hints and a clear view of how it could be done. I am doing many small trades in short times, so I am interested in closing all the profitable trades which are having a profit > 0.01 $ , and checking that often, in intervals. The strategy for generating the orders is still tested, but as you said v20 it is now implemented in Oanda API and it offers hedging, so I am just having 50 % of the positions in one direction and 50 % in the other direction, and closing them, when they are profitable, in short intervals, and repeat the operation as much as possible during a trading day.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

If you want to run the script more than once a minute, you could use something like this:

Code: Select all

#!/usr/bin/python2.7
import time
i=15
while i>0:
	time.sleep(1)
	print "Countdown to run script: "+str(i)+" seconds."
	i=i-1
print "importing traderScript.py"
import traderScript
If you run this script on crontab every minute, it causes an (i*second) delay before importing your trading script.

If you make a few of these scripts with varying delay times, importing the same script, then run them all every minute on a crontab, you can effectively run your main trading script more than once per minute.

Cron only allows you to run scripts once per minute maximum, so this is a workaround.

Don't have too many scripts running, each instance of the script opens a new connection to the API and if you have too many open, the server will refuse any new connections.

TOO MANY SCRIPTS OPEN WILL CAUSE ALL SORTS OF SHIT with your computer, including memory leaks and crashes.

This will also probably happen when you are asleep and blissfully unaware of the carnage happening on your trading VPS, until you try to log in the next day and get the horrible sinking feeling that SOMETHING IS NOT QUITE RIGHT WITH YOUR INSTALLATION ANYMORE.

My script took about 4 seconds to run - this was checking about 500 open trades. I had six scripts a minute running (one every ten seconds) which worked out fine.

Check the values of the startTime() and endTime() functions in the terminal for an idea of how long the script takes to run. You should see these printed to the console just before the script finishes executing, so you don't need to scroll up through all the printout.

Good luck!
Last edited by mcbusrider on Mon Nov 07, 2016 6:32 pm, edited 7 times in total.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

Sorry I can't help you out much on using the V20 endpoints, there's a module on GitHub called OandapyV20 but I never messed around with it (I still have legacy accounts).

I read the documentation on the Oanda developer portal but I was a bit disappointed with it; all the info on the V20 pages seemed to link to old REST scripts.

If you manage to get something working on V20, please share your findings, I'm sure someone on here will find it helpful.

It'll probably take a bit of hacking to replace the legacy endpoints in my scripts with the new V20 endpoints, but most of the basic functionality of the script will work the same.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

If you're hedging, check out Dottybot for some great ideas on how to offset hedge trade closures.

http://www.stevehopwoodforex.com/phpBB3 ... =93&t=4797

The manual describes the methods in great detail, so I won't do so here.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

To close all profitable trades only when profit> $1 over all trades (leave losers open), I would loop through all open trades.

The loop would be used to calculate the Unrealized P&L of each open trade in that pair (or over multiple pairs, if you are taking that into account).

Add the calculated p&l for each open trade to a master Profit variable (Google is your friend if you want to know how to calculate P&L on forex trades)

Anything that shows a profit: append a list with the trade ID of that profitable trade.

When the loop has completed, check if masterProfit> $1

If masterProfit>$1, loop through and close each trade in the trade ID list of profitable trades.
Post Reply

Return to “Alternative platforms”