<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Zorro &#8211; The Financial Hacker</title>
	<atom:link href="https://financial-hacker.com/tag/zorro/feed/" rel="self" type="application/rss+xml" />
	<link>https://financial-hacker.com</link>
	<description>A new view on algorithmic trading</description>
	<lastBuildDate>Mon, 16 Feb 2026 16:53:44 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://financial-hacker.com/wp-content/uploads/2017/07/cropped-mask-32x32.jpg</url>
	<title>Zorro &#8211; The Financial Hacker</title>
	<link>https://financial-hacker.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Build Better Strategies, Part 6: Evaluation</title>
		<link>https://financial-hacker.com/build-better-strategies-part-6-evaluation/</link>
					<comments>https://financial-hacker.com/build-better-strategies-part-6-evaluation/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Thu, 05 Feb 2026 16:54:41 +0000</pubDate>
				<category><![CDATA[No Math]]></category>
		<category><![CDATA[System Development]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Experiment]]></category>
		<category><![CDATA[Indicator]]></category>
		<category><![CDATA[Walk forward analysis]]></category>
		<category><![CDATA[White's reality check]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4901</guid>

					<description><![CDATA[Developing a successful strategy is a process with many steps, described in the Build Better Strategies article series. At some point you have coded a first, raw version of the strategy. At that stage you&#8217;re usually experimenting with different functions for market detection or trade signals. The problem: How can you determine which indicator, filter, &#8230; <a href="https://financial-hacker.com/build-better-strategies-part-6-evaluation/" class="more-link">Continue reading<span class="screen-reader-text"> "Build Better Strategies, Part 6: Evaluation"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Developing a successful strategy is a process with many steps, described in the <a href="https://financial-hacker.com/build-better-strategies/">Build Better Strategies</a> article series. At some point you have coded a first, raw version of the strategy. At that stage you&#8217;re usually experimenting with different functions for market detection or trade signals. The problem: How can you determine which indicator, filter, or machine learning method  works best with which markets and which time frames? Manually testing all combinations is very time consuming, close to impossible. Here&#8217;s a way to run that process automated with a single mouse click.<span id="more-4901"></span></p>
<p>A robust trading strategy has to meet several criteria:</p>
<ul>
<li>It must exploit a real and significant market inefficiency. Random-walk markets cannot be algo traded.</li>
<li>It must work in all market situations. A trend follower must survive a mean reverting regime.</li>
<li>It must work under many different optimization settings and parameter ranges.</li>
<li>It must be unaffected by random events and price fluctuations.</li>
</ul>
<p>There are metrics and algorithms to test all this. The robustness under different market situations can be determined through the <strong>R2 coefficient</strong> or the deviations between the <strong>walk forward cycles</strong>. The parameter range robustness can be tested with a WFO profile (aka <strong>cluster analysis</strong>), the price fluctuation robustness with <strong><a href="https://financial-hacker.com/better-tests-with-oversampling/">oversampling</a></strong>. A <strong>Montecarlo analysis</strong> finds out whether the strategy is based on a real market inefficiency.</p>
<p>Some platforms, such as <strong>Zorro</strong>, have functions for all this. But they require dedicated code in the strategy, often more than for the algorithm itself. In this article I&#8217;m going to describe an <strong>evaluation framework</strong> &#8211; a &#8216;shell&#8217; &#8211; that skips the coding part. The evaluation shell is included in the latest Zorro version. It can be simply attached to any strategy script. It makes all strategy variables accessible in a panel and adds stuff that&#8217;s common to all strategies &#8211; optimization, money management, support for multiple assets and algos, cluster and montecarlo analysis. It evaluates all strategy variants in an automated process and builds the optimal portfolio of combinations from different algorithms, assets, and timeframes. </p>
<p>The process involves these steps: </p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2026/02/eval.png" alt="" /></p>
<p>The first step of strategy evaluation is generating sets of parameter settings, named <strong><span class="tast">jobs</span></strong>. Any job is a variant of the strategy that you want to test and possibly include in the final portfolio. Parameters can be switches that select between different indicators, or variables (such as timeframes) with optimization ranges. All parameters can be edited in the user interface of the shell, then saved with a mouse click as a job. </p>
<p>The next step is an automated process that runs through all previously stored jobs, trains and tests any of them with different asset, algo, and time frame combinations, and stores their results in a <strong><span class="tast">summary</span></strong>. The summary is a CSV list with the performance metrics of all jobs. It is automatically sorted &#8211; the best performing job variants are at the top &#8211; and looks like this:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2026/02/shellsummary.png" alt="" /></p>
<p>So you can see at a glance which parameter combinations work with which assets and time frames, and which are not worth to examine further. You can repeat this step with different global settings, such as bar period or optimization method, and generate multiple summaries in this way. </p>
<p>The next step in the process is <strong><span class="tast">cluster analysis</span></strong>. Every job in a selected summary is optimized multiple times with different walk-forward settings. The result with any job variant is stored in WFO profiles or heatmaps:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2026/02/RangerMatrix.png" alt="" /></p>
<p>After this process, you likely ended up with a couple survivors in the top of the summary. The surviving jobs have all a positive return, a steady rising equity curve, shallow drawdowns, and robust parameter ranges since they passed the cluster analysis. But any selection process generates <strong><span class="tast">selection bias</span></strong>. Your perfect portfolio will likely produce a great backtest, but will it perform equally well in live trading? To find out, you run a <span class="tast"><strong>Montecarlo analysis</strong>, aka &#8216;Reality Check&#8217;</span>.</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2026/02/RealityCheck_s1.png" alt="" /></p>
<p>This is the most important test of all, since it can determine whether your strategy exploits a real market inefficiency. If the Montecarlo analysis fails with the final portfolio, it will likely also fail with any other parameter combination, so you need to run it only close to the end. If your system passes Montecarlo with a <strong><span class="tast">p-value</span></strong> below 5%, you can be relatively confident that the system will return good and steady profit in live trading. Otherwise, back to the drawing board.</p>
<h3>The use case</h3>
<p>For a real life use case,  we generated algorithms for the Z12 system that comes with Zorro. Z12 is a portfolio from several trend and counter trend algorithms that all trade simultaneously. The trading signals are generated with spectral analysis filters. The system trades a subset of Forex pairs and index CFDs on a 4-hour timeframe. The timeframe was choosen for best performance, as were the traded Forex pairs and CFDs. </p>
<p>We used the evaluation shell to create new algos, not from a selected subset, but from all major Forex pairs and major index CFDs, with 3 different time frames from 60, 120, and 240 minutes. 29 algorithms passed the cluster and montecarlo analysis, of which the least correlated were put into the final portfolio. This is the equity curve of the new Z12 system:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2026/02/z12perf.png" alt="" /></p>
<p>Other performance parameters, such as Profit Factor, Sharpe ratio, Calmar Ratio, and R2 also improved by more than 30%. The annual return almost doubled, compared with the average of the previous years. Nothing in the basic Z12 algorithms has changed. Only new combinations of algos, assets, and timeframes are now traded.</p>
<p>The evaluation shell is included in Zorro version 3.01 or above. Usage and details are described under <a href="https://zorro-project.com/manual/en/shell.htm" target="_blank" rel="noopener">https://zorro-project.com/manual/en/shell.htm</a>.  Attaching the shell to a strategy is described under <a href="https://zorro-project.com/manual/en/shell2.htm" target="_blank" rel="noopener">https://zorro-project.com/manual/en/shell2.htm</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/build-better-strategies-part-6-evaluation/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Pimp your performance with key figures</title>
		<link>https://financial-hacker.com/pimp-your-performance-with-key-figures/</link>
					<comments>https://financial-hacker.com/pimp-your-performance-with-key-figures/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Wed, 08 Jan 2025 13:34:40 +0000</pubDate>
				<category><![CDATA[No Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Money]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4782</guid>

					<description><![CDATA[Not all scripts we’re hired to write are trading strategies. Some are for data analysis or event prediction – for instance: Write me a script that calculates the likeliness of a stock market crash tomorrow. Some time ago a client ordered a script for improving the performance of their company. This remarkable script was very &#8230; <a href="https://financial-hacker.com/pimp-your-performance-with-key-figures/" class="more-link">Continue reading<span class="screen-reader-text"> "Pimp your performance with key figures"</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Not all scripts we’re hired to write are trading strategies. Some are for data analysis or event prediction – for instance: <em>Write me a script that calculates the likeliness of a stock market crash tomorrow</em>. Some time ago a client ordered a script for improving the performance of their company. This remarkable script was very different to a trading system. Its algorithm can in fact improve companies, but also your personal performance. How does this work?<span id="more-4782"></span></p>



<p>Just like the performance of a stock, the performance of a company is measured by numerical indicators. They are named <strong>key figures</strong>. Key figures play a major role in quality management, such as the <strong>ISO 9000</strong> standards. An ISO 9000 key figure is a detail indicator, such as the number of faults in a production line, the number of bugs found in a beta test, the number of new clients acquired per day, the total of positive minus negative online reviews, an so on. Aside from being essential for an ISO 9000 certification, these key figures have two purposes:</p>


<ul class="wp-block-list">
	<li>They give <strong>detailed insight</strong> and expose strengths and weaknesses.</li>


	<li>And they give a <strong>strong motivation</strong> for reaching a certain goal.</li>
</ul>


<p>The script below opens a user interface for entering various sorts of key figures. It calculates an <strong>overall score</strong> that reflects the current performance of a company &#8211; or of a person &#8211; and displays it in a chart. If you use it not for a company, but for yourself, it helps improving your personal life. And from the short script you can see how to create a relatively complex software with relatively few lines of code.</p>


<p>Hackers like the concept of key figures. They are plain numbers that you can work with. Anyone can define key figures for herself. If you’re a writer, an important key figure is the number of words you&#8217;ve written today; if you&#8217;re an alcolohic, it&#8217;s the number of drinks you had today. Many self-improvement books tell you precisely what you need to do for living a healthier, wealthier, happier life &#8211; but they all suffer from the same problem: <strong>long-term motivation</strong>. If you lack the iron will to keep your daily exercises, reduce smoking, stay away from fast food, and so on &#8211; all good resolutions will eventually fall into oblivion. If you had <strong>resolutions for 2025</strong>, you&#8217;ll soon know what I mean.</p>


<p>Failure is less likely when you can observe your progress any day and see its immediately effect on your overall performance score. This score is a direct measure of your success in live. Whether you’re a company or a person, you want to keep this core rising. This feedback produces a strong motivation, every day again.</p>


<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="701" height="405" class="wp-image-4783" src="https://financial-hacker.com/wp-content/uploads/2025/01/word-image-4782-1.png" alt="" srcset="https://financial-hacker.com/wp-content/uploads/2025/01/word-image-4782-1.png 701w, https://financial-hacker.com/wp-content/uploads/2025/01/word-image-4782-1-300x173.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></figure>



<p><br />
The above performance chart is plotted by the key figure management script in C for the Zorro platform. The red line is the overall score, derived from all key figures in a way explained below. The blue line is the key figure for which you just entered a new value (in the example it&#8217;s the number of large or small features implemented in the last 6 months in the Zorro platform). The X axis is the date in YYMMDD format.</p>


<p>Of course, key figures can be very different. Some may have a daily goal, some not, some shall sum up over time, others (like your bank account value) are just taken as they are. The idea is that your overall score rises when you exceed the daily goals, and goes down otherwise. All key figures and their parameters can be freely defined in a CSV file, which can be edited with a text editor or with Excel. It looks like this:</p>


<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p><code>Name, Decimals, Unit, Offset, Growth, Sum<br />
Appr,1,0.1,0,0,0<br />
Praise,0,10,0,-30,1<br />
Weight,1,-0.1,-250,0.033,0<br />
Duck,1,0.5,0,-0.5,1<br />
Worth,0,1,-6000,0,0</code></p>
</div></div>
</div></div>


<p>In the first column you can assign a name. The second column is the number of decimals in the display, the third is their unit in the overall score, the fourth is an offset in the score, the fifth is the daily goal, and the last tells if the figures shall sum up over time (1) or not (0).</p>


<p>Example. Suppose you’re a president of a large country and want to pimp up your personal performance. What’s your key figures? First, of course, approval rate. Any tenth percent adds one point to your score. So the first entry is simple:</p>


<p><code>Name, Decimals, Unit, Offset, Growth, Sum </code><br />
<code>Appr, 1, 0.1, 0, 0, 0</code></p>


<p>Next, fame. Key figure is the daily number of praises on Fox News, OneAmerica, and Newsmax. You’ve ordered a White House department to count the praises; of course you’re personally counting them too, just in case. Less than 30 praises per day would be bad and reduce your score, more will improve it. So 30 praises are daily subtracted from your score. Any 10 further praises add one point. This is an accumulative key figure:</p>


<p><code>Praise, 0, 10, 0, -30, 1</code></p>


<p>Next, health. Key figure is weight. Your enemies spread rumors that you&#8217;re unfit and obese. Your doctors urge you to shed weight. So you want to lose one pound every month, which (you have your mathematicians for calculating difficult things) is about 0.033 per day. Any lost 0.1 pound adds one point to your score. The numbers are negative since you want your weight to go down, not up. The offset is your current weight.</p>


<p><code>Weight, 1, -0.1, -250, 0.033, 0</code></p>


<p>Next, literacy. Your enemies spread rumors you&#8217;re illiterate. To prove them wrong, you&#8217;ve decided to read at least half a page per day in a real book (you’ve chosen <a href="https://www.amazon.de/-/en/Doreen-Cronin/dp/0689863772">Duck for President</a> to begin with). Any further half page adds one point to your score. This is also an accumulative figure.</p>


<p><code>Duck, 1, 0.5, 0, -0.5, 1</code></p>


<p>Finally, net worth. You’ve meanwhile learned to better avoid business attempts. Let your net worth grow due to the value increase of your inherited real estate, which is currently at 6 billion. Any million further growth adds one point to your score (numbers given in millions):</p>


<p><code>Worth, 0, 1, -6000, 0, 0</code></p>


<p>For improving your personal performance, download the script from the 2025 repository. Copy the files <strong>KeyFigures.csv</strong> and <strong>KeyFigures.c</strong> in your Strategy folder. Edit <strong>KeyFigures.csv</strong> for entering your personal key figures, as in the above example (you can later add or remove key figures and use Excel to add or remove the new columns to the data file). This is the script:</p>
<pre class="prettyprint">// Pimp Your Performance with Key Figures //////////////////////

string Rules = "Strategy\\KeyFigures.csv";
string Data = "Data\\KeyData.csv"; // key figures history
string Format = "0%d.%m.%Y,f1,f,f,f,f,f,f,f,f,f,f,f,f,f,f";
int Records,Fields;

var value(int Record,int Field,int Raw)
{
	var Units = dataVar(1,Field,2);
	var Offset = dataVar(1,Field,3);
	var Growth = dataVar(1,Field,4);
	var Value = 0;
	int i;
	for(i=0; i&lt;=Record; i++) {
		if(dataVar(2,i,Field+1) &lt; 0.) continue; // ignore negative entries
		Value += Growth;
		if(i == Record || (dataInt(1,Field,5)&amp;1)) // Sum up? 
			Value += dataVar(2,i,Field+1)+Offset;
	}
	if(Raw) return Value-Offset;
	else return Value/Units;
}

var score(int Record)
{
	int i,Score = 0;
	for(i=0; i&lt;Fields; i++) 
		Score += value(Record,i,0);
	panelSet(Record+1,Fields+1,sftoa(Score,0),YELLOW,16,4);
	return Score;
}


void click(int Row,int Col)
{
	dataSet(2,Row-1,Col,atof(panelGet(Row,Col)));
	score(Row-1);
	if(dataSaveCSV(2,Format,Data)) sound("Click.wav");
	int i;
	for(i=0; i&lt;Records; i++) {
		var X = ymd(dataVar(2,i,0)) - 20000000;
		plotBar("Score",i,X,score(i),LINE,RED);
		plotBar(dataStr(1,Col-1,0),i,NIL,value(i,Col-1,1),AXIS2,BLUE);
	}
	if(Records &gt;= 2) plotChart("");
}

void main()
{
	int i = 0, j = 0;
	printf("Today is %s",strdate("%A, %d.%m.%Y",NOW));
	ignore(62);
	PlotLabels = 5;
// File 1: Rules
	Fields = dataParse(1,"ssss,f1,f,f,f,i",Rules);
// File 2: Content
	Records = dataParse(2,Format,Data);
	int LastDate = dataVar(2,Records-1,0);
	int Today = wdate(NOW);
	if(LastDate &lt; Today) { // no file or add new line
		dataAppendRow(2,16);
		for(i=1; i&lt;=Fields; i++)
			if(!(dataInt(1,i-1,5)&amp;1))
				dataSet(2,Records,i,dataVar(2,Records-1,i));
		Records++;
	}
	dataSet(2,Records-1,0,(var)Today);

// display in panel
	panel(Records+1,Fields+2,GREY,-58);
	panelFix(1,0);
	print(TO_PANEL,"Key Figures");
	for(i=0; i&lt;Fields; i++)
		panelSet(0,i+1,dataStr(1,i,0),ColorPanel[0],16,1);
	panelSet(0,i+1,"Score",ColorPanel[0],16,1);
	panelSet(0,0,"Date",ColorPanel[0],16,1);
	for(j=0; j&lt;Records; j++) {
		panelSet(j+1,0,strdate("%d.%m.%y",dataVar(2,j,0)),ColorPanel[0],0,1);
		score(j);
		for(i=0; i&lt;Fields; i++) 
			panelSet(j+1,i+1,sftoa(dataVar(2,j,i+1),-dataVar(1,i,1)),ColorPanel[2],0,2);
	}
	panelSet(-1,0,"Rules",0,0,0);
}</pre>
<p>The file locations and the CSV format of the key figures history are defined at the begin. The <strong>value</strong> function calculates the contribution of a particular key figure to the overall score. The <strong>score</strong> function updates the overall score. The <strong>click</strong> function, which is called when you enter a new value, calculates the score of that day, updates the spreadsheet, and prints the chart. The <strong>main</strong> function imports the data and key figures from their CSV files into datasets, prints the current day and displays a spreadsheet of your key figures and score history, like this:</p>


<figure class="wp-block-image"><img decoding="async" width="484" height="163" class="wp-image-4784" src="https://financial-hacker.com/wp-content/uploads/2025/01/ein-bild-das-text-screenshot-schrift-zahl-enth.png" alt="Ein Bild, das Text, Screenshot, Schrift, Zahl enthält.

Automatisch generierte Beschreibung" srcset="https://financial-hacker.com/wp-content/uploads/2025/01/ein-bild-das-text-screenshot-schrift-zahl-enth.png 484w, https://financial-hacker.com/wp-content/uploads/2025/01/ein-bild-das-text-screenshot-schrift-zahl-enth-300x101.png 300w" sizes="(max-width: 484px) 85vw, 484px" /> </figure>



<p> <br />
You will need <a href="https://zorro-project.com/download.php" target="_blank" rel="noopener">Zorro S</a> because the spreadsheet function is not available in the free version. Start the script any morning. It will open the spreadsheet, where you can click in any of the white fields and enter a new key figure value for today. You can anytime enter new figures for today or for past days. At any entry, the score is calculated and &#8211; if the history spans more than 2 days – a chart is plotted as in the above example.</p>


<p>Normally, personal performance depends on about 5-10 key figures (maximum is 15). For instance, miles you’ve jogged today, steps walked, exercises done, pages read, words written, words learned in a new language, value of your bank account, value of your stock portfolio, burgers eaten, cigarettes smoked, enemies killed, or number of old ladies you helped crossing the street. If you’re a president, consider the script a free present (we hope for generous tax exceptions in exchange). If you’re an ISO 9000 certified company and want to use the script for your quality management, please contact oP group to pay your fee. For personal use, the script is free. Pimp your performance and make the world a better place!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/pimp-your-performance-with-key-figures/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Better Tests with Oversampling</title>
		<link>https://financial-hacker.com/better-tests-with-oversampling/</link>
					<comments>https://financial-hacker.com/better-tests-with-oversampling/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Mon, 23 Nov 2015 14:14:52 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[System Development]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Price action]]></category>
		<category><![CDATA[Time series oversampling]]></category>
		<category><![CDATA[Walk forward analysis]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">http://www.financial-hacker.com/?p=1055</guid>

					<description><![CDATA[The more data you use for testing or training your strategy, the less bias will affect the test result and the more accurate will be the training. The problem: price data is always in short supply. Even shorter since you must put aside some part for out-of-sample tests. Extending the test or training period far &#8230; <a href="https://financial-hacker.com/better-tests-with-oversampling/" class="more-link">Continue reading<span class="screen-reader-text"> "Better Tests with Oversampling"</span></a>]]></description>
										<content:encoded><![CDATA[<p>The more data you use for testing or training your strategy, the less bias will affect the test result and the more accurate will be the training. The problem: <strong>price data is always in short supply</strong>. Even shorter since you must put aside some part for out-of-sample tests. Extending the test or training period far into the past is not always a solution. The markets of the 1990s or 1980s were very different from today, so their price data can cause misleading results.<br />
   In this article I&#8217;ll describe a simple method to <strong>produce more trades</strong> for testing and training from the same amount of price data. As a side effect, you&#8217;ll get an additional metric for the robustness of your strategy. <span id="more-1055"></span></p>
<p>The price curve is normally divided into equal sections, named <strong>bars</strong>. Any bar has an associated <strong>candle</strong> with an open, close, high, low, and average price which are used by the system for detecting patterns and generating trade signals. When the raw price data has a higher time resolution than a bar, which is normally the case, the candle prices are sampled like this:</p>
<p><span class="wp-katex-eq" data-display="false">Open ~=~ y_{t-dt} </span><br />
<span class="wp-katex-eq" data-display="false">High ~=~ max(y_{t-dt}~...~y_t)</span><br />
<span class="wp-katex-eq" data-display="false">Low ~=~ min(y_{t-dt}~...~y_t)</span><br />
<span class="wp-katex-eq" data-display="false">Close ~=~ y_t</span><br />
<span class="wp-katex-eq" data-display="false">Avg ~=~ 1/n \sum_{t-dt}^{t}{y_i}</span></p>
<p>where <em><strong>y<sub>t</sub></strong></em> is the raw price tick at time <em><strong>t</strong></em>, and <em><strong>dt</strong></em> is the bar period. If we now subdivide the bar period into <em><strong>m</strong></em> partitions and resample the bars with the time shifted by <em><strong>dt/m</strong></em>, we can produce <em><strong>m</strong></em> slightly different price curves from the same high resolution curve:</p>
<p><span class="wp-katex-eq" data-display="false">Open_j ~=~ y_{t-j/m dt-dt} </span><br />
<span class="wp-katex-eq" data-display="false">High_j ~=~ max(y_{t-j/m dt-dt}~...~y_{t-j/m dt})</span><br />
<span class="wp-katex-eq" data-display="false">Low_j ~=~ min(y_{t-j/m dt-dt}~...~y_{t-j/m dt})</span><br />
<span class="wp-katex-eq" data-display="false">Close_j ~=~ y_{t-j/m dt}</span><br />
<span class="wp-katex-eq" data-display="false">Avg_j ~=~ 1/n \sum_{t-j/m dt-dt}^{t-j/m dt}{y_i}</span></p>
<p><em><strong>m</strong></em> is the oversampling factor. The price curve index <em><strong>j</strong></em> runs from <em><strong>0</strong></em> to <em><strong>m-1</strong></em>. Any curve <em><strong>j</strong></em> has obviously the same properties as the original price curve, but has slightly different candles. Some candles can even be extremely different in volatile market situations. Testing a strategy will thus normally produce a different result on any curve.</p>
<p><strong>Time series oversampling</strong> can also can also be used with price-based bars, such as Renko Bars or Range Bars, although the above equations then change to the composition formula of the specific bar type. I found that the profit factors of strategies can differ by up to 30% between oversampled price curves. A large variance in results hints that something with the strategy may be wrong &#8211; maybe it&#8217;s too sensitive to randomness and thus subject to improvement. A strategy that produces large losses on some curves should better be discarded, even if the overall result is positive. But you can safely assume that live training results are best represented by the worst of all the oversampled price curves.</p>
<h3>Price action example</h3>
<p>Time series oversampling is supported by the <a href="http://www.financial-hacker.com/hackers-tools-zorro-and-r/">Zorro platform</a>. This allows us to quickly check its pros and cons with example strategies. We&#8217;ll look into a simple price action strategy with candle patterns. This is a strategy of the <a href="http://www.financial-hacker.com/build-better-strategies/">data mining flavor</a>. It is not based on a market model, since no good model can explain a predictive power of candle patterns (if you know one, please let me know too!). This trading method therefore has an irrational touch, although it&#8217;s said to have worked for Japanese rice traders 300 years ago, maybe due to trading habits or behavior patterns of large market participants. Whatever the reason: while trading the old rice candle patterns in today&#8217;s markets can not be really recommended, tests indeed hint at a <strong>weak and short-lived predictive power</strong> of 3-candle patterns in some currency pairs, such as EUR/USD. The emphasis is on short-lived: Trading habits change and thus predictive candle patterns expire within a few years, while new patterns emerge. </p>
<p>Here&#8217;s the Zorro script of such a strategy. In the training run it generates trading rules with 3-candle patterns that preceded profitable trades. In testing and live trading, a position is opened whenever the generated rule detects such a potentially profitable pattern. A walk forward test is used for curve fitting prevention, which is mandatory for all data mining systems:</p>
<p><!--?prettify linenums=true?--></p>
<pre class="prettyprint">function run()
{
  BarPeriod = 60; // 1-hour bars
  set(RULES+ALLCYCLES);
  NumYears = 10;
  NumWFOCycles = 10;

  if(Train) {
    Hedge = 2;	  // allow simultaneous long + short trades 
    Detrend = TRADES; // detrend on trade level
    MaxLong = MaxShort = 0; // no limit
  } else {
    Hedge = 1;	// long trade closes short and vice versa
    Detrend = 0;
    MaxLong = MaxShort = 1; // only 1 open position	
  }
	
  LifeTime = 3; // 3 hours trade time
  if(between(lhour(CET),9,13))  // European business hours
  {
    if(adviseLong(PATTERN+FAST+2,0, // train patterns with trade results
      priceHigh(2),priceLow(2),priceClose(2),
      priceHigh(1),priceLow(1),priceClose(1),
      priceHigh(1),priceLow(1),priceClose(1),
      priceHigh(0),priceLow(0),priceClose(0)) &gt; 50)
        enterLong();	
			
    if(adviseShort(PATTERN+FAST+2) &gt; 50)
      enterShort();
  }
}</pre>
<p>The core of the script is the adviseLong/adviseShort call, Zorro&#8217;s machine learning function (details are better explained in the <a href="http://manual.zorro-project.com/tutorial_pre.htm" target="_blank" rel="noopener noreferrer">Zorro tutorial</a>). The function is fed with patterns of 3 candles; the high, low, and close prices of adjacent candles are compared with each other (the open price is not used as it&#8217;s identical to the previous close in 24-hour traded assets). Training target is the return of a 3-hours trade after the appearance of a pattern. We&#8217;re using 3 hours trade time because the patterns consist of 3 bars, and it makes some sense to have a prediction horizon similar to the pattern length. Since we&#8217;re trading EUR/USD, we&#8217;re limiting the trades to European business hours. So the last trade must be entered at 13:00 for being closed at 16:00.</p>
<p>But when we train and test the above script with EUR/USD, we get no profitable strategy &#8211; at least not with realistic trading costs (an FXCM microlot account is simulated by default):</p>
<p><figure id="attachment_1139" aria-describedby="caption-attachment-1139" style="width: 879px" class="wp-caption alignnone"><a href="http://www.financial-hacker.com/wp-content/uploads/2015/11/priceaction2.png"><img decoding="async" class="wp-image-1139 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/11/priceaction2.png" alt="" width="879" height="321" srcset="https://financial-hacker.com/wp-content/uploads/2015/11/priceaction2.png 879w, https://financial-hacker.com/wp-content/uploads/2015/11/priceaction2-300x110.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a><figcaption id="caption-attachment-1139" class="wp-caption-text">Price action without oversampling, P&amp;L curve</figcaption></figure></p>
<p>We can see that the script seems to enter trades mostly at random, so the equity drops continuously at about the rate of the trading costs. The script performs a 10-years walk-forward test in 10 cycles. The default training/test split is 85%, so the test time is about 9 months after a training time of 4 years. 4 years are roughly equivalent to 4*250*24 = 24000 patterns to check. That&#8217;s apparently not enough to significantly distinguish profitable from random patterns.</p>
<p>The problem: <strong>We can not simply extend the training time.</strong> When we do that, we&#8217;ll find that the result does not get better. The reason is the limited pattern lifetime. It makes no sense to train past the half-life of the found patterns. So this is not the solution. But what happens when we train and test the same strategy with 4-fold oversampling?<br />
<!--?prettify linenums=true?--></p>
<pre class="prettyprint">NumSampleCycles = 4;</pre>
<p>When we add this line to the script, the training process gets four times more patterns. Although many of them are similar, the amount of data is now enough to distinguish profitable from random patterns with some accuracy. We can see this in the now positive P&amp;L curve over the likewise extended test periods:</p>
<p><figure id="attachment_1117" aria-describedby="caption-attachment-1117" style="width: 879px" class="wp-caption alignnone"><a href="http://www.financial-hacker.com/wp-content/uploads/2015/11/priceaction.png"><img loading="lazy" decoding="async" class="wp-image-1117 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/11/priceaction.png" alt="" width="879" height="321" srcset="https://financial-hacker.com/wp-content/uploads/2015/11/priceaction.png 879w, https://financial-hacker.com/wp-content/uploads/2015/11/priceaction-300x110.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a><figcaption id="caption-attachment-1117" class="wp-caption-text">Price action with 4-fold oversampling, P&amp;L curve</figcaption></figure></p>
<p>Also you&#8217;ll now get an additional section in the performance report, like this:</p>
<pre><code>Sample Cycles    Best    Worst    Avg  StdDev
Net Profit       5362$   4001$   4730$   4094$
Profit Factor     1.58    1.45    1.51    0.05
Num Trades        1256    1273    1240
Win Rate           41%     39%     40%</code></pre>
<p>Large deviations between the sample cycles will tell you that your strategy is unstable against random price curve fluctuations.</p>
<p>I&#8217;ve added the above script to the 2015 repository. But although it generates some profit, be aware that it&#8217;s for demonstration only and no &#8216;industrial quality&#8217;. Sharpe ratio and R2 are not good, drawdowns are long, and essential ingredients such as stops, trailing, money management, portfolio diversification, filters, and DMB measurement are not included. So better don&#8217;t trade it live.</p>
<h3>Conclusion</h3>
<p>Admittedly the price action system is a drastic and somewhat dubious example of the benefits of oversampling. But I found that 4-fold or 6-fold oversampling improves optimization and training of almost all strategies, and also increases the quality of backtests by making them less susceptible to extreme candles and outliers. </p>
<p>Oversampling is certainly not the one-fits-all solution. It will not work when the system relies on a specific time for opening and closing trades, as for gap trading or for systems based on daily bars. And it does not help either when single candles have little effect on the result, for instance when trade signals are generated from moving averages with very long time periods. But in most cases it noticeably improves testing and trading.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/better-tests-with-oversampling/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title>The Cold Blood Index</title>
		<link>https://financial-hacker.com/the-cold-blood-index/</link>
					<comments>https://financial-hacker.com/the-cold-blood-index/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Mon, 26 Oct 2015 12:50:51 +0000</pubDate>
				<category><![CDATA[3 Most Useful]]></category>
		<category><![CDATA[Indicators]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Cold Blood Index]]></category>
		<category><![CDATA[Data mining bias]]></category>
		<category><![CDATA[Drawdown]]></category>
		<category><![CDATA[Grid trading]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">http://www.financial-hacker.com/?p=83</guid>

					<description><![CDATA[You&#8217;ve developed a new trading system. All tests produced impressive results. So you started it live. And are down by $2000 after 2 months. Or you have a strategy that worked for 2 years, but revently went into a seemingly endless drawdown. Situations are all too familiar to any algo trader. What now? Carry on in cold blood, &#8230; <a href="https://financial-hacker.com/the-cold-blood-index/" class="more-link">Continue reading<span class="screen-reader-text"> "The Cold Blood Index"</span></a>]]></description>
										<content:encoded><![CDATA[<p>You&#8217;ve developed a new trading system. All tests produced impressive results. So you started it live. And are down by $2000 after 2 months. Or you have a strategy that worked for 2 years, but revently went into a seemingly endless drawdown. Situations are all too familiar to any algo trader. What now? <strong>Carry on in cold blood, or pull the brakes in panic?</strong> <br />     Several reasons can cause a strategy to lose money right from the start. It can be already<strong> expired</strong> since the market inefficiency disappeared. Or the system is worthless and the test falsified by some <strong>bias</strong> that survived all reality checks. Or it&#8217;s a <strong>normal drawdown</strong> that you just have to sit out. In this article I propose an algorithm for deciding very early whether or not to abandon a system in such a situation.<span id="more-83"></span></p>
<p>When you start a trading strategy, you&#8217;re almost always under water for some time. This is a normal consequence of <strong>equity curve volatility</strong>. It is the very reason why you need initial capital at all for trading (aside from covering margins and transaction costs). Here you can see the typical bumpy start of a trading system:</p>
<p><figure id="attachment_252" aria-describedby="caption-attachment-252" style="width: 735px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="wp-image-252 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/09/z5zulu3.png" alt="z5zulu3" width="735" height="323" srcset="https://financial-hacker.com/wp-content/uploads/2015/09/z5zulu3.png 735w, https://financial-hacker.com/wp-content/uploads/2015/09/z5zulu3-300x132.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /><figcaption id="caption-attachment-252" class="wp-caption-text">CHF grid trader, initial live equity curve</figcaption></figure></p>
<p>You can estimate from the live equity curve that this system was rather profitable (it was a grid trader exploiting the CHF price cap). It started in July 2013 and had earned about 750 pips in January 2014, 7 months later. Max drawdown was ~400 pips from September until November. So the raw return of that system was about 750/400 ~= 180%. Normally an excellent value for a trade system. But you can also see from the curve that you were down 200 pips about six weeks into trading, and thus had lost almost half of your minimum initial capital. And if you had started the system in September, you had even stayed under water for more than 3 months! This is a psychologically difficult situation. Many traders panic, pull out, and this way <strong>lose money even with highly profitable systems</strong>. Algo trading unaffected by emotions? Not true.</p>
<h3>Not so out of sample</h3>
<p>The basic problem: you can never fully trust your test results. No matter how out-of-sample you test it, a strategy still suffers from a certain amount of <strong>Data-Snooping Bias</strong>. The standard method of measuring bias &#8211; <strong><a href="http://www.financial-hacker.com/whites-reality-check/">White&#8217;s Reality Check</a></strong> &#8211; works well for simple mechanically generated systems, as in the <strong><a href="http://www.financial-hacker.com/trend-and-exploiting-it/">Trend Experiment</a></strong>. But all human decisions about algorithms, asset selection, filters, training targets, stop/takeprofit mechanisms, WFO windows, money management and so on add new bias, since they are normally affected by testing. The out-of-sample data is then not so out-of-sample anymore. While the bias by training or optimization can be measured and even eliminated with walk forward methods, the <strong>bias introduced by the mere development process is unknown</strong>. The strategy might still be profitable, or not anymore, or not at all. You can only find out by comparing live results permanently with test results.</p>
<p>You could do that with no risk by trading on a demo account. But if the system is really profitable, demo time is sacrificed profit and thus expensive. Often very expensive, as you must demo trade a long time for some result significancy, and many strategies have a limited lifetime anyway. So you normally demo trade a system only a few weeks for making sure that the script is bug-free, then you go live with real money.</p>
<h3>Pull-out conditions</h3>
<p>The simplest method of comparing live results is based on the <strong>maximum drawdown</strong> in the test. This is the pull-out inequality:</p>
<p style="text-align: center;"><em><strong>[pmath size=18]E ~&lt;~ C + G t/y &#8211; D[/pmath]</strong></em></p>
<p><em><strong>E</strong></em> = Current account equity<br /> <em><strong>C</strong></em> = Initial account capital<br /> <em><strong>G</strong></em> = Test profit<br /> <em><strong>t</strong></em> = Live trading period<br /> <em><strong>y</strong></em> = Test period<br /> <em><strong>D</strong></em> = Test maximum drawdown</p>
<p>This formula means simply that you should pull out when the live trading drawdown exceeds the maximum drawdown from the test. Traders often check their live results this way, but there are many problems involved with this method:</p>
<ul style="list-style-type: square;">
<li>The maximum backtest drawdown is more or less random.</li>
<li>Drawdowns grow with the test period, thus longer test periods produce worse maximum drawdowns and later pull-out signals.</li>
<li>The drawdown time is not considered.</li>
<li>The method does not work when profits are reinvested by some money management algorithm.</li>
<li>The method does not consider the unlikeliness that the maximum drawdown happens already at live trading start.</li>
</ul>
<p>For those reasons, the above pullout inequality is often modified for taking the drawdown length and growth into account. The maximum drawdown is then assumed to <strong>grow with the square root of time</strong>, leading to this modified formula:</p>
<p style="text-align: center;"><strong><em>[pmath size=18]E ~&lt;~ C + G t/y &#8211; D sqrt{{t+l}/y}[/pmath]</em></strong></p>
<p><em><strong>E</strong></em> = Current account equity<br /> <em><strong>C</strong></em> = Initial account capital<br /> <em><strong>G</strong></em> = Test profit<br /> <em><strong>t</strong></em> = Live trading period<br /> <b><i>y</i></b> = Test period<br /> <em><strong>D</strong></em> = Maximum drawdown depth<br /> <b>l</b> = Maximum drawdown length</p>
<p> This was in fact the algorithm that I often suggested to clients for supervising their live results. It puts the drawdown in relation to the test period and also considers the drawdown length, as the probability of being inside the worst drawdown right at live trading start is <em><strong>l/y</strong></em>. Still, the method does not work with a profit reinvesting system. And it is dependent on the rather random test drawdown. You could address the latter issue by taking the drawdown from a Montecarlo shuffled equity curve, but this produces new problems since trading results have often serial correlation.</p>
<p>After this lenghty introduction for motivation, here&#8217;s the proposed algorithm that overcomes the mentioned issues.</p>
<h3>Keeping cold blood</h3>
<p>For finding out if we really must immediately stop a strategy, we calculate the deviation of the current live trading situation from the strategy behavior in the test. For this we do not use the maximum drawdown, but the backtest equity or balance curve:</p>
<ol>
<li>Determine a time window of length <em><strong>l </strong></em>(in days) that you want to check. It&#8217;s normally the length of the current drawdown; if your system is not in a drawdown, you&#8217;re probably in cold blood anyway. Determine the drawdown depth <em><strong>D</strong></em>,  i.e. the net loss during that time.</li>
<li>Place a time window of same size <em><strong>l </strong></em>at the start of the test balance curve.</li>
<li>Determine the balance difference <em><strong>G</strong></em> from end to start of the window. Increase a counter <em><strong>N</strong></em> when <em><strong>G &lt;= D</strong></em>. </li>
<li>Move the window forward by 1 day.</li>
<li>Repeat steps 3 and 4 until the window arrived at the end of the balance curve. Count the steps with a counter <em><strong>M</strong></em>.</li>
</ol>
<p>Any window movement takes a sample out of the curve. We have <em><strong>N</strong></em> samples that are similar or worse, and <em><strong>M-N</strong></em> samples that are better than the current trading situation. The probability to <strong>not</strong> encounter such a drawdown in <em><strong>T</strong></em> out of <em><strong>M</strong></em> samples is a simple combinatorial equation:</p>
<p style="text-align: center;"><em><strong>[pmath size=18]1-P ~=~ {(M-N)!(M-T)! }/ {M!(M-N-T)!}[/pmath]</strong></em></p>
<p><em><strong>N</strong></em> = Number of  <em><strong>G &lt;= D</strong></em> occurrences<br /> <em><strong>M</strong></em> = Total samples = <em><strong>y-l+1</strong></em><br /> <em><strong>l </strong></em>= Window length in days<em><strong><br /> </strong></em><em><strong>y</strong></em> = Test time in days<br /> <em><strong>T</strong></em> = Samples taken = <em><strong>t-l+1<br /> </strong><strong>t</strong></em> = Live trading time in days</p>
<p><em><strong>P</strong></em> is the <strong>cold blood index</strong> &#8211; the similarity of the live situation with the backtest. As long as <em><strong>P</strong></em> stays above 0.1 or 0.2, probably all is still fine. But if <em><strong>P</strong></em> is very low or zero, either the backtest was strongly biased or the market has significantly changed. The system can still be profitable, just less profitable as in the test. But when the current loss <em><strong>D</strong></em> is large in comparison to the gains so far, we should stop.</p>
<p>Often we want to calculate <strong>P</strong> soon after the begin of live trading. The window size <strong><em>l</em> </strong>is then identical to our trading time <em><strong>t</strong></em>,<em><strong> </strong></em>hence <em><strong>T == 1</strong></em>. This simplifies the equation to: </p>
<p style="text-align: center;"><em><strong>[pmath size=18]P ~=~ N/M[/pmath]</strong></em></p>
<p>In such a situation I&#8217;d give up and pull out of a painful drawdown as soon as <em><strong>P</strong></em> drops below 5%.</p>
<p>The slight disadvantage of this method is that you must perform a backtest with the same capital allocation, and store its balance or equity curve in a file for later evaluation during live trading. However this should only take a few lines of code in a strategy script. </p>
<p>Here&#8217;s a small example script for Zorro that calculates <em><strong>P</strong></em> (in percent) from a stored balance curve when a trading time <strong>t</strong> and drawdown of length <em><strong>l</strong></em> and depth <em><strong>D</strong></em> is given:</p>
<pre>int TradeDays = 40;    <em>// t, Days since live start</em>
int DrawDownDays = 30; <em>// l, Days since you're in drawdown</em>
var DrawDown = 100;    <em>// D, Current drawdown depth in $</em>

string BalanceFile = "Log\\BalanceDaily.dbl"; <em>// stored double array</em>

var logsum(int n)
{
  if(n &lt;= 1) return 0;
  return log(n)+logsum(n-1);
}

void main()
{
  int CurveLength = file_length(BalanceFile)/sizeof(var);
  var *Balances = file_content(BalanceFile);

  int M = CurveLength - DrawDownDays + 1;
  int T = TradeDays - DrawDownDays + 1;
 
  if(T &lt; 1 || M &lt;= T) {
    printf("Not enough samples!");
    return;
  }
 
  var GMin=0., N=0.;
  int i=0;
  for(; i &lt; M-1; i++)
  {
    var G = Balances[i+DrawDownDays] - Balances[i];
    if(G &lt;= -DrawDown) N += 1.;
    if(G &lt; GMin) GMin = G;
  } 

  var P;
  if(TradeDays &gt; DrawDownDays)
    P = 1. - exp(logsum(M-N)+logsum(M-T)-logsum(M)-logsum(M-N-T));
  else
    P = N/M;

  printf("\nTest period: %i days",CurveLength);
  printf("\nWorst test drawdown: %.f",-GMin);
  printf("\nM: %i N: %i T: %i",M,(int)N,T);
  printf("\nCold Blood Index: %.1f%%",100*P);
}</pre>
<p>Since my computer is unfortunately not good enough for calculating the factorials of some thousand samples, I&#8217;ve summed up the logarithms instead &#8211; therefore the strange <strong>logsum</strong> function in the script.</p>
<h3>Conclusion</h3>
<ul style="list-style-type: square;">
<li>Finding out early whether a live trading drawdown is &#8216;normal&#8217; or not can be essential for your wallet.</li>
<li>The backtest drawdown is a late and inaccurate criteria.</li>
<li>The Cold Blood Index calculates the precise probability of such a drawdown based on the backtest balance curve.</li>
</ul>
<p>I&#8217;ve added the script above to the 2015 scripts collection. I also have suggested to the Zorro developers to implement this method for automatically analyzing drawdowns while live trading, and issue warnings when <em><strong>P</strong></em> gets dangerously low. This can also be done separately for components in a portfolio system. This feature will probably appear in a future Zorro version. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/the-cold-blood-index/feed/</wfw:commentRss>
			<slash:comments>27</slash:comments>
		
		
			</item>
		<item>
		<title>Is &#8220;Scalping&#8221; Irrational?</title>
		<link>https://financial-hacker.com/is-scalping-irrational/</link>
					<comments>https://financial-hacker.com/is-scalping-irrational/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Fri, 09 Oct 2015 16:45:41 +0000</pubDate>
				<category><![CDATA[Indicators]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Entropy]]></category>
		<category><![CDATA[Experiment]]></category>
		<category><![CDATA[HFT]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[Shannon]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">http://www.financial-hacker.com/?p=483</guid>

					<description><![CDATA[Clients often ask for strategies that trade on very short time frames. Some are possibly inspired by &#8220;I just made $2000 in 5 minutes&#8221; stories on trader forums. Others have heard of High Frequency Trading: the higher the frequency, the better must be the trading! The Zorro developers had been pestered for years until they &#8230; <a href="https://financial-hacker.com/is-scalping-irrational/" class="more-link">Continue reading<span class="screen-reader-text"> "Is &#8220;Scalping&#8221; Irrational?"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Clients often ask for strategies that trade on <strong>very short time frames</strong>. Some are possibly inspired by &#8220;I just made $2000 in 5 minutes&#8221; stories on trader forums. Others have heard of <a href="http://www.financial-hacker.com/hacking-hft-systems/" target="_blank" rel="noopener"><strong>High Frequency Trading</strong></a>: the higher the frequency, the better must be the trading! The <strong><a href="http://www.financial-hacker.com/hackers-tools-zorro-and-r/">Zorro</a></strong> developers had been pestered for years until they finally implemented tick histories and millisecond time frames. <strong>Totally useless features?</strong> Or has short term algo trading indeed some quantifiable advantages? An experiment for looking into that matter produced a <strong>surprising result</strong>.<span id="more-483"></span></p>
<p>It is certainly tempting to earn profits within minutes. Additionally, short time frames produce more bars and trades &#8211; a great advantage for strategy development. The quality of test and training depends on the amount of data, and timely price data is always in short supply. Still, scalping &#8211; opening and closing trades in minutes or seconds &#8211; is largely considered nonsense and irrational by algo traders. Four main reasons are given:</p>
<ol>
<li>Short time frames cause high <strong>trading costs</strong> &#8211; slippage, spread, commission &#8211; in relation to the expected profit.</li>
<li>Short time frames expose more <strong>&#8216;noise&#8217;,</strong> <strong>&#8216;randomness&#8217;</strong> and <strong>&#8216;artifacts&#8217;</strong> in the price curve, which reduces profit and increases risk.</li>
<li>Any algorithms had to be individually adapted to the broker or price data provider due to <strong>price feed dependency</strong> in short time frames.</li>
<li>Algorithmic strategies usually <strong>cease working</strong> below a certain time frame.</li>
</ol>
<p>Higher costs, less profit, more risk, feed dependency, no working strategies &#8211; seemingly good arguments against scalping (HFT is a very different matter). But never trust common wisdom, especially not in trading. That&#8217;s why I had not yet added scalping to my <a href="http://www.financial-hacker.com/seventeen-popular-trade-strategies-that-i-dont-really-understand/">list of irrational trade methods</a>. I can confirm reasons number 3 and 4 from my own experiences: Below bar periods of about 10 minutes, backtests with price histories from different brokers began to produce noticeably different results. And I never managed to develop a strategy with a significantly positive walk-forward test on bar periods less than 30 minutes. But this does not mean that such a strategy does not exist. Maybe short time frames just need special trade methods?</p>
<p>So I&#8217;ve programmed an experiment for finding out once and for all if scalping is really as bad as it&#8217;s rumored to be. Then I can at least give some reasoned advice to the next client who desires a tick-triggered short-term trading strategy.</p>
<h3>Trading costs examined</h3>
<p>The first part of the experiment is easily done: a statistic of the impact of trading costs. Higher costs obviously require more profits for compensation. How many trades must you win for overcoming the trading costs at different time frames? Here&#8217;s a short script (in C, for Zorro) for answering this question:</p>
<pre class="prettyprint">function run()
{
  BarPeriod = 1;
  LookBack = 1440;
  Commission = 0.60;
  Spread = 0.5*PIP;

  int duration = 1, i = 0;
  if(!is(LOOKBACK))
    while(duration &lt;= 1440)
  { 
    var Return = abs(priceClose(0)-priceClose(duration))*PIPCost/PIP;
    var Cost = Commission*LotAmount/10000. + Spread*PIPCost/PIP;
    var Rate = ifelse(Return &gt; Cost, Cost/(2*Return) + 0.5, 1.);

    plotBar("Min Rate",i++,duration,100*Rate,AVG+BARS,RED); 
 
    if(duration &lt; 10) duration += 1;
    else if(duration &lt; 60) duration += 5;
    else if(duration &lt; 180) duration += 30;
    else duration += 60;
  }
  Bar += 100; // hack!
}</pre>
<p>This script calculates the minimum win rate to compensate the trade costs for different trade durations. We assumed here a spread of <strong>0.5 pips</strong> and a round turn commission of <strong>60 cents</strong> per 10,000 contracts &#8211; that&#8217;s average costs of a Forex trade. <strong>PIPCost/PIP</strong> in the above script is the conversion factor from a price difference to a win or loss on the account. We&#8217;re also assuming no win/loss bias: Trades shall win or lose on average the same amount. This allows us to split the <strong>Return</strong> of any trade in a win and a loss, determined by <strong>WinRate</strong>. The win is <strong>WinRate * Return</strong> and the loss is <strong>(1-WinRate) * Return</strong>. For breaking even, the win minus the loss must cover the cost. The required win rate for this is</p>
<p style="padding-left: 30px; text-align: center;"><em><strong>WinRate = Cost/(2*Return) + 0.5</strong></em></p>
<p>The win rate is averaged over all bars and plotted in a histogram of trade durations from 1 minute up to 1 day. The duration is varied in steps of 1, 5, 30, and 60 minutes. We&#8217;re entering a trade for any duration every 101 minutes (<strong>Bar += 100</strong> in the script is a hack for running the simulation in steps of 101 minutes, while still maintaining the 1-minute bar period).</p>
<p>The script needs a few seconds to run, then produces this histogram (for EUR/USD and 2015):</p>
<p><figure id="attachment_524" aria-describedby="caption-attachment-524" style="width: 889px" class="wp-caption alignnone"><a href="http://www.financial-hacker.com/wp-content/uploads/2015/10/scalp11.png"><img loading="lazy" decoding="async" class="wp-image-524 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/10/scalp11.png" alt="" width="889" height="513" srcset="https://financial-hacker.com/wp-content/uploads/2015/10/scalp11.png 889w, https://financial-hacker.com/wp-content/uploads/2015/10/scalp11-300x173.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a><figcaption id="caption-attachment-524" class="wp-caption-text">Required win rate in percent vs. trade duration in minutes</figcaption></figure></p>
<p>You need about <strong>53% win rate</strong> for covering the costs of 1-day trades (rightmost bar), but <strong>90% win rate </strong>for 1-minute trades! Or alternatively, a 9:1 reward to risk ratio at 50% win rate. This exceeds the best performances of real trading systems by a large amount, and seems to confirm convincingly the first reason why you better take tales by scalping heroes on trader forums with a grain of salt.</p>
<p>But what about reason number two &#8211; that short time frames are plagued with &#8216;noise&#8217; and &#8216;randomness&#8217;? Or is it maybe the other way around and some effect makes short time frames even more predictable? That&#8217;s a little harder to test.</p>
<h3>Measuring randomness</h3>
<p>&#8216;Noise&#8217; is often identified with the high-frequency components of a signal. Naturally, short time frames produce more high-frequency components than long time frames. They could be detected with a highpass filter, or eliminated with a lowpass filter. Only problem: <strong>Price curve noise</strong> is not always related to high frequencies. Noise is just the part of the curve that does not carry information about the trading signal. For cycle trading, high frequencies are the signal and low-frequency trend is the noise. So the jaggies and ripples of a short time frame price curve might be just the very inefficiencies that you want to exploit. It depends on the strategy what noise is; there is no &#8216;general price noise&#8217;.</p>
<p>Thus we need a better criteria for determining the tradeability of a price curve. That criteria is <strong>randomness</strong>. You can not trade a random market, but you can potentially trade anything that deviates from randomness. Randomness can be measured through the <strong>information content</strong> of the price curve. A good measure of information content is the <strong>Shannon Entropy</strong>. It is defined this way:</p>
<p><a href="http://www.financial-hacker.com/wp-content/uploads/2015/10/shannon.png"><img loading="lazy" decoding="async" class="wp-image-529 size-full aligncenter" src="http://www.financial-hacker.com/wp-content/uploads/2015/10/shannon.png" alt="" width="260" height="47" /></a></p>
<p>This formula basically measures disorder. A very ordered, predictable signal has low entropy. A random, unpredictable signal has high entropy. In the formula, <em><strong>P(s<sub>i</sub>)</strong></em> is the relative frequency of a certain pattern <em><strong>s<sub>i </sub></strong></em>in the signal <em><strong>S</strong></em>. The entropy is at maximum when all patterns are evenly distributed and all <em><strong>P(s<sub>i</sub>)</strong></em> have about the same value. If some patterns appear more frequently than other patterns, the entropy goes down. The signal is then less random and more predictable. The Shannon Entropy is measured in <strong>bit</strong>.</p>
<p>The problem: Zorro has tons of indicators, even the Shannon Gain, but not the Shannon Entropy! So I have no choice but to write a new indicator, which fortunately is my job anyway. This is the source code of the Shannon Entropy of a char string:</p>
<pre class="prettyprint">var ShannonEntropy(char *S,int Length)
{
  static var Hist[256];
  memset(Hist,0,256*sizeof(var));
  var Step = 1./Length;
  int i;
  for(i=0; i&lt;Length; i++) 
    Hist[S[i]] += Step;
  var H = 0;
  for(i=0;i&lt;256;i++) {
    if(Hist[i] &gt; 0.)
      H -= Hist[i]*log2(Hist[i]);
  }
  return H;
}</pre>
<p>A char has 8 bit, so 2<sup>8</sup> = 256 different chars can appear in a string. The frequency of each char is counted and stored in the <strong>Hist</strong> array. So this array contains the <em><strong>P(s<sub>i</sub>)</strong> </em>of the above entropy formula. They are multiplied with their binary logarithm and summed up; the result is <em><strong>H(S)</strong></em>, the Shannon Entropy.</p>
<p>In the above code, a char is a pattern of the signal. So we need to convert our price curve into char patterns. This is done by a second <strong>ShannonEntropy</strong> function that calls the first one:</p>
<pre class="prettyprint">var ShannonEntropy(var *Data,int Length,int PatternSize)
{
  static char S[1024]; // hack!
  int i,j;
  int Size = min(Length-PatternSize-1,1024);
  for(i=0; i&lt;Size; i++) {
    int C = 0;
    for(j=0; j&lt;PatternSize; j++) {
    if(Data[i+j] &gt; Data[i+j+1])
      C += 1&lt;&lt;j;
    }
    S[i] = C;
  }
  return ShannonEntropy(S,Size);
}</pre>
<p><strong>PatternSize</strong> determines the partitioning of the price curve. A pattern is defined by a number of price changes. Each price is either higher than the previous price, or it is not; this is a binary information and constitutes one bit of the pattern. A pattern can consist of up to 8 bits, equivalent to 256 combinations of price changes. The patterns are stored in a char string. Their entropy is then determined by calling the first <strong>ShannonEntropy</strong> function with that string (both functions have the same name, but the compiler can distinguish them from their different parameters). Patterns are generated from any price and the subsequent <strong>PatternSize</strong> prices; then the procedure is repeated with the next price. So the patterns overlap.</p>
<h3>An unexpected result</h3>
<p>Now we only need to produce a histogram of the Shannon Entropy, similar to the win rate in our first script:</p>
<pre class="prettyprint">function run()
{
  BarPeriod = 1;
  LookBack = 1440*300;
  StartWeek = 10000;
 
  int Duration = 1, i = 0;
  while(Duration &lt;= 1440)
  { 
    TimeFrame = frameSync(Duration);
    var *Prices = series(price(),300);

    if(!is(LOOKBACK) &amp;&amp; 0 == (Bar%101)) {
      var H = ShannonEntropy(Prices,300,3);
      plotBar("Randomness",i++,Duration,H,AVG+BARS,BLUE);	
    }
    if(Duration &lt; 10) Duration += 1;
    else if(Duration &lt; 60) Duration += 5;
    else if(Duration &lt; 240) Duration += 30;
    else if(Duration &lt; 720) Duration += 120;
    else Duration += 720;
  }
}</pre>
<p>The entropy is calculated for all time frames at every 101th bar, determined with the modulo function. (Why 101? In such cases I&#8217;m using odd numbers for preventing synchronization effects). I cannot use here the hack with skipping the next 100 bars as in the previous script, as skipping bars would prevent proper shifting of the price series. That&#8217;s why this script must really grind through any minute of 3 years, and needs several minutes to complete.</p>
<p>Two code lines should be explained because they are critical for measuring the entropy of daily candles using less-than-a-day bar periods:</p>
<p><strong>StartWeek = 10000;</strong></p>
<p>This starts the week at Monday midnight (<strong>1</strong> = Monday, <strong>00 00</strong> = midnight) instead of Sunday 11 pm. This line was missing at first and I wondered why the entropy of daily candles was higher than I expected. Reason:  The single Sunday hour at 11 pm counted as a full day and noticeably increased the randomness of daily candles.</p>
<p><strong>TimeFrame = frameSync(Duration);</strong></p>
<p>This synchronizes the time frame to full hours respectively days. If this is missing, the Shannon Entropy of daily candles gets again a too high value since the candles are not in sync with a day anymore. A day has often less than 1440 one-minute bars due to weekends and irregularities in the historical data.</p>
<p>The Shannon Entropy is calculated with a pattern size of 3 price changes, resulting in 8 different patterns. 3 bit is the maximum entropy for 8 patterns. As price changes are not completely random, I expected an entropy value slightly smaller than 3, steadily increasing when time frames are decreasing. However I got this interesting histogram (EUR/USD, 2013-2015, FXCM price data):</p>
<p><figure id="attachment_569" aria-describedby="caption-attachment-569" style="width: 637px" class="wp-caption alignnone"><a href="http://www.financial-hacker.com/wp-content/uploads/2015/10/scalp2_32.png"><img loading="lazy" decoding="async" class="wp-image-569 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/10/scalp2_32.png" alt="" width="637" height="513" srcset="https://financial-hacker.com/wp-content/uploads/2015/10/scalp2_32.png 637w, https://financial-hacker.com/wp-content/uploads/2015/10/scalp2_32-300x242.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a><figcaption id="caption-attachment-569" class="wp-caption-text">Entropy vs. time frame (minutes)</figcaption></figure></p>
<p>The entropy is almost, but not quite 3 bit. This confirms that price patterns are not absolutely random. We can see that the 1440 minutes time frame has the lowest Shannon Entropy at about 2.9 bit. This was expected, as the daily cycle has a strong effect on the price curve, and daily candles are thus more regular than candles of other time frames. For this reason price action or price pattern algorithms often use daily candles. The entropy increases with decreasing time frames, but only down to time frames  of about ten minutes. Even lower time frames are actually less random!</p>
<p>This is an unexpected result. The lower the time frame, the less price quotes does it contain, so the impact of chance should be in fact higher. But the opposite is the case. I could produce similar results with other patterns of 4 and 5 bit, and also with other assets. For making sure I continued the experiment with a different, tick-based price history and even shorter time frames of 2, 5, 10, 15, 30, 45, and 60 seconds (Zorro&#8217;s &#8220;useless&#8221; micro time frames now came in handy, after all):</p>
<p><figure id="attachment_601" aria-describedby="caption-attachment-601" style="width: 205px" class="wp-caption alignnone"><a href="http://www.financial-hacker.com/wp-content/uploads/2015/10/scalp2_41.png"><img loading="lazy" decoding="async" class="wp-image-601 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/10/scalp2_41.png" alt="" width="205" height="513" srcset="https://financial-hacker.com/wp-content/uploads/2015/10/scalp2_41.png 205w, https://financial-hacker.com/wp-content/uploads/2015/10/scalp2_41-120x300.png 120w" sizes="auto, (max-width: 205px) 85vw, 205px" /></a><figcaption id="caption-attachment-601" class="wp-caption-text">Entropy vs. time frame (seconds)</figcaption></figure></p>
<p>The x axis is now in second units instead of minutes. We see that price randomness continues to drop with the time frame.</p>
<p>There are several possible explanations. Price granularity is higher at low time frames due to the smaller number of ticks. High-volume trades are often split into many small parts (&#8216;<strong>iceberg trades</strong>&#8216;) and may cause a sequence of similar price quotes in short intervals. All this reduces the price entropy of short time frames. But it does not necessarily increase trade opportunities:  A series of identical quotes has zero entropy and is 100% predictable, but can not be traded. Of course, iceberg trades are still an interesting inefficiency that could theoretically be exploited &#8211; if it weren&#8217;t for the high trading costs. So that&#8217;s something to look further into only when you have direct market access and no broker fees.</p>
<p>I have again uploaded the scripts to the 2015 scripts collection. You&#8217;ll need Zorro 1.36 or above for reproducing the results. Zorro S and tick based data are needed for the second time frames.</p>
<h3>Conclusions</h3>
<ul style="list-style-type: square;">
<li>Scalping is not completely nuts. Very low time frames expose some regularity.</li>
<li>Whatever the reason, this regularity can not be exploited by retail traders due to the high costs of short term trades.</li>
<li>On time frames above 60 minutes prices become less random and more regular. This recommends long time frames for algo trading.</li>
<li>The most regular price patterns appear with 1-day bars. They also cause the least trading costs.</li>
</ul>
<h3>Papers</h3>
<p>Shannon Entropy: <a href="http://www.ueltschi.org/teaching/chapShannon.pdf" target="_blank" rel="noopener noreferrer">Lecture</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/is-scalping-irrational/feed/</wfw:commentRss>
			<slash:comments>24</slash:comments>
		
		
			</item>
		<item>
		<title>Hacker&#8217;s Tools</title>
		<link>https://financial-hacker.com/hackers-tools-zorro-and-r/</link>
					<comments>https://financial-hacker.com/hackers-tools-zorro-and-r/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Sat, 03 Oct 2015 08:01:30 +0000</pubDate>
				<category><![CDATA[3 Most Useful]]></category>
		<category><![CDATA[Introductory]]></category>
		<category><![CDATA[No Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Aronson]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[R]]></category>
		<category><![CDATA[TSSB]]></category>
		<category><![CDATA[Vector-based test]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">http://www.financial-hacker.com/?p=89</guid>

					<description><![CDATA[For our financial hacking experiments (and for harvesting their financial fruits) we need some software machinery for research, testing, training, and live trading financial algorithms. There are many tools for algo trading, but no existing software platform today is really up to all those tasks. You have to put together your system from different software &#8230; <a href="https://financial-hacker.com/hackers-tools-zorro-and-r/" class="more-link">Continue reading<span class="screen-reader-text"> "Hacker&#8217;s Tools"</span></a>]]></description>
										<content:encoded><![CDATA[<p>For our financial hacking experiments (and for harvesting their financial fruits) we need some software machinery for research, testing, training, and live trading financial algorithms. There are many <a href="https://zorro-project.com/algotradingtools.php" target="_blank" rel="noopener">tools for algo trading</a>, but no existing software platform today is really up to all those tasks. You have to put together your system from different software packages. Fortunately, two are normally sufficient. I&#8217;ll use <strong>Zorro</strong> and <strong>R</strong> for most articles on this blog, but will also occasionally look into other tools.<span id="more-89"></span></p>
<h3>Choice of languages</h3>
<p>Algo trading systems are normally based on a script in some programming language. You can avoid writing scripts entirely by using a visual &#8216;strategy builder&#8217;, &#8216;code wizard&#8217; or spreadsheet program for defining your strategy. But this is also some sort of programming, just in a different language that you have to master. And visual builders can only create rather simple &#8216;indicator soup&#8217; systems that are unlikely to produce consistent trading profit. For serious algo trading sytems, real development, and real research, there&#8217;s no stepping around &#8216;real programming&#8217;.</p>
<p>You&#8217;re also not free to select the programming language with the nicest or easiest syntax. One of the best compromises of simplicity and object orientation is probably <strong>Python</strong>. It also offers libraries with useful statistics and indicator functions. Consequently, many strategy developers start with programming their systems in Python&#8230; and soon run into serious limitations. There&#8217;s another criterion that is more relevant for system development than syntax: <strong>execution speed</strong>.</p>
<p>Speed mostly depends on whether a computer language is <strong>compiled </strong>or <strong>interpreted</strong>. <strong>C</strong>,<strong> Pascal</strong>, and <strong>Java </strong>are compiled languages, meaning that the code runs directly on the processor (C, C++, Pascal) or on a &#8216;virtual machine&#8217; (Java). <strong>Python</strong>, <strong>R</strong>, and <strong>Matlab </strong>is interpreted: The code won&#8217;t run by itself, but is executed by an interpreter software. Interpreted languages are much slower and need more CPU and memory resources than compiled languages. It won&#8217;t help much for trading strategies that they have fast C-programmed libraries. All backtests or optimization processes must still run through the bottleneck of interpreted trading logic. Theoretically the slowness can be worked around with &#8216;vectorized coding&#8217; &#8211; see below &#8211; but that has little practical use.</p>
<p>R and Python have other advantages. They are <strong>interactive</strong>: you can enter commands directly at a console. This allows quick code or function testing. Some languages, such as <strong>C#</strong>, are inbetween: They are compiled to a machine-independent interim code that is then, dependent on implementation, either interpreted or converted to machine code. C# is about 4 times slower than C, but still 30 times faster than Python.</p>
<p>Here&#8217;s a benchmark table of the same two test programs written in several languages: a sudoku solver and a loop with a 1000 x 1000 matrix multiplication (in seconds):</p>
<table>
<tbody>
<tr>
<td>Language</td>
<td>Sudoku</td>
<td>Matrix</td>
</tr>
<tr>
<td>C, C++</td>
<td>1.0</td>
<td>1.8</td>
</tr>
<tr>
<td>Java</td>
<td>1.7</td>
<td>2.6</td>
</tr>
<tr>
<td>Pascal</td>
<td>&#8212;</td>
<td>4</td>
</tr>
<tr>
<td>C#</td>
<td>3.8</td>
<td>9</td>
</tr>
<tr>
<td>JavaScript</td>
<td>18.1</td>
<td>16</td>
</tr>
<tr>
<td>Basic (VBA)</td>
<td>&#8212;</td>
<td>25</td>
</tr>
<tr>
<td>Erlang</td>
<td>18</td>
<td>31</td>
</tr>
<tr>
<td>Python</td>
<td>119</td>
<td>121</td>
</tr>
<tr>
<td>Ruby</td>
<td>98</td>
<td>628</td>
</tr>
<tr>
<td>Matlab</td>
<td>&#8212;</td>
<td>621</td>
</tr>
<tr>
<td>R</td>
<td>&#8212;</td>
<td>1738</td>
</tr>
</tbody>
</table>
<p>Speed becomes important as soon as you want to develop a short-term trading system. In the development process you&#8217;re all the time testing system variants. A 10-years backtest with M1 historical data executes the strategy about 3 million times. If a C-written strategy needs 1 minute for this, the same strategy in EasyLanguage would need about 30 minutes, in Python 2 hours, and in R more than 10 hours! And that&#8217;s only a backtest, no optimization or WFO run. If I had coded the <a href="http://www.financial-hacker.com/trend-and-exploiting-it/">trend experimen</a>t in Python or R, I would today still wait for the results. You can see why trade platforms normally use a C variant or a proprietary compiled language for their strategies. <a href="http://www.financial-hacker.com/hacking-hft-systems/">HFT systems</a> are anyway written in C or directly in machine language.</p>
<p>Even compiled languages can have large speed differences due to different implementation of trading and analysis functions. When we compare not Sudoku or a matrix multiplication, but a real trading system &#8211; the small RSI strategy from <a href="http://manual.zorro-project.com/conversion.htm">this page</a> &#8211; we find very different speeds on different trading platforms (10 years backtest, ticks resolution):</p>
<ul style="list-style-type: square;">
<li>Zorro: ~ 0.5 seconds (compiled C)</li>
<li>MT4:  ~ 110 seconds (MQL4, a C variant)</li>
<li>MultiCharts: ~ 155 seconds (EasyLanguage, a C/Pascal mix)</li>
</ul>
<p>However, the differences are not as bad as suggested by the benchmark table. In most cases the slow language speed is partically compensated by fast vector function libraries. A script that does not go step by step through historical data, but only calls library functions that process all data simultaneously, would run with comparable speed in all languages. Indeed some trading systems can be coded in this <strong>vectorized</strong> method, but <b>u</b>nfortunately this works only with simple systems and requires entirely different scripts for backtests and live trading.</p>
<h3>Choice of tools</h3>
<p><strong>Zorro</strong> is a software for financial analysis and algo-trading &#8211; a sort of Swiss Knife tool since you can use it not only for live trading, but also for all sorts of quick tests. It&#8217;s my software of choice for financial hacking because:</p>
<ul style="list-style-type: square;">
<li>It&#8217;s free (unless you&#8217;re rich).</li>
<li>Scripts are in C, event driven and very fast. You can code a system or an idea in 5 minutes.</li>
<li>Open architecture &#8211; you can add anything with DLL plugins.</li>
<li>Minimalistic &#8211; just a frontend to a programming language.</li>
<li>Can be automatized for experiments.</li>
<li>Very stable &#8211; I rarely found bugs and they were fixed fast.</li>
<li>Very accurate, realistic trading simulation, including HFT.</li>
<li>Supports also options and futures, and portfolios of multiple assets.</li>
<li>Has a library with 100s of indicators, statistics and machine learning functions, most with source code.</li>
<li>Is continuously developed and supported (new versions usually come out every 2..3 months).</li>
<li>Last but not least: I know it quite well, as I&#8217;ve written its tutorial&#8230;</li>
</ul>
<p><a href="http://www.financial-hacker.com/wp-content/uploads/2015/09/Zorro.png"><img loading="lazy" decoding="async" class="aligncenter wp-image-117 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/09/Zorro-e1441536629470.png" alt="Zorro" width="294" height="582" srcset="https://financial-hacker.com/wp-content/uploads/2015/09/Zorro-e1441536629470.png 294w, https://financial-hacker.com/wp-content/uploads/2015/09/Zorro-e1441536629470-152x300.png 152w" sizes="auto, (max-width: 294px) 85vw, 294px" /></a></p>
<p>A strategy example coded in C, the classic SMA crossover:</p>
<pre class="prettyprint">void run()
{
  double* Close = series(priceClose());
  double* MA30 = series(SMA(Close,30));	
  double* MA100 = series(SMA(Close,100));
	
  Stop = 4*ATR(100);
  if(crossOver(MA30,MA100))
    enterLong();
  if(crossUnder(MA30,MA100))
    enterShort();
}</pre>
<p>More code can be found among the <a href="https://zorro-project.com/code.php" target="_blank" rel="noopener">script examples</a> on the Zorro website. You can see that Zorro offers a relatively easy trading implementation. But here comes the drawback of the C language: You can not as easy drop in external libraries as in Python or R. Using a C/C++ based data analysis or machine learning package involves sometimes a lengthy implementation. Fortunately, Zorro can also call R and Python functions for those purposes.</p>
<p><strong>R</strong> is a script interpreter for data analysis and charting. It is not a real language with consistent syntax, but more a conglomerate of operators and data structures that has grown over 20 years. It&#8217;s harder to learn than a normal computer language, but offers some unique advantages. I&#8217;ll use it in this blog when it comes to complex analysis or machine learning tasks. It&#8217;s my tool of choice for financial hacking because:</p>
<ul style="list-style-type: square;">
<li>It&#8217;s free. (&#8220;Software is like sex: it&#8217;s better when it&#8217;s free.&#8221;)</li>
<li>R scripts can be very short and effective (once you got used to the syntax).</li>
<li>It&#8217;s the global standard for data analysis and machine learning.</li>
<li>Open architecture &#8211; you can add modules for almost anything.</li>
<li>Minimalistic &#8211; just a console with a language interpreter.</li>
<li>Very stable &#8211; I found a few bugs in external libraries, but so far never in the main program.</li>
<li>Has tons of &#8220;packages&#8221; for all imaginable mathematical and statistical tasks, and especially for machine learning.</li>
<li>Is continuously developed and supported by the global scientific community (about 15 new packages usually come out every day).</li>
</ul>
<p><a href="http://www.financial-hacker.com/wp-content/uploads/2015/09/r.jpg"><img loading="lazy" decoding="async" class="alignnone wp-image-115 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/09/r-e1441536432531.jpg" alt="r" width="693" height="576" srcset="https://financial-hacker.com/wp-content/uploads/2015/09/r-e1441536432531.jpg 693w, https://financial-hacker.com/wp-content/uploads/2015/09/r-e1441536432531-300x249.jpg 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>This is the SMA crossover in R for a &#8216;vectorized&#8217; backtest:</p>
<pre class="prettyprint">require(quantmod)
require(PerformanceAnalytics)

Data &lt;- xts(read.zoo("EURUSD.csv", tz="UTC", format="%Y-%m-%d %H:%M", sep=",", header=TRUE))
Close &lt;- Cl(Data)
MA30 &lt;- SMA(Close,30)
MA100 &lt;- SMA(Close,100)
 
Dir &lt;- ifelse(MA30 &gt; MA100,1,-1) # calculate trade direction
Dir.1 &lt;- c(NA,Dir[-length(Dir)]) # shift by 1 for avoiding peeking bias
Return &lt;- ROC(Close)*Dir.1 
charts.PerformanceSummary(na.omit(Return))</pre>
<p>You can see that the vectorized code just consists of function calls. It runs almost as fast as the C equivalent. But it is difficult to read, it can not be used for live trading, and many parts of a trading logic &#8211; even a simple stop loss &#8211; cannot be coded for a vectorized test. Thus, so good R is for interactive data analysis, so hopeless is it for writing trade strategies &#8211; although some R packages (for instance, <strong>quantstrat</strong>) even offer rudimentary optimization and test functions. They all require an awkward coding style and do not simulate trading very realistically, but are still too slow for serious backtests.</p>
<p>Although R can not replace a serious backtest and trading platform, Zorro and R complement each other perfectly: <a href="http://www.financial-hacker.com/build-better-strategies-part-5-developing-a-machine-learning-system/" target="_blank" rel="noopener noreferrer">Here</a> is an example of a machine learning system build together with a deep learning package from R and the training and trading framework from Zorro.</p>
<h3>More hacker&#8217;s tools</h3>
<p>Aside from languages and platforms, you&#8217;ll often need auxiliary tools that may be small, simple, cheap, but all the more important since you&#8217;re using them all the time. For editing not only scripts, but even short CSV lists I use <a href="https://notepad-plus-plus.org/" target="_blank" rel="noopener noreferrer"><strong>Notepad++</strong></a>. For interactive working with R I recommend <a href="https://www.rstudio.com" target="_blank" rel="noopener noreferrer"><strong>RStudio</strong></a>. Very helpful for strategy development is a <strong>file comparison</strong> tool: You often have to compare trade logs of different system variants and check which variant opened which trade a little earlier or later, and which consequences that had. For this I use <a href="http://www.scootersoftware.com/" target="_blank" rel="noopener noreferrer"><strong>Beyond Compare</strong></a>.</p>
<p>Aside from Zorro and R, there&#8217;s also a relatively new system development software that I plan to examine closer at some time in the future, <strong><a href="http://www.tssbsoftware.com/" target="_blank" rel="noopener noreferrer">TSSB</a></strong> for generating and testing bias-free trading systems with advanced machine learning algorithms. David Aronson and Timothy Masters were involved in its development, so it certainly won&#8217;t be as useless as most other &#8220;trade system generating&#8221; software. However, there&#8217;s again a limitation: TSSB can not trade or export, so you can not really use the ingenious systems that you developed with it. Maybe I&#8217;ll find a solution to combine TSSB with Zorro.</p>
<h3>References</h3>
<p><a href="https://www.tiobe.com/tiobe-index/">TIOBE index</a> of top programming languages</p>
<p><a href="http://attractivechaos.github.io/plb/">Speed comparison</a> of programming languages</p>
<hr />
<p><strong>Update (November 2017).</strong> The release of new deep learning packages has made TSSB sort of obsolete. For instance, the H2O package natively supports several ways of features filtering and dimensionality reduction, as well as ensembles, both so far the strength of TSSB. H2O is supported with Zorro&#8217;s <strong>advise</strong> function. Still, the TSSB book by Davin Aronson is a valuable source of methods, approaches, and tips about machine learning for financial prediction.</p>
<p>Download links to the latest versions of Zorro and R are placed on the side bar. A brief tutorial to both Zorro an R is contained in the Zorro manual; a more comprehensive introduction into working with Zorro can be found in the <a href="https://www.createspace.com/7147886" target="_blank" rel="noopener noreferrer">Black Book</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/hackers-tools-zorro-and-r/feed/</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
			</item>
		<item>
		<title>Trend Indicators</title>
		<link>https://financial-hacker.com/trend-delusion-or-reality/</link>
					<comments>https://financial-hacker.com/trend-delusion-or-reality/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Fri, 04 Sep 2015 16:48:13 +0000</pubDate>
				<category><![CDATA[Indicators]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Decycler]]></category>
		<category><![CDATA[Ehlers]]></category>
		<category><![CDATA[Low-Lag]]></category>
		<category><![CDATA[Momentum]]></category>
		<category><![CDATA[Zorro]]></category>
		<guid isPermaLink="false">http://www.lotter.org/hacker/?p=19</guid>

					<description><![CDATA[The most common trade method is &#8216;going with the trend&#8216;. While it&#8217;s not completely clear how one can go with the trend without knowing it beforehand, most traders believe that &#8216;trend&#8217; exists and can be exploited. &#8216;Trend&#8217; is supposed to manifest itself in price curves as a sort of momentum or inertia that continues a price &#8230; <a href="https://financial-hacker.com/trend-delusion-or-reality/" class="more-link">Continue reading<span class="screen-reader-text"> "Trend Indicators"</span></a>]]></description>
										<content:encoded><![CDATA[<p>The most common trade method is &#8216;<strong>going with the trend</strong>&#8216;. While it&#8217;s not completely clear how one can go with the trend without knowing it beforehand, most traders believe that &#8216;trend&#8217; exists and can be exploited. &#8216;Trend&#8217; is supposed to manifest itself in price curves as a sort of <strong>momentum</strong> or <strong>inertia</strong> that continues a price movement once it started. This inertia effect does not appear in random walk curves.<span id="more-19"></span> One can speculate about possible causes of trend, such as:</p>
<ul style="list-style-type: square;">
<li>Information spreads slowly, thus producing a delayed, prolonged reaction and price movement. (There are examples where it took the majority of traders <strong>more than a year</strong> to become aware of essential, fundamental information about a certain market!)</li>
<li>Events trigger other events with a similar effect on the price, causing a sort of avalanche effect.</li>
<li>Traders see the price move, shout &#8220;Ah! Trend!&#8221; and jump onto the bandwagon, thus creating a self fulfilling prophecy.</li>
<li>Trade algorithms detect a trend, attempt to exploit it and amplify it this way.</li>
<li>All of this, but maybe on different time scales.</li>
</ul>
<p>Whatever the cause, hackers prefer experiment over speculation, so let&#8217;s test once and for all if trend in price curves really exists and can be exploited in an algorithmic strategy. Exploiting trend obviously means buying at the begin of a trend, and selling at the end. For this, we simply assume that trend begins at the bottom of a price curve valley and ends at a peak, or vice versa. Obviously this assumption makes no difference between &#8216;real&#8217; trends and random price fluctuations. Such a difference could anyway only be determined in hindsight. However, trade profits and losses by random fluctuations should cancel out each other in the long run, at least when trade costs are disregarded. When trends exist in price curves, this method should produce an overall profit from the the remaining trades that are triggered by real trends and last longer than in random walk curves. And hopefully this profit will exceed the costs of the random trades. At least &#8211; that&#8217;s the theory. So we&#8217;re just looking for peaks and valleys of the price curve. The script of the trend following experiment would look like this (all scripts here are in C for the <a href="http://www.financial-hacker.com/hackers-tools-zorro-and-r/">Zorro</a> platform; <strong>var</strong> is typedef&#8217;d to <strong>double</strong>):</p>
<pre>void run()
{
  var *Price = series(price());
  var *Smoothed = series(Filter(Price,Period));
  
  if(valley(Smoothed))
    enterLong();
  else if(peak(Smoothed))
    enterShort();
}</pre>
<p>This strategy is simple enough. It is basically the first strategy from the <a href="http://manual.zorro-trader.com/tutorial_var.htm" target="_blank" rel="noopener noreferrer">Zorro tutorial</a>. The <strong>valley</strong> function returns <strong>true</strong> when the last price was below the current price and also below the last-but-one price; the <strong>peak</strong> function returns <strong>true</strong> when the last price was above the current and the last-but-one. Trades are thus entered at all peaks and valleys and closed by reversal only. For not getting too many random trades and too high trade costs, we&#8217;re removing the high frequencies from the price curve with some smoothing indicator, named <strong>Filter</strong> in the code above. Trend, after all, is supposed to be longer-lasting and should manifest itself in the lower frequencies. This is an example trade produced by this system: <a href="http://www.financial-hacker.com/wp-content/uploads/2015/09/work4_detail.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-195" src="http://www.financial-hacker.com/wp-content/uploads/2015/09/work4_detail.png" alt="work4_detail" width="680" height="321" srcset="https://financial-hacker.com/wp-content/uploads/2015/09/work4_detail.png 680w, https://financial-hacker.com/wp-content/uploads/2015/09/work4_detail-300x142.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a> The black jagged line in the chart above is the raw price curve, the red line is the filtered curve. You can see that it lags behind the black curve a little, which is typical of smoothing indicators. It has a peak at the end of September and thus entered a short trade (tiny green dot). The red line continues going down all the way until November 23, when a valley was reached. A long trade (not shown in this chart) was then entered and the short trade was closed by reversal (other tiny green dot). The green straight line connects the entry and exit points of the trade. It was open almost 2 months and made in that time a profit of ~ 13 cents per unit, or 1300 pips.</p>
<p>The only remaining question is &#8211; which indicator shall we use for filtering out the high frequencies, the ripples and jaggies, from the price curve? We&#8217;re spoilt for choice.</p>
<h3><strong>The Smoothing Candidates</strong></h3>
<p>Smoothing a curve in some way is a common task of all trend strategies. Consequently, there&#8217;s a multitude of smoothing, averaging, low-lag and spectral filter indicators at our disposal. We have to test them. The following candidates were selected for the experiment, traditional indicators as well as fancier algorithms:</p>
<ul>
<li><strong>SMA</strong>, the simple moving average, the sum of the last <strong>n</strong> prices divided by <strong>n</strong>.</li>
<li><strong>EMA</strong>, exponential moving average, the current price multiplied with a small factor plus the last EMA multiplied with a large factor. The sum of both factors must be <strong>1</strong>. This is a first order lowpass filter.</li>
<li><strong>LowPass</strong>, a second order lowpass filter with the following source code:
<pre>var LowPass(var *Data,int Period)
{
  var* LP = series(Data[0]);
  var a = 2.0/(1+Period);
  return LP[0] = (a-0.25*a*a)*Data[0]
    + 0.5*a*a*Data[1]
    - (a-0.75*a*a)*Data[2]
    + 2*(1.-a)*LP[1]
    - (1.-a)*(1.-a)*LP[2];
}</pre>
</li>
<li><strong>HMA</strong>, the Hull Moving Average, with the following source code:
<pre>var HMA(var *Data,int Period)
{
  return WMA(series(2*WMA(Data,Period/2)-WMA(Data,Period),sqrt(Period))
}</pre>
</li>
<li><strong>ZMA</strong>, Ehler&#8217;s Zero-Lag Moving Average, an EMA with a correction term for removing lag. This is the source code:
<pre>var ZMA(var *Data,int Period)
{
  var *ZMA = series(Data[0]);
  var a = 2.0/(1+Period);
  var Ema = EMA(Data,Period);
  var Error = 1000000;
  var Gain, GainLimit=5, BestGain=0;
  for(Gain = -GainLimit; Gain &lt; GainLimit; Gain += 0.1) {
     ZMA[0] = a*(Ema + Gain*(Data[0]-ZMA[1])) + (1-a)*ZMA[1];
     var NewError = Data[0] - ZMA[0];
     if(abs(Error) &lt; newError) {
       Error = abs(newError);
       BestGain = Gain;
     }
  }
  return ZMA[0] = a*(Ema + BestGain*(Data[0]-ZMA[1])) + (1-a)*ZMA[1];
}</pre>
</li>
<li><strong>ALMA</strong>, Arnaud Legoux Moving Average, based on a shifted Gaussian distribution (described in <a href="http://www.forexfactory.com/attachment.php?attachmentid=1123528&amp;d=1359078631" target="_blank" rel="noopener noreferrer">this paper</a>):
<pre>var ALMA(var *Data, int Period)
{
  var m = floor(0.85*(Period-1));
  var s = Period/6.0;
  var alma = 0., wSum = 0.;
  int i;
  for (i = 0; i &lt; Period; i++) {
    var w = exp(-(i-m)*(i-m)/(2*s*s));
    alma += Data[Period-1-i] * w;
    wSum += w;
  }
  return alma / wSum;
}</pre>
</li>
<li><strong>Laguerre</strong>, a 4-element Laguerre filter:
<pre>var Laguerre(var *Data, var alpha)
{
  var *L = series(Data[0]);
  L[0] = alpha*Data[0] + (1-alpha)*L[1];
  L[2] = -(1-alpha)*L[0] + L[1] + (1-alpha)*L[2+1];
  L[4] = -(1-alpha)*L[2] + L[2+1] + (1-alpha)*L[4+1];
  L[6] = -(1-alpha)*L[4] + L[4+1] + (1-alpha)*L[6+1];
  return (L[0]+2*L[2]+2*L[4]+L[6])/6;
}</pre>
</li>
<li><strong>Linear regression</strong>, fits a straight line between the data points in a way that the distance between each data point and the line is minimized by the least-squares rule.</li>
<li><strong>Smooth</strong>, John Ehlers&#8217; &#8220;Super Smoother&#8221;, a 2-pole Butterworth filter combined with a 2-bar SMA that suppresses the Nyquist frequency:
<pre>var Smooth(var *Data,int Period)
{
  var f = (1.414*PI) / Period;
  var a = exp(-f);
  var c2 = 2*a*cos(f);
  var c3 = -a*a;
  var c1 = 1 - c2 - c3;
  var *S = series(Data[0]);
  return S[0] = c1*(Data[0]+Data[1])*0.5 + c2*S[1] + c3*S[2];
}</pre>
</li>
<li><strong>Decycle</strong>, another low-lag indicator by John Ehlers. His decycler is simply the difference between the price and its fluctuation, retrieved with a highpass filter:
<pre>var Decycle(var* Data,int Period)
{
  return Data[0]-HighPass2(Data,Period);
}</pre>
</li>
</ul>
<p>The above source codes have been taken from the <strong>indicators.c</strong> file of the Zorro platform, which contains source codes of all supplied indicators.</p>
<h3>Comparing Step Responses</h3>
<p>What is the best of all those indicators? For a first impression here&#8217;s a chart showing them reacting on a simulated sudden price step. You can see that some react slow, some very slow, some fast, and some overshoot: <a href="http://www.financial-hacker.com/wp-content/uploads/2015/09/LowLag_EURUSD.png"><img loading="lazy" decoding="async" class="alignnone wp-image-139 size-full" src="http://www.financial-hacker.com/wp-content/uploads/2015/09/LowLag_EURUSD.png" alt="" width="795" height="351" srcset="https://financial-hacker.com/wp-content/uploads/2015/09/LowLag_EURUSD.png 795w, https://financial-hacker.com/wp-content/uploads/2015/09/LowLag_EURUSD-300x132.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a> You can generate such a step response diagram with this Zorro script:</p>
<pre>// compare the step responses of some low-lag MAs
function run()
{
  set(PLOTNOW);
  BarPeriod = 60;
  MaxBars = 1000;
  LookBack = 150;
  asset("");   // don't load an asset
  ColorUp = ColorDn = 0;  // don't plot a price curve
  PlotWidth = 800;
  PlotHeight1 = 400;

  var *Impulse = series(ifelse(Bar&gt;200 &amp;&amp; Bar&lt;400,1,0)); // 0-&gt;1 impulse
  int Period = 50;
  plot("Impulse",Impulse[0],0,GREY);
  plot("SMA",SMA(Impulse,Period),0,BLACK);
  plot("EMA",EMA(Impulse,Period),0,0x808000);
  plot("ALMA",ALMA(Impulse,Period),0,0x008000);
  plot("Laguerre",Laguerre(Impulse,4.0/Period),0,0x800000);
  plot("Hull MA",HMA(Impulse,Period),0,0x00FF00);
  plot("Zero-Lag MA",ZMA(Impulse,Period),0,0x00FFFF); 
  plot("Decycle",Decycle(Impulse,Period),0,0xFF00FF);
  plot("LowPass",LowPass(Impulse,Period),0,0xFF0000);
  plot("Smooth",Smooth(Impulse,Period),0,0x0000FF);
}</pre>
<p>We can see that from all the indicators, the <strong>ALMA</strong> seems to be the best representation of the step, while the <strong>ZMA</strong> produces the fastest response with no overshoot, the <strong>Decycler</strong> the fastest with some overshoot, and <strong>Laguerre</strong> lags a lot behind anything else. Obviously, all this has not much meaning because the time period parameters of the indicators are not really comparable. So the step response per se does not reveal if the indicator is well suited for trend detection. We have no choice: We must use them all.</p>
<h3>The Trend Experiment</h3>
<p>For the experiment, all smoothing indicators above will be applied to a currency, a stock index, and a commodity, and will compete in exploiting trend. Because different time frames can represent different trader groups and thus different markets, the indicators will be applied to price curves made of 15-minutes, 1-hour, and 4-hours bars. And we&#8217;ll also try different indicator time periods in 10 steps from 10 to 10000 bars.</p>
<p>So we&#8217;ll have to program 10 indicators * 3 assets * 3 bar sizes * 10 time periods = 900 systems. Some of the 900 results will be positive, some negative, and some zero. If there are no significant positive results, we&#8217;ll have to conclude that trend in price curves either does not exist, or can at least not be exploited with this all-too-obvious method. However we&#8217;ll likely get some winning systems, if only for statistical reasons.</p>
<p>The next step will be checking if their profits are for real or just caused by a statistical effect dubbed <strong>Data Mining Bias</strong>. There is a method to measure Data Mining Bias from the resulting equity curves: the notorious <strong>White&#8217;s Reality Check</strong>. We&#8217;ll apply that check to the results of our experiment. If some systems survive White&#8217;s Reality Check, we&#8217;ll have the once-and-for-all proof that markets are ineffective, trends really exist, and algorithmic trend trading works.</p>
<p><a href="http://www.financial-hacker.com/trend-and-exploiting-it/">Next Step</a>&#8230;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/trend-delusion-or-reality/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
	</channel>
</rss>
