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 :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'