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.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

Latest trading script:
http://www.stevehopwoodforex.com/phpBB3 ... 10#p149134

For running more than one script per minute on crontab:
http://www.stevehopwoodforex.com/phpBB3 ... 49#p149149

Close All Profitable Trades Script:
This post.

Place Pending Order Script:
http://www.stevehopwoodforex.com/phpBB3 ... 86#p124919

Written in Python, using Oandapy wrapper
Scripts for the Oanda REST API


REALLY IMPORTANT: IF YOU'RE USING NEW ACCOUNTS WITH OANDA AND WANT TO TRY THESE SCRIPTS OUT, YOU'LL NEED TO ADAPT THEM TO USE THE OANDAPYV20 WRAPPER.

ALL MY SCRIPTS WORK WITH THE LEGACY API AND THE OANDAPY WRAPPER MODULE - NOT WITH THE NEWER V20 API.

THIS IS BECAUSE ALL MY ACCOUNTS WITH OANDA ARE LEGACY ACCOUNTS, NOT V20 ACCOUNTS.

CHEERS!

NIGE




Hi, everyone,

It's great to be a part of this community and I feel, after silently lurking for a few months, that it's time to give something back.

I'm a novice coder and this is my first serious attempt at making a trading script work :arrrg: :youknow: .

If you don't code yet, or are struggling, I can assure you that it's worth sticking with! Equally, if you are a more experienced coder, please feel free to amend or advise - I'm really enjoying the journey!

I hope you find this script (written in Python using the Oandapy wrapper) and the ideas presented here useful.

I believe the Oanda REST API to offer great functionality but I haven't found many scripts around which use it. I hope this post may go some way towards changing that situation.

I guess I should add the usual stuff about losing money with Forex, etc...USE A PRACTICE ACCOUNT IF YOU'RE IN DOUBT!!!

This script has been working ok, but that just means I haven't discovered any issues with the code yet. Again, USE A PRACTICE ACCOUNT IF YOU'RE IN DOUBT!!!

Anyhoo...

THE BACKGROUND

I've been using Oanda for a while now, with no major issues. I like this broker because:

1) You can split your main account into a number of sub-accounts (I believe the limit is 19 sub-accounts - I have 15 at the moment) and you can move money around between the accounts, up to a daily limit of these types of transactions (I've only ever hit this once). This limits your exposure in any one account, which in turn allows you to trade more aggressively, if this kind of thing floats your boat.

2) You also have a choice of currency on these accounts and you can use these sub-accounts to change currency at the current Oanda market rate, if you wish to go down that route.

3) They allow you to trade from 1 unit (0.00001 lot) upwards, in increments of 1 unit, instead of the 1000 unit lower limit (0.01 lot) of pretty much everything else out there. This allows precision sizing of lots and also opens up live trading strategies which would normally be out of reach until you get five grand in the bank.

4) Their in-house fxTrade trading platform works really well, for what it is. They have good versions for iPhone and Android.

THE IDEA

So, there I was, happily scalping away at my 10 unit lot sizes on my smartphone, growing my account by about a penny a week, when I had a brainwave of automating some of the tasks.

I wanted to code a script to close all profitable trades, over all sub-accounts.

THE ISSUES

However, Empty4 doesn't recognise anything under 1000 units (0.01 lot), so an Expert Advisor or Script on that platform was not going to be fit for purpose, as I was only trading a 1/100th of this lot size.

Also, it gets a bit messy if you want to automatically change accounts in Empty4, unless you run multiple instances of the program (with the relevant increase in required processing power). This is ok for one or two accounts, perhaps, but not too good for 15 accounts if you're paying by the gigabyte for a VPS...

THE SOLUTION

After some digging around, I found this thing called the Oanda REST API.

It's like a kind of interface between user and account. You can do all the necessary trading stuff with it: get market prices, open and close pending orders and trades but, most importantly, you can do it all with unit increments and minimum size of 1 unit.

