JForex Example: Not letting profit turn to losses with a breakeven stop

While the dual-timeframe trading setup and much of the algorithm in my contest strategy are for competition only (read: not for use with real money) as I’ve warned numerous times, some of the risk management techniques used there are really what I use in real life. This being one of them.

There’s a saying in trading that “never let profits turns into losses.” That is exactly the motivation behind this JForex code snippet. The following source code are excerpts from my Dukascopy JForex contest’s July strategy. The complete source code file is available in that link.

Back to this concept of not letting profits turn to losses. This is a matter of balancing between giving room for your trade to reach its potential and limiting your drawdown. If you’re too careful, you may find yourself being whipsawed out before a price move can materialize. If you keep your leash too loose though, well, you may watch your profits turn into losses.

The way I intrepret the saying is that once your trade is profitable enough, you shouldn’t let it slip back into a loss.

I implement the above statement in my automated strategy as follows. Note that everything goes in the onTick() method so that it watches your position on every tick. The line numbers correspond to the complete source code of my automated strategy.

		boolean isLong;
		double open, stop, diff, newStop;

		for (IOrder order : engine.getOrders(instrument)) {
			if (order.getState() == IOrder.State.FILLED) {
				isLong = order.isLong();
				open = order.getOpenPrice();
				stop = order.getStopLossPrice();
				diff = (open - stop);

				// ********* BREAKEVEN ***********************
				if (isLong && diff > 0 && tick.getBid() > (open + diff))
				{
					order.close(roundLot(order.getAmount() * beRatio));	// close a portion

					newStop = open + instrument.getPipValue() * LOCKPIP;
					order.setStopLossPrice(newStop);
               print(order.getLabel() + ": Moved STOP to breakeven");
				}
				else if (!isLong && diff < 0 && tick.getAsk() < (open + diff))
				{
					order.close(roundLot(order.getAmount() * beRatio));

					newStop = open - (instrument.getPipValue() * LOCKPIP);
					order.setStopLossPrice(newStop);
					print(order.getLabel() + ": Moved STOP to breakeven");
				}

What this does is that it will partially exit a position and move the stop to breakeven once the price is equidistantly positive from your initial stop loss. For example, if my stop loss is 100 pips, then once the position is 100 pips in profit, it will exit partially and set the new stop to breakeven.

Update: This is now integrated into the JFUtil open source project.

read more

JForex Example: Multiple-time frame strategy

The key to my July JForex strategy is the use of multiple time frames. As Dr. Alexander Elder demonstrates in his famous book, Trading For A Living, a proper technical analysis should at least consider time frames five-times faster and slower than the one in which you trade.

For example, if you trade on a 30 minute chart, the one faster is 30/5 = 6 minutes, which can be rounded as the five-minute chart. And the one slower would be 30 * 5 = 150 minutes. The closest standard time frame of which is a 4-hour chart.

For my July JForex strategy, it trades on the 30 minute chart and monitor the 4-hour chart in addition to the 30-minute chart. The strategy doesn’t make use of a faster time frame for simplicity.

This is surprisingly easy to do in Dukascopy‘s JForex API. Referring to lines 81 to 87 of my strategy source code.

		if (period == PERIODINT)
		{
			setSentiment(instrument, bidBar, askBar);
			return;
		}

		if (period != PERIODSHR)	return;		// skip all other periods

This chunk of code appears in the onBar() method. Since onBar() is called at the beginning of every price bar across all possible standard periods (from tick to weekly), it’s just a matter of filtering out the redundant periods and/or catching the method when the period is correct.

I have done both in the sample code.

Line 81 is to catch the longer period, PERIODINT = Period.FOUR_HOURS (line 54, not shown), in an IF statement block. It calls my function setSentiment() and exits onBar() with the ‘return’, skipping everything in onBar() afterward.

Line 87 is to skip all other periods that I’m not using. I could have used if (period == PERIODSHR) and put everything in an IF block as in lines 81-85. But since the strategy is doing a lot more work in PERIODSHR, there would be a lot of codes in that IF block. So I am doing the reverse for the same result but simpler-looking codes.

With this cleared, I can go over my dual moving average entry signal setup in the next post later this week.

read more

JForex StopManager 1.0

I am building my real JForex automated trading system one feature at a time. The idea is to automate some of my most fundamental trading techniques on JForex so that I can trade forex semi-automatically on Dukascopy.

I am starting off here with a simple stop management strategy. In a nutshell, once the market price moves in your favour equidistant from your original stop loss, this strategy moves the stop to breakeven.

For example, if I go long EURUSD at 1.3500 with a stop at 1.3400 (100 pips stop). Then if the price breaks above 1.3600 (100 pips profit), the strategy moves the stop to breakeven.

This is a simplistic implementation of the saying that “never let profits turn into losses”.

You can download the source code here and the executable strategy here. Note that these files are made available through Dropbox.

Update: This logic is now integrated into the JFUtil open source project. You can also see a list of my latest JForex articles here.

/*

	StopManager.java
	version 1.0
	Copyright 2010 Quantisan.com

	Move stops to breakeven when equidistance to original stop loss

*/

package jforex;

import com.dukascopy.api.*;

public class StopManager implements IStrategy {
	private IEngine engine;
	private IConsole console;
	private IContext context;

	@Configurable("Lock-in Pips for Breakeven")
	public int lockPip = 3;

	@Configurable("Move stop to breakeven?")
	public boolean moveBE = true;

	public void onStart(IContext context) throws JFException {
		this.engine = context.getEngine();
		this.console = context.getConsole();
		this.context = context;
	}

	public void onAccount(IAccount account) throws JFException {
	}

	public void onMessage(IMessage message) throws JFException {
	}

	public void onStop() throws JFException {
	}

	public void onTick(Instrument instrument, ITick tick) throws JFException {
		for (IOrder order : engine.getOrders(instrument)) {
			if (order.getState() == IOrder.State.FILLED) {
				boolean isLong;
				double open, stop, diff, newStop;
				String label = order.getLabel();
				IChart chart;

				isLong = order.isLong();
				open = order.getOpenPrice();
				stop = order.getStopLossPrice();
				diff = open - stop;		// stop loss distance

				if (isLong) {			// long side order
					if (moveBE && diff > 0 && tick.getBid() > (open + diff)) {
						// make it breakeven trade + lock in a few pips
						newStop = open + instrument.getPipValue() * lockPip;
						order.setStopLossPrice(newStop);
                        console.getOut().println(label + ": Moved stop to breakeven");

						chart = this.context.getChart(instrument);
						chart.draw(label + "_BE", IChart.Type.SIGNAL_UP, tick.getTime(), newStop);
					}
				}
				else {					// short side order
					// Move to breakeven
					if (moveBE && diff < 0 && tick.getAsk() < (open + diff)) {	// diff is negative
						// make it breakeven trade + lock in a few pips
                        newStop = open - (instrument.getPipValue() * lockPip);
						order.setStopLossPrice(newStop);
                        console.getOut().println(label + ": Moved stop to breakeven");

						chart = this.context.getChart(instrument);
						chart.draw(label + "_BE", IChart.Type.SIGNAL_DOWN, tick.getTime(), newStop);
					}
				}
            }
        }
	}

    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
    }
}
read more

Data Scraping the Toronto Stock Exchange: Extracting 3,660 companies’ data

One of the tasks that I’ve always wanted to make more efficient in my stock trading is the work of scanning for stocks to trade. One look at my trading strategy posts and you’ll see that I have devised many stock scanning systems in the past few years. The most recent system that I’ve used is one that uses options data to filter stocks. However, it is not automated. So it takes a lot of time to gather and analyze the data. Furthermore, the set of tools that I use is limited to U.S. stocks. Now that I have taken an interest in the Canadian stock market, I can’t seem to find any public tool that I like. Thus, I am biting the bullet now and taking my time to develop a custom system once and for all.

Before we can analyze stock data, we need to extract them first. Where better else for that than go straight to the source at TMX.com, the parent company of Toronto Stock Exchange (TSX) and TSX Venture Exchange (TSXV). TMX.com provide a list of publicly traded companies in ten Excel files. The files are divided by sectors. Each contain a number of fundamental company data, such as market capitalization and outstanding shares. So step 1 is to extract those data.

This is where I am at now. I attached the source code for an alpha/developmental release below for anyone interested. It is a working program to scrape the data from TMX.com’s files. But it’s still a work-in-progress. That’s why I am calling it a version 0.1.

The next milestone is to program a Stocks class to hold, organize, and manage all three thousand, six hundred, and sixty companies’ data. This is an easy task to do by extending the built-in dictionary class in Python. However, I haven’t gotten to that chapter yet in my scientific programming with Python learning book. I stopped at chapter 8 to work on this project. Chapter 9 is the inheritence and hierarchical material.

The goal of this project is to build an automated data scraping program for TSX and TSXV data from various sources into my computer. Once I have my data, that’s when the real fun starts.

Regarding the code below, I know that source code is useless for most people. Once the project is complete, I will compile the code into a standalone application and post it on this site. Subscribe to my RSS feed so that you can keep up-to-date with the progress of this project and my other ramblings on trading.

# extractTMX.py
# version: 0.1 alpha release
# revision date: March, 2010
# by Paul, Quantisan.com

"""A data scraping module to extract company listing excel files from TMX.COM"""

import xlrd									# to read Excel file
#import sys
from finClasses import Stock				# custom Stock class

def _verify():
	"""Verification function for a rundown of the module"""
	pass									# copy test block here when finished

def findCol(sheet, key):
	"""Find the column corresponding to header string 'key'"""
	firstRow = sheet.row_values(0)
	for col in range(len(firstRow)):
		if key in firstRow[col]: return col		# return first sighting
	else:										# not found
		raise ValueError("%s is not found!" % key)

def scrapeXLS(book):
	"""Data scraping function for TMX Excel file"""

	listingDict = {}						# dict of ('ticker': market cap)

	for index in range(book.nsheets):
		sh = book.sheet_by_index(index)

		mcCol = findCol(sh, "Market Value")
		assert type(mcCol) is int, "mcCol is a %s" % type(mcCol)
		osCol = findCol(sh, "O/S Shares")
		assert type(osCol) is int, "osCol is a %s" % type(osCol)
		secCol = findCol(sh, "Sector")		# multiple matches but taking first
		assert type(secCol) is int, "secCol is a %s" % type(secCol)
		hqCol = findCol(sh, "HQ\nRegion")
		assert type(hqCol) is int, "hqCol is a %s" % type(hqCol)

		for rx in range(1, sh.nrows):
			sym = str(sh.cell_value(rowx=rx, colx=4))		# symbol

			s = sh.cell_value(rowx=rx, colx=2)	# exchange col.
			if s == "TSX": exch = "T"
			elif s == "TSXV": exch = "V"
			else: raise TypeError("Unknown exchange value")

			mc = sh.cell_value(rowx=rx, colx=mcCol)		# market cap
			# check for empty market cap cell
			mc = int(mc) if type(mc) is float else 0

			os = int(sh.cell_value(rowx=rx, colx=osCol))	# O/S shares
			sec = str(sh.cell_value(rowx=rx, colx=secCol))	# sector
			hq = str(sh.cell_value(rowx=rx, colx=hqCol))	# HQ region

			listingDict[sym] = Stock(symbol=sym,exchange=exch,
				mktCap=mc,osShares=os, sector=sec,hqRegion=hq)
	return listingDict

def fetchFiles(fname):
	infile = open(fname, 'r')				# text file of XLS file names
	listing = {}
	for line in infile:						# 1 file name per line
		if line[0] == '#': continue			# skip commented lines

		line = line.strip()					# strip trailing \n
		print "Reading '%s' ..." % line

		xlsFile = "TMX/" + line				# in TMX directory
		book = xlrd.open_workbook(xlsFile)	# import Excel file
		listing.update(scrapeXLS(book))		# append scraped the data to dict
	return listing

#if __name__ == '__main__':					# verify block
#	if len(sys.argv) == 2 and sys.argv[1] == 'verify':
#		_verify()

if __name__ == '__main__':					# test block
	listing = fetchFiles('TMX/TMXfiles.txt')
read more