There's also a number of programming language "wrappers" linked on the Oanda REST API developer pages. These allow you to use your programming language of choice to code your scripts.

I looked through a few of these and Python seemed to offer the best example code, so I installed the wrapper and started amending the script until I got it to work.

THE "closeAllProfitableTrades.py" OANDA REST API (PYTHON/OANDAPY) SCRIPT

To make this script work, you'll need (at least) the following:

1) a Python interpreter. If you use Linux, this comes inbuilt. I don't know about Mac, but you can find a Windows Python IDE pretty easily.

2) the "Oandapy" wrapper (Google "Oandapy" or get it from the link at the Oanda REST API developer pages). This goes in the same folder as your script and allows the Python interpreter to interface with the Oanda REST API.

3) an Oanda practice account (or live account, if you're feeling more adventurous).

4) an Oanda REST API access token - you get this from the Oanda website, this is your personal token and allows UNLIMITED ACCESS to all your accounts (including deleting all trades) so TAKE CARE WITH IT!!!

5) a Text Editor (or Python IDE) for amending/generating the script with your own account information. I recommend using "Gedit" on Ubuntu or "Notepad ++" on Windows, as these highlight the script/comment text in different colours.

6) Use the text editor to save the attached code 'closeAllProfitableTrades.py' in the same directory as Oandapy.py

You'll need to enter your account details and the REST API token in the relevant parts of the script, using the text editor/IDE.

If you're using live accounts, you'll also need to change the "environment" variable from "practice" to "live"

N.B. there are different Access Tokens for live and practice accounts - make sure you're using the correct one for your account type(s)!

WHAT THE SCRIPT DOES (or at least, what the script is designed to do...) :youknow:

I've added some notes in the script, which should explain the functionality in depth. However, as a brief overview, it's designed to run once, check the price of all open trades in all sub-accounts and close any that are in profit over a specified amount (the "offset" variable).

It works on any lot size from 1 unit (0.00001 lot) up, on all open trades and on all sub accounts with Oanda.

It's probably very clunky and no doubt there is a fair bit of redundant code in there, but it works (tested on Lubuntu Linux).

AUTOMATING IT:

The script can easily be made to run infinitely (using a 'while True:' loop and adding a 'time.sleep(3600)' - for a one hour delay), but I personally prefer to run it as a one-shot script on an automated scheduler (I use Crontab on Lubuntu) as I don't trust my code enough yet to have it run indefinitely!

If you're manually trading, this is a real timesaver on closing all your profitable trades.

Happy trading!

Nige
:!!:


closeAllProfitableTrades.py

Code: Select all

#!/usr/bin/python

##  by mcbusrider 2015  
'''
The MIT License (MIT)

'closeAllProfitableTrades.py' Copyright (c) 2015 mcbusrider (Steve Hopwood Forex forum user)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
'''
## Import relevant modules
import httplib, json
import sys
import json
import urllib
import time
import datetime
import oandapy ## see below for more info on this module 
'''
'oandapy' is available from GitHub (or from Oanda's REST API developer pages) and released under the following license:

The MIT License (MIT)

Copyright (c) 2014 OANDA Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''

## Declare Global Variables ##
oanda = oandapy.API(environment="practice", access_token="xxxxxxxxxxxxxxxxxxxxxxxxxx1234567890yyyyyyyyyyyyyyyyyyyyyyyyyyyy")## get your "access_token" from Oanda - this will allow the script to access your accounts - SO USE IT WITH CARE!!!
## There are 3 potential 'environments': 'live', 'practice' and 'sandbox'.  Check out the docs at Oanda REST API developer pages for more information.
account_id=123456 ## this will eventually be set to the account number item in the account list
ask=None ## declare 'ask' variable 
price=None ## declare 'price' variable
prices=None ## declare 'prices' variable
bid=None ## declare 'bid' variable
pair=None ## declare 'pair' variable
account_list= [123456, 789012] ## add your Oanda account/sub-account numbers to this list, seperated by commas
account=0 ## declare ' account' variable - this is used as a counter to iterate through the 'account_list' list 
account_list_end=(len(account_list)) ## account_list_end' variable contains the number of items in the account_list.  Used in conjunction with the 'account' variable to enable us to loop through the accounts, calling the 'closeAllTrades' function for each account

### "CloseAllTrades" Function ###
def closeAllTrades(account_id):##define the main function of the script
	print "Account number: "+str(account_id)	## print the Account number we're working on
  	trades_response = oanda.get_trades(account_id) ## gets a list of all open trades for this account
	trades = trades_response.get("trades")	## 'trades' variable now set to contain information for all open trades on this account
## set up loop to iterate through all open trades
	i=0	## start loop at first trade
	j=(len(trades))## finish loop at last trade
## j=length of list of trades (giving length of list)
	while i<j: ## if there are still some trades left to check...
## loop until end of list of trades is reached
		instrument=trades[i].get("instrument") ## 'instrument' is now set to currency pair for this trade
		print "instrument: "+str(instrument) ## print currency pair for this trade
		prices_response = oanda.get_prices(instruments=instrument) ## get market prices for this currency pair from Oanda
		prices = prices_response.get("prices")## 'prices' variable now set to market info for the currency pair
		print "current trade info: "+str(prices) ## print info for the currency pair
## Set current ask and bid prices for this currency pair
		ask = prices[0].get("ask")
		bid = prices[0].get("bid")
## Print current ask and bid prices for this currency pair
		print "closeAllTrades ask: "+str(ask) 	
		print "closeAllTrades bid: "+str(bid) 
		trade_id=trades[i].get("id") ## 'trade_id' variable now contains the current trade number
		print "trade_id: "+str(trade_id) ## print 'trade_id' (current trade number)
		price = trades[i].get("price")	## price' variable now contains the original opening price for the current trade
		print "price: "+str(price) ## print 'price' (the original opening price for the current trade)
		side=trades[i].get("side")	## is current trade a buy or a sell trade?  'side' variable now contains this information
		print "side: "+str(side)	## print 'side' (whether it's a buy or a sell trade)
		instrument=trades[i].get("instrument") ## 'instrument' variable is now set to the currency pair of the current trade
		pair=instrument	## set 'pair' variable equal to 'instrument' variable (currency pair of current trade)
		print "instrument: "+str(instrument) ## print 'instrument' (equal to 'instrument' variable (currency pair of current trade))'''
##  
		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":## if 'pair' is one of the above, one pip is worth 0.01...
			offset=.05 ## ...so 'offset' variable is set to the "Take Profit" in pips - this is used to offset the market price by a number of pips.  Default = 5 pips...
		else:
			offset=.0005 ## if 'pair' is not one of the above pairs, must amend offset to reflect correct pip price, as one pip is now worth 0.0001.  Again, Default = 5 pips		
  		if side=='buy':	## if it's a buy trade...					
				print "Account number: "+str(account_id)
				print "checking: buy trade number: "+str(trade_id)
## Check Trade/Close Buy Trade if Take Profit is reached					
				if bid>(price+offset): ## if bid price is more than current market price, plus Take Profit...	
						print "closing: sell trade number: "+str(trade_id)
						response = oanda.close_trade(account_id,trade_id) ## run "Oanda close trade script" on this account, this trade
		else:	## otherwise, it must be a sell trade...
## Check Trade/Close Sell Trade if Take Profit is reached				
				print "Account number: "+str(account_id)		
				print "checking: sell trade number: "+str(trade_id) 
				if ask<(price-offset): ## if ask price is less than current market price, minus Take Profit...'''
						print "closing: sell trade number: "+str(trade_id) 
						response = oanda.close_trade(account_id,trade_id)## run "Oanda close trade script" on this account, this trade
		time.sleep(10)	## wait ten seconds between closing trades, so you can see what's going on.
				## This has been tested as working on the open markets with a value of .1 seconds.
				## If this line isn't here, you sometimes get a "too many open connections" error from Oanda.
		i=i+1   ## move on to next trade and loop again
  	return		## end function when last trade check/close complete

## 'closeAllTrades' CALL LOOP ##

## Loop through each account_id in account_list and call 'closeAllTrades' function for each account_id

while account < account_list_end: ## this will loop until each 'account' in the 'account_list' has been checked
	account_id=account_list[account] ## 'account_id' is now set to the 'account'-numbered item in 'account_list' list
	account=account+1		## increase 'account' counter, ready for next time round
	closeAllTrades(account_id)	## call script for this 'account_id'
Last edited by mcbusrider on Mon Nov 07, 2016 8:05 am, edited 7 times in total.
TickJob
Posts: 4
Joined: Wed Jul 15, 2015 10:01 pm

Oanda REST API scripts

Post by TickJob »

Hi mcbusrider,

I also like to try Oanda auto trade but I don't how to start. Could you help me to start? The auto trading program basically do the following:
1. submit a series of limit buy or sell orders initially,
2. add some more orders when certain number of initial orders become open orders,
3. check total profit reaching profit target then close all orders
4. repeat 1.

Thanks in advanced.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

Hi, TickJob,

Thanks for your interest in this; I'll certainly do my best to help you get up and running with using the REST API, but first we need to be on the same page.

May I just ask if you have a Python interpreter installed on your operating system? If not, this is your first step.

Once you have the interpreter installed, you also need to install Oandapy, which you can find on GitHub or through a Google search. Check out the sample scripts that come with Oandapy and see if you can adapt any of that code for your own stuff.

I have a Python script for opening pending orders, which I'll be happy to share with you in a few hours' time, when I get to my computer.

I've also made a script which closes all profitable trades which are over a certain pip profit threshold.

I run both scripts on a Lubuntu VPS at regular intervals, using Crontab task scheduler. This ensures that if the script crashes at some point during execution, it will start up again at the next scheduled runtime.

These two scripts should at least get you up and running with opening/closing trades and it should be pretty easy to modify the logic in these scripts to fit your preferred open/close scenarios.

I should be able to post the scripts in about 12 hours or so.

Cheers,

Nige
TickJob
Posts: 4
Joined: Wed Jul 15, 2015 10:01 pm

Oanda REST API scripts

Post by TickJob »

Thanks mcbusrider.

I have just installed Anaconda on my Windows XP, and also start reading up py programming. Your working script of open order and closing order is great starting point for me to learn. Hopefully I can just load and run and see how it work, and then try to change bit by bit to learn.
py1.jpg
You do not have the required permissions to view the files attached to this post.
TickJob
Posts: 4
Joined: Wed Jul 15, 2015 10:01 pm

Oanda REST API scripts

Post by TickJob »

actually I am playing with the fxtrade manually to submit a series of buy and sell as shown in the picture below. quite tediou and tired doing manually.
oa1.jpg
You do not have the required permissions to view the files attached to this post.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

'placePendingOrders.py' Script

Can't sleep - dogs are keeping me up :arrrg:

I'm new to all this programming lark, too! It seems like a long, drawn-out, painful process, but completely worth the journey, when you get something to work.

Hopefully, this should help you with setting the pending orders. This is the script I use, with comments added. It SHOULD work - no guarantees with anything, as I don't have the requisite skillset to troubleshoot more than basic issues at the moment.

Obviously, you'll need to replace all sensitive information with your own details...

The script contains a built-in balance checker function - this will only allow trading on accounts with an available balance of more than 25% NAV (change this if you like, it's in the "checkAvailBalance" function (line 80).

On Line 94, "NavFree=NAV/4" sets NavFree to one quarter of NAV, or 25% (NAV = Net Asset Value = what your account is worth if everything is closed down and all profits/losses are realised). To change this line to a more accurate percentage calculation, you could use "NavFree=NAV/100*25"

I use the "Buy Low...Sell High" principle with these, so I set all my buy orders lower than current market ask price, with all my sell orders higher than current market bid price. If you want to change this part of the code, have a mess around with the values in the "placeBuyOrder" (line 126) and "placeSellOrder" (line 204) functions.

So, here's the script. You need to save this with a ".py" extension for it to work.

Let me know how you get on!

placePendingOrders.py

Code: Select all

#!/usr/bin/python2.7
##  by mcbusrider 2015  
'''
The MIT License (MIT)
 
'placePendingOrders.py' Copyright (c) 2015 mcbusrider (Steve Hopwood Forex forum user)
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
'''

## placePendingOrders.py
import httplib, json
import sys
import json
import urllib
import time
import datetime
import oandapy

## Start of Buy Order section

#oanda = oandapy.API(environment="practice", access_token="hjdfhdhdfhfu45454754857494874jdhfdfdjfdkfjdfkjd")
#account_id = 1234567
oanda = oandapy.API(environment="live", access_token="djfhdfhdfhdjhdjhdjfdhf7485748574857485745difhdjfdjfhdjfh")
## the access_token is your own personal key to allow this script unlimited access to your accounts.  Use with caution on a live account!!!

currencyList = []
##currencyList variable is a list, which will contain the currency pairs you wish to trade
defaultSize = 1
##defaultSize variable will contain the default size of the order you wish to place - initially set at 1
size=defaultSize
##size variable is set to defaultSize.  This is probably poor coding on my part, but it works, and if it ain't broke...
lotSizeIncreaseThreshold=[3,16,42,81,133,198,276,367,471,588,718,861,1017,1186,1368,1563,1771,1992,2226,2473,2733,3006,3292,3591,3903,4228,4566,4917,5281,5658,6048,6451,6867,7296,7738,8193,8661,9142,9636,10143,10663,11196,11742,12301,12873,13458,14056,14667,15291,15928]
##lotSizeIncreaseThreshold variable is another list.  When the account balance is greater than the threshold, the trade size is set to increase in double units, like this: 1,2,4,6,8,10 etc.)
accountSize={}
##accountSize list will contain the size of trade for each account, based on the account balance being greater than the relevant lotSizeIncreaseThreshold
stagger=.0015
##stagger variable is the distance away from market price that you wish to place the first pending order.  Subsequent trades will be calculated at 'stagger' distance from the last trade, e.g. if stagger is set to .0015, orders will be placed 15 pips away/30 pips away/45 pips away etc. from market price.
offset=stagger
##offset variable is set to stagger.  Again, probably poor coding on my part, but it works, so it's staying like that <!-- s:-) --><img src=\"{SMILIES_PATH}/friendly.gif\" alt=\":-)\" title=\"smile\" /><!-- s:-) -->
account_id = 123456
##account_id variable is the account number you wish to set the orders on.
now = datetime.datetime.now()
##now is set to the current time
trade_expire = now + datetime.timedelta(minutes=1)
##the minimum expiry of a pending trade is one hour.  I set the timedelta to one minute, simply because it is the lowest denomination and when I was setting this to one hour, orders were staying open for two hours, for some reason.
trade_expire = trade_expire.isoformat("T") + "Z"
##trade_expire is the time the order is due to expire 
master_account_list= [123456, 789012, 345678, 901234]
##master_account_list contains all the account numbers on your account, if you want to use multiple accounts
account=0
##account is a counter, used for iterating through the master_account_list and account_list items
master_account_list_end=(len(master_account_list))
##master_account_list_end contains the position of the last account number stored in the master_account_list
account_list=[]
##sets account_list to an empty list
allowTrade=False
##allowTrade boolean - if this is set to true, the current account can trade
account_list_end=(len(account_list))
##account_list_end contains the position of the last account number stored in the account_list.  
##The account_list is generated from the master_account_list during the checkAvailBalance function.
##this function will only allow trades from accounts with more than a specified free margin to use (default is 25% of NAV)
##on a successful check, the account_list will be appended with the account number from the master_account_list, otherwise the next account is checked.
def checkAvailBalance(account, account_id, allowTrade):
	response = oanda.get_account(account_id)
	print "Account Info: "+str(response)
	balance = response.get("balance")
	UPL = response.get("unrealizedPl")
	usedMargin = response.get("marginUsed")
	freeMargin = response.get("marginAvail")
	NAV = usedMargin+freeMargin

	print "balance: "+str(balance)	
	print "Unrealized Profit Loss(UPL): "+str(UPL)
	print "usedMargin: "+str(usedMargin)
	print "freeMargin: "+str(freeMargin)
	print "NAV: "+str(NAV)
	NAVfree=NAV/4
	##this check stops trading on this account if available balance is less than 25% of NAV
	print "%free% of NAV: "+str(NAVfree)
	if freeMargin<NAVfree:#if less than 25% available margin, no trade
		allowTrade=False
		print "freeMargin < 25% of NAV, so allowTrade==False"
		return
	else:
		allowTrade=True
		print "freeMargin > 25% of NAV, so allowTrade==True"
		print "adding this account to account_list..."	
		account_list.append(account_id)
		accountSize[account_id]=defaultSize
		print "accountSize dictionary: "+str(accountSize.keys())
		x=1
		while balance>lotSizeIncreaseThreshold[x]:
		##this checks the balance of the account to see what size trade we are allowing
		##if the balance is greater than the amount in lotSizeIncreaseThreshold...
			accountSize[account_id]=(x*2)
			##the accountSize for this account should be set to the position in the list, multiplied by two
			x=x+1
			##check the next one in the list
			if balance<lotSizeIncreaseThreshold[1]:
			##if the balance is lower than the second balance in the list...I know, I know...but it works!
				accountSize[account_id]=1
				##accountSize for this account is set to 1
		print "accountSize dict: "	
		for key, value in accountSize.iteritems():
			print key, value
			##prints a list of accounts we are allowed to trade on, with the size of the trade for each account
	return

def placeBuyOrder(account_id, pair, size, offset):
	response = oanda.get_prices(instruments=pair)
	prices = response.get("prices")	
	asking_price = prices[0].get("bid")+offset
	##asking_price is set to bid price + offset in pips
	TP = asking_price
	##TakeProfit is calculated by using the same offset - e.g., order is placed 15 pips away, with a 15 pip TP
        time.sleep(.25)
	##this causes a quarter of a second delay in an attempt to stop the "too many connections" error from the Oanda server, which crashes the script.  You may need to move this up a bit if you get this error, but it seems to work ok for me on this setting.
	loop=1
	while loop<6:
	##loop contains the number of pending orders you wish to set, minus one
		response = oanda.create_order(account_id, 
    		instrument=pair,
   		units=size,
   		side='buy',
    		type='limit',
    		price=asking_price,
    		takeProfit=TP+offset,
    		expiry=trade_expire
		)	
		TP=TP-offset
		asking_price=asking_price-offset			
		loop=loop+1	
	return
	
def createAccountList(master_account_list,account_list,allowTrade):	
	count=0	
	while count < master_account_list_end:
		account_id=master_account_list[count]
		checkAvailBalance(count,account_id,allowTrade)
		count=count+1	
	return

createAccountList(master_account_list,account_list,allowTrade)
##make the account_list from the master_account_list, checking if we are currently allowing trades on each account	
account_list_end=(len(account_list))
print "master_account_list: "+str(master_account_list)
print "length of master account list: "+str(len(master_account_list))
print "account_list: "+str(account_list)
print "length of account list: "+str(len(account_list))
print "account: "+str(account)
##gives info on which accounts are tradeable
while account < account_list_end:
	##loop through all accounts
	account_id=account_list[account]
	##account_id is set to "account" numbered item of the account_list
	size=accountSize[account_id]
	##size is set to the account size for this account
	account=account+1
	##increase this now, before I forget to put it in there...
	if account_id==123456:
		currencyList = ["EUR_JPY","EUR_GBP","GBP_CHF","GBP_JPY","NZD_JPY","GBP_JPY"]
	elif account_id==789012:	
		currencyList = ["GBP_USD","EUR_GBP","GBP_USD","USD_CAD","EUR_JPY","GBP_AUD","AUD_CAD","EUR_CHF"]
	elif account_id==345678:
		currencyList = ["GBP_JPY","EUR_CHF","EUR_AUD","AUD_JPY","GBP_JPY","GBP_CAD"]
	elif account_id==901234:
		currencyList = ["CAD_CHF","AUD_CAD","EUR_AUD","AUD_JPY","GBP_CAD","EUR_GBP","EUR_USD","USD_CAD","EUR_NZD","NZD_JPY"]
	##currencyList contains the pairs you wish to trade on the buy side of things
				
	for pair in currencyList:
		offset=stagger
		##sets the default offset to the stagger variable, which is constant throughout the script
		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":
			offset=offset*100
			##this sets the offset to compensate for the pip value on instruments with fewer digits.  If you get a ridiculous number of pending trades around the same price, check how many digits are in the pair's price and change accordingly.
		placeBuyOrder(account_id, pair, size, offset)

## Start of Sell Order section
##this is pretty much similar to the buy section, but for sell trades, obviously...
account_id = 123456
now = datetime.datetime.now()
trade_expire = now + datetime.timedelta(minutes=1)
trade_expire = trade_expire.isoformat("T") + "Z"
account=0
account_list_end=(len(account_list))

def placeSellOrder(account_id, pair, size, offset):
	response = oanda.get_prices(instruments=pair)
	prices = response.get("prices")	
	asking_price = prices[0].get("bid")+offset
	TP = asking_price
        time.sleep(.25)
	loop=1
	while loop<3:	
			response = oanda.create_order(account_id, 
    			instrument=pair,
   			units=size,
   		 	side='sell',
    			type="limit",
    			price=asking_price,
    			takeProfit=TP-offset,
    			expiry=trade_expire
			)
			TP=TP+offset
			asking_price=asking_price+offset
			loop=loop+1	
	return

while account < account_list_end:
	account_id=account_list[account]
	size=accountSize[account_id]
	account=account+1
	if account_id==123456:
		currencyList = ["EUR_USD","USD_JPY","EUR_CHF","GBP_USD","USD_JPY","NZD_USD","USD_JPY","GBP_CAD","CAD_JPY"]
	elif account_id==789012:	
		currencyList = ["EUR_USD","GBP_CAD","USD_JPY","EUR_USD","GBP_CAD","USD_CHF","EUR_USD"]
	elif account_id==345678:	
		currencyList = ["GBP_CHF","CHF_JPY","EUR_USD","USD_CHF","EUR_JPY","GBP_NZD","NZD_JPY","NZD_CAD","GBP_NZD"]
	elif account_id==901234:
		currencyList = ["EUR_CAD","EUR_JPY","EUR_JPY","EUR_CAD","AUD_CHF"]
			
	for pair in currencyList:
			offset=stagger
			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":
				offset=offset*100

			placeSellOrder(account_id, pair, size, offset)
	
Last edited by mcbusrider on Fri Jul 24, 2015 4:07 am, edited 8 times in total.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

actually I am playing with the fxtrade manually to submit a series of buy and sell as shown in the picture below. quite tediou and tired doing manually.
I like fxTrade on the iPhone and I was using it extensively until I found out about the REST API, which is great, once you get the hang of it. Setting the pending trades is a lot easier with a script :yahoo:

I had to put the balance checker in the script as I trusted it too early and had a closeout on one of my accounts. I'd really advise you, if you're putting this on a live account, to only use 1 unit lot size until you get the hang of it.

If you don't want to run the script on an automated scheduler, try putting a "while: true" loop around the code, which will keep it running indefinitely, with a "time.sleep(3600)" command in there at the end of the code, which will delay for 3600 seconds (example), or one hour. Then the script will just loop again and start from the top of the script.

However, I've noticed that sometimes the API overloads with an error of "too many connections" and throws you out of the script. I much prefer running it on Crontab, as if it breaks out of the script due to an error, it just starts again at the allotted time.

If you're looking for a replacement for XP, I'd recommend Lubuntu. It's a bit of a learning curve, but has better functionality than XP and seems more stable for this kind of thing IMO. Also, Python is installed as standard.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

If you want to run scripts all the time, a VPS is the way to go - it will run all the time.

I have a Windows Server 2008 VPS with InterServer. No problems at all with them, their customer service is impeccable and they're cheap and good - a rare combination nowadays.

On the Windows Server, I run Virtualbox with an instance of Lubuntu. Virtualbox is a virtualisation software, which allows you to run an operating system inside an operating system...potentially creating a scenario of Matryoshka doll-contained operating systems, only limited by memory resources, graphic card rendering capability and hard drive space...but I digress...

I can access my VPS through Remote Desktop Protocol (RDP) on my laptop or smartphone, so any maintenance or script changes I want to make can be done from either device.

If you're having issues syncing time, I use Dimension 4, which is a freeware utility that runs in the background and syncs your internal computer's clock with an internet time server. The good folks at InterServer put me on to that one.

I use a Dropbox account to store my scripts, with access from my laptop, my phone, the VPS and Lubuntu. One change on the script updates all instances of the script, so I can work offline from the server and not need to keep on logging into the VPS every time I want to make a change.

For editing scripts on the iPhone, I recommend the "CodeAnywhere" app.

I noticed that sometimes, the script executable permissions change after an edit and it won't run, so if the script stops working after an edit, you may need to alter the permissions of it (right-click/properties/permissions and make sure the script is set to execute/edit by all users).
Last edited by mcbusrider on Thu Jul 23, 2015 1:28 am, edited 2 times in total.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

Oh, one more thing, before I murder these dogs...

Python works on block spacing: you have to have correct block spacing in lines of code. For example:

Code: Select all

if a<b:
      c=d
else:
      e=f
will work.

This:

Code: Select all

if a<b:
c=d
else:
e=f
will not.

If the scripts don't work, try moving the comments across so they are in line with the next line of code, or taking them out completely. It was working before I put the comments in, but I haven't tested it since.
mcbusrider
Trader
Posts: 23
Joined: Sun Mar 15, 2015 4:37 pm

Oanda REST API scripts

Post by mcbusrider »

check total profit reaching profit target then close all orders
this will mean making a slight amendment to closeAllProfitableTrades.py

the logic for this check is:

Code: Select all

set TargetProfit in pips
set GrandTotalProfit = 0 ## this is a running total of profit, in pips 

  set a loop to iterate through all open trades
  select trade (using loop number)
  get instrument of current trade
  get ask and bid price of current trade
  get type (buy or sell) of current trade
  get open price of current trade
  calculate profit of current trade, using open price of current trade versus (buy or ask price) of instrument.
  check if instrument of current trade is on the "3 digit pip" list - if so, divide profit by 100 to give standard value of profit in pips across all trades.
  add profit in pips to GrandTotalProfit (even if this is a negative amount, addition will still apply)
  loop through next trade and repeat


when profit (or loss) of all open trades has been added to GrandProfitTotal:
           if GrandTotalProfit>TargetProfit:
                  loop through all trades again
                  close this trade
                  next trade
          else:
                  do not close all trades

Bear in mind the above code is not valid Python, it's just the process.


Most of this code is already in the script, it just needs a tweak here and there.

Have a go at doing this, TickJob, see how you get on - that's the best way to learn.

If you get stuck, gimme a shout!

Best of luck,

Nige
Last edited by mcbusrider on Fri Jul 24, 2015 3:52 am, edited 1 time in total.
Post Reply

Return to “Alternative platforms”