<?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>jcl &#8211; The Financial Hacker</title>
	<atom:link href="https://financial-hacker.com/author/jcl/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>jcl &#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>The Digital River Mystery</title>
		<link>https://financial-hacker.com/the-digital-river-mystery/</link>
					<comments>https://financial-hacker.com/the-digital-river-mystery/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Wed, 23 Oct 2024 10:57:47 +0000</pubDate>
				<category><![CDATA[No Math]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4751</guid>

					<description><![CDATA[Digital River was a popular eCommerce service, used by thousands of developers and software companies worldwide to distribute their software. oP group Germany, developers of the Zorro platform, also sold their licenses and subscriptions through Digital River. They have large clients, such as nVidia and Adobe. The first hint that something strange was going on &#8230; <a href="https://financial-hacker.com/the-digital-river-mystery/" class="more-link">Continue reading<span class="screen-reader-text"> "The Digital River Mystery"</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Digital River was a popular eCommerce service, used by thousands of developers and software companies worldwide to distribute their software. oP group Germany, developers of the Zorro platform, also sold their licenses and subscriptions through Digital River. They have large clients, such as nVidia and Adobe. The first hint that something strange was going on with Digital River was an email in July to their clients.<span id="more-4751"></span></p>


<p>They told that they will now charge hefty fees for using their store, for asking support questions, and for paying out. Mentioning the payout, they also told that they will from now on hold back payments for 2 months. Aside from the fact that they cannot legally change conditions in this way without their client&#8217;s consent, emails like that are normally business suicide. Since all competitors offer much better conditions, Digital  River would clearly sooner or later lose all their clients in this way. This email was a mystery. It made only sense under the assumption that Digital River intended to go out of business, but keep as much as their currernt client&#8217;s money as possible by offsetting them with insane fees.  </p>


<p>But Digital River did not hold back payments for 2 months. In November they stopped paying altogether. They did not give explanations. Reminders were answered with meaningless text blocks like this:</p>


<p><em>Please know that we are fully aware of the situation and are working diligently to resolve these issues as quickly as possible. Our team is investigating the cause of these delays to ensure they address them effectively and prevent such occurrences. We understand how important these payments are for you and your business. We are committed to ensuring that all outstanding payments are processed and that our communication with you is clear and timely moving forward. We appreciate your long-standing partnership and your trust in us over the years. Rest assured we are taking your concerns very seriously and trying to rectify this situation.</em>&#8220;</p>


<p>There is a lot of speculation about what is behind it. Some believe that Digital River ran in liquidity problems, and originally intended to still pay, although later and fewer. The legality of this is disputable, but it does not yet constitute obvious fraud. However, most clients now assume that they prepared an exit fraud with the intention to keep all their client&#8217;s sales. In that case the mysterious email had just the purpose to delay legal action.</p>


<p>On their website, Digital River gives no hint of any trouble, and continues to run the stores and charge the customer&#8217;s credit cards as if nothing happened. The only thing certain is that clients are now hurrying to switch to other eCommerce providers, such as PayPro Global or Paddle, and that their last three months earnings are possibly gone. Unless some part of if can be recovered by lawsuits or criminal proceedings.</p>
<p>Since most Zorro S license subscribers run their subscriptions through Digital River, oP group has activated a fallback server for verifying subscription tokens. So all subscriptions will remain valid until renewed with the new online store provider, PayPro Global. If you have recently purchased a product from Digital River, better cancel the charge on your credit card or request a refund. At least in some cases, it was reported that refunds were indeed paid.  </p>
<p>More details: <a href="https://www.theregister.com/2024/10/15/digital_river_runs_dry_hasnt" target="_blank" rel="noopener">Digital_river_runs_dry</a> | <a href="https://www.heise.de/en/news/Digital-River-Missing-payments-and-evasive-communication-9992490.html" target="_blank" rel="noopener">Missing payments and evasive communication</a></p>

]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/the-digital-river-mystery/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Trading with REST</title>
		<link>https://financial-hacker.com/crypto-trading-with-rest-part-1/</link>
					<comments>https://financial-hacker.com/crypto-trading-with-rest-part-1/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Mon, 17 Oct 2022 11:16:41 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Bittrex]]></category>
		<category><![CDATA[Broker]]></category>
		<category><![CDATA[Hacking]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4517</guid>

					<description><![CDATA[Many brokers and exchanges can nowadays be accessed online with a REST API that communicates with plain-text HTTP requests. The days of awkward proprietary broker APIs are coming to an end. This article is a step by step instruction of implementating a REST API interface in C for connecting a trading system to the Bittrex &#8230; <a href="https://financial-hacker.com/crypto-trading-with-rest-part-1/" class="more-link">Continue reading<span class="screen-reader-text"> "Trading with REST"</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Many brokers and exchanges can nowadays be accessed online with a REST API that communicates with plain-text HTTP requests. The days of <a href="https://financial-hacker.com/dear-brokers/" target="_blank" rel="noopener">awkward proprietary broker APIs</a> are coming to an end. This article is a step by step instruction of implementating a REST API interface in C for connecting a trading system to the <a href="https://global.bittrex.com/" target="_blank" rel="noopener">Bittrex cryptocurrency exchange.</a> It&#8217;s for the <a href="https://zorro-project.com" target="_blank" rel="noopener">Zorro platform</a>, but the principles are also valid for other exchanges and platforms. The C code for a basic REST API implementation is relatively short and straightforward. <span id="more-4517"></span></p>
<p> For connecting the Zorro platform to a particular broker API, a DLL must be dropped in its Plugin folder. The DLL is then automatically recognized and appears in Zorro&#8217;s Broker selection box. For trading with the broker, the DLL exports functions for getting prices and sending orders. These functions are standardized and described in the <a href="https://zorro-project.com/manual/en/brokerplugin.htm" target="_blank" rel="noopener">Zorro manual</a>. They are the same for all brokers. The following 4 functions are the most important:</p>
<p><strong>BrokerOpen</strong> &#8211; identify the DLL.<br /><strong>BrokerLogin</strong> &#8211; initialize and store login credentials.<br /><strong>BrokerAsset</strong> &#8211; retrieve price and other parameters of an asset.<br /><strong>BrokerBuy2</strong> &#8211; send a buy or sell order.</p>
<p>These four are sufficient for running most trading strategies. The DLL can export additional functions that are useful, but not mandatory, since Zorro works around them when they are not implemented:</p>
<p><strong>BrokerAccount</strong> -get the account state.<br /><strong>BrokerTrade</strong> &#8211; get the trade or order state.<br /><strong>BrokerHistory2</strong> -get price history.<br /><strong>BrokerCommand</strong> &#8211; set special modes, get order book, etc.</p>
<p>Zorro users have written DLLs for several broker APIs, but the code is often redundant and invents the wheel many times again. I&#8217;ll give here an example of a relatively lean broker DLL that can be used as template for individual REST API implementations. Bittrex is a US based digital currency exchange that supports several hundred crypto currencies and provides free API access. We&#8217;re first going to implement the 4 mandatory functions, following the API description on the Bittrex website:</p>
<p><a href="https://bittrex.github.io/api/v3" target="_blank" rel="noopener">https://bittrex.github.io/api/v3</a></p>
<p>We will use the free Visual C++ Community Edition from Microsoft. Aside from the exported functions, we need some internal functions to print messages, send HTTP requests, parse a JSON response, and generate a digital signature. For all this there&#8217;s ready code available on the Internet, but there are also ready functions in Zorro&#8217;s library. To make life easier, we simply import the <a href="https://zorro-project.com/manual/en/funclist.htm" target="_blank" rel="noopener">Zorro function library</a> to the DLL. The VC++ setup for generating such a DLL is described here:</p>
<p><a href="https://zorro-project.com/manual/en/dlls.htm#project" target="_blank" rel="noopener">https://zorro-project.com/manual/en/dlls.htm</a></p>
<p>The setup is for a C++ trading strategy, but works as well for a broker API DLL. First we&#8217;re going to implement the adminstrative stuff, the <strong>BrokerOpen</strong> and <strong>BrokerLogin</strong> functions:</p>
<pre class="prettyprint">#define PLUGIN_TYPE 2<br />#define PLUGIN_NAME "Bittrex V3"<br />#define DLLFUNC extern "C" __declspec(dllexport)<br /><br />int (__cdecl *BrokerMessage)(const char *Text);<br />int (__cdecl *BrokerProgress)(const int Progress);<br />...<br /><br />DLLFUNC int BrokerOpen(char* Name,FARPROC fpMessage,FARPROC fpProgress)<br />{<br />  strcpy_s(Name,32,PLUGIN_NAME);<br />  (FARPROC&amp;)BrokerMessage = fpMessage;<br />  (FARPROC&amp;)BrokerProgress = fpProgress;<br />  return PLUGIN_TYPE;<br />}</pre>
<p>The <strong>BrokerOpen</strong> function is Zorro specific. It sets up two function pointers for printing message and sending heartbeats to Zorro. It&#8217;s needed for recognizing the DLL in the <strong>Plugin</strong> folder and letting the plugin name, &#8220;Bittrex V3&#8221;, appear in the broker scrollbox. </p>
<p>Next we need the login function that&#8217;s called at the begin and the end of any algo trading session</p>
<pre class="prettyprint">struct GLOBAL {<br />  int PriceType,VolType,OrderType;<br />  double Unit; // smallest trade unit<br />  char Path[256]; // send path buffer<br />  char Key[256],Secret[256]; // credentials<br />  char Symbol[64],Uuid[256]; // last trade symbol and UUID<br />  char AccountId[16]; // account currency<br />} G; // parameter singleton<br />...<br /><br />DLLFUNC int BrokerLogin(char* User,char* Pwd,char* Type,char* Accounts)<br />{<br />  if(User) { // login<br />    memset(&amp;G,0,sizeof(G));<br />    strcpy_s(G.Key,User);<br />    strcpy_s(G.Secret,Pwd);<br />    return 1;<br />  } else  // logout<br />    return 0;<br />}</pre>
<p>This function only sets up the <strong>G</strong> struct, a singleton that holds all global variables of the DLL. The <strong>User</strong> and <strong>Pwd</strong> arguments contain the Bittrex key and secret. They are taken from the Zorro login fields or from the account list. <strong>Type</strong> is the account type, ignored here because Bittrex has no demo accounts.  <strong>Account</strong> is the account identifier and also ignored since we&#8217;re not using sub-accounts.</p>
<p>Next comes the function to retrieve prices and other parameters of a particular cryptocurrency. It&#8217;s a bit more complex and requires a HTTP request to the API. Some requests require authentication, some not. For all this we first implement a <strong>send()</strong> function in the DLL that uses Zorro&#8217;s functions for sending <a href="https://zorro-project.com/manual/en/http.htm" target="_blank" rel="noopener">http requests</a> and generating a <a href="https://zorro-project.com/manual/en/hmac.htm" target="_blank" rel="noopener">HMAC signature</a>. The authentication method by the Bittrex REST API V3 is a bit complex:</p>
<p><em>To properly sign an authenticated request for the Bittrex v3 API, the following headers must be included: Api-Key, Api-Timestamp, Api-Content-Hash, Api-Signature. <span style="font-size: revert;">Api-Timestamp is </span>the current time as a UNIX timestamp in epoch-millisecond format. <span style="font-size: revert;">Api-Content-Hash </span>is a SHA512 hash of the request body, Hex-encoded (with no request body, a SHA512 hash of an empty string). For creating the Api-Signature, first generate a string by concatenating the following items: Contents of the Api-Timestamp header; the full URI used to make the request, including query string; the HTTP method of the request, in all caps (GET, POST, DELETE, etc.); Contents of the Api-Content-Hash header. Sign this string via HmacSHA512, using the API secret as the signing secret. Hex-encode the result and populate the Api-Signature header with it.</em></p>
<p>This is the implementation:</p>
<pre class="prettyprint">#define RHEADER "https://api.bittrex.com/v3/"<br />...<br /><br />int sleep(int ms)<br />{<br />  Sleep(ms); <br />  return BrokerProgress(0);<br />}<br /><br />char* send(const char* Url,<br />  int Mode = 0,<br />  const char* Method = NULL,<br />  const char* Body = NULL)
{
  static char Url[1024], Header[2048], Signature[1024],
    Buffer1[1024*1024], Buffer2[2048];
  *Signature = *Header = 0;
  sprintf_s(Url,"%s%s",RHEADER,Url);
  if (Mode &amp; 1) { // Authentication required
    strcpy_s(Header, "Content-Type:application/json");
    strcat_s(Header, "\nAccept:application/json");
    strcat_s(Header, "\nApi-Key: ");
    strcat_s(Header,G.Key);
    strcat_s(Header, "\nApi-Timestamp: ");
    __time64_t Time; _time64(&amp;Time);
    static __time64_t Offset = 0;
    char* TimeStamp = i64toa(Time*1000 + Offset++); 
    strcat_s(Header, TimeStamp);
    strcat_s(Header, "\nApi-Content-Hash: ");
    char* Hash = hmac(Body, 0, 0, 512);
    strcat_s(Header,Hash);
    strcpy_s(Signature, TimeStamp);
    strcat_s(Signature, Url);
    if(Method &amp;&amp; *Method)
      strcat_s(Signature, Method);
    else if(!Body)
      strcat_s(Signature,"GET");
    else
      strcat_s(Signature,"POST");
    strcat_s(Signature, Hash);
    strcat_s(Header, "\nApi-Signature: ");
    strcat_s(Header, hmac(Signature, 0, G.Secret, 512));
  }

  char* Response = Mode &amp; 2? Buffer2 : Buffer1;<br />  int MaxSize = Mode &amp; 2? sizeof(Buffer2) : sizeof(Buffer1);<br />  int Id = http_request(Url,Body,Header,Method);
  if(!Id) goto send_error;
// wait 30 seconds for the server to reply
  int Size = 0, Wait = 3000;  
  while (!(Size = http_status(Id)) &amp;&amp; --Wait &gt; 0)
    if(!sleep(10)) goto send_error;
  if (!Size) goto send_error;
  if(!http_result(Id,Response,MaxSize)) goto send_error;
  Response[MaxSize-1] = 0; // prevent buffer overrun
  http_free(Id);
  return Response;
<br />// transfer unsuccessful?
send_error:
  if(Id) http_free(Id);
  return NULL;
}
</pre>
<p>The above code adds an authentication header with signature when <strong>Mode</strong> == 1. <strong>Mode == 2</strong> selects a second, smaller response buffer and thus allows to evaluate two API responses at the same time. The <strong>sleep</strong> function generates a delay with a heartbeat to keep the Zorro window responsive during long requests. If it returns <strong>0</strong>, someone has hit Zorro&#8217;s [Stop] key and all operations should be aborted. The Windows <strong>_time64</strong> function has only 1-second resolution, so we add an incremented <strong>Offset</strong> for generating unique timestamps.</p>
<p>We&#8217;re now prepared to implement the <strong>BrokerAsset</strong> function:</p>
<pre class="prettyprint">double fixAmount(double Value)<br />{<br />  int Exp = log10(Value);<br />  if (Exp &gt;= 0) Exp++;<br />  return pow(10,Exp);<br />}<br /><br />DLLFUNC int BrokerAsset(char* Symbol,double* pPrice,double* pSpread,<br />double *pVolume, double *pPip, double *pPipCost, double *pMinAmount,<br />double *pMargin, double *pRollLong, double *pRollShort, double *pCommission)<br />{<br />  sprintf_s(G.Url,"markets/%s/ticker",fixSymbol(Symbol));<br />  char* Response = send(G.Url,2);<br />  if(!Response) return 0;<br />  double Bid = strvar(Response, "bidRate", 0.),<br />    Ask = strvar(Response,"askRate",0.);<br />  if (Ask &gt; 0. Bid &gt; 0. &amp;&amp; pSpread) <br />    *pSpread = Ask - Bid;<br />  double Last = strvar(Response, "lastTradeRate", 0.);<br />  if(Ask == 0. || G.PriceType == 2) <br />    Ask = Last;<br />  if (Ask == 0.) return 0; // symbol does not exist<br />  if(pPrice) *pPrice = Ask;<br />  if(pVolume) {<br />    sprintf_s(G.Url,"markets/%s/summary",fixSymbol(Symbol));<br />    Response = send(G.Url,2);<br />    if (Response) {<br />      if (G.VolType == 4)<br />        *pVolume = strvar(Response, "volume", 0);<br />    else<br />        *pVolume = strvar(Response, "quoteVolume", 0);<br />    }<br />  }<br />  if (pMinAmount) { // get lot amount<br />    sprintf_s(G.Url,"markets/%s",fixSymbol(Symbol));<br />    Response = send(G.Url,2);<br />    if (Response) {<br />      *pMinAmount = fixAmount(strvar(Response,"minTradeSize",0.000001));<br />      if (pPip) {<br />        int Exp = strvar(Response,"precision",8);<br />        *pPip = pow(10,-Exp); <br />        while (*pPip * *pMinAmount &lt; 0.000000001)<br />         *pPip *= 10; // avoid too small pip cost<br />        if (pPipCost)<br />          *pPipCost = *pPip * *pMinAmount;<br />      }<br />    }<br />  }<br />  if (pMargin) <br />    *pMargin = -100; // no leverage<br />  return 1;<br />} </pre>
<p>This function is supposed to return current price, current ask-bid spread, and current volume. It can also optionally request other asset specific parameters when available from the API. Otherwise Zorro will replace them with parameter values from the asset list. Broker APIs rarely provide all requested parameters. Make sure to only calculate and fill a parameter when its pointer passed to the function is nonzero. Most of the pointers are NULL most of the time.</p>
<p>The <strong>send</strong> function uses the second buffer because we&#8217;ll need price requests internally for calculating the account state. For getting lot amount, pip size, and pip cost, two more API requests are needed. The values from the response string are parsed with Zorro&#8217;s <strong>strvar</strong> function. The <strong>fixAmount</strong> function converts a value to its next-higher power of 10 &#8211; for instance, 7 is converted to 10 and 0.07 to 0.1. We&#8217;re doing this because we don&#8217;t want a strange number for the lot amount. The pip size is calculated from the precision, but we prevent it from going too small. Bittrex has no leverage, so the margin cost is always 100%.    </p>
<p>The next and final function sends an order to the API:</p>
<pre class="prettyprint">DLLFUNC int BrokerBuy2(char* Symbol,int Volume,double StopDist,double Limit,double *pPrice,int *pFill)<br />{<br />  if(!isConnected() || !Volume) return 0;<br /><br />// compose the body<br />  char Body[256] = "{\n";<br />  strcat_s(Body,"\"marketsymbol\": \"");<br />  strcat_s(Body,fixSymbol(Symbol));<br />  strcat_s(Body,"\",\n\"direction\": \"");<br />  strcat_s(Body,Volume &gt; 0? "BUY" : "SELL");<br />  strcat_s(Body,"\",\n\"type\": \"");<br />  strcat_s(Body,Limit &gt; 0. ? "LIMIT" : "MARKET");<br />  strcat_s(Body,"\",\n\"quantity\": \"");<br />  double Size = labs(Volume);<br />  if(G.Amount &lt; 1.) Size *= G.Amount;<br />  strcat_s(Body,ftoa(Size));<br />  if (Limit &gt; 0.) {<br />    strcat_s(Body,"\",\n\"limit\": \"");<br />    strcat_s(Body,ftoa(Limit));<br />  }<br />  strcat_s(Body,"\",\n\"timeInForce\": \"");<br />  if ((G.OrderType&amp;2) &amp;&amp; Limit &gt; 0.) <br />    strcat_s(Body,"GOOD_TIL_CANCELLED"); // limit orders only<br />  else if (G.OrderType&amp;1) <br />    strcat_s(Body,"FILL_OR_KILL"); // fill all or nothing<br />  else <br />    strcat_s(Body,"IMMEDIATE_OR_CANCEL");<br />  strcat_s(Body,"\"\n}");<br /><br />  char* Response = send("orders",1,0,Body);<br />  if(!Response) return 0;<br /><br />  char* Uuid = strtext(Response,"id","");<br />  if(!*Uuid) return 0; // failed<br />  strcpy(G.Uuid,Uuid);<br />  double Filled = strvar(Response,"fillQuantity",0);<br />  if(Filled == 0. &amp;&amp; !(G.OrderType&amp;2))<br />    return 0; // unfilled FOK/IOC order<br />  double Price = strvar(Response,"proceeds",0);<br />  if (Filled &gt; 0. &amp;&amp; Price &gt; 0. &amp;&amp; pPrice)<br />    *pPrice = Price/Filled;<br />  if (*pFill) *pFill = Filled/min(1.,G.Unit);<br />  return -1; <br />}</pre>
<p>The function first composes a message body in this JSON format (example):</p>
<pre>{<br /><span class="hljs-attr">  "marketSymbol"</span>: <span class="hljs-string">"ETH/BTC"</span>,<br /><span class="hljs-attr">  "direction"</span>: <span class="hljs-string">"BUY"</span>,<br /><span class="hljs-attr">  "type"</span>: <span class="hljs-string">"LIMIT"</span>,<br /><span class="hljs-attr">  "quantity"</span>: <span class="hljs-string">"0.1"</span>,<br /><span class="hljs-attr">  "limit"</span>: "0.008<span class="hljs-string">"</span>,<br /><span class="hljs-attr">  "timeInForce"</span>: "IMMEDIATE_OR_CANCEL<span class="hljs-string">"</span><br />}</pre>
<p>If the order is accepted, the response has this JSON format:</p>
<pre>{<br />  "id": "12345-6789-007-4711",<br />  "marketSymbol": "ETH/BTC",<br />  "direction": "BUY",<br />  "type": "LIMIT",<br />  "quantity": "0.1",<br />  "limit": "0.008",<br />  "timeInForce": "IMMEDIATE_OR_CANCEL",<br />  "fillQuantity": "0.05",<br />  "commission": "0.000002",<br />  "proceeds": "0.00001",<br />  "status": "<span class="json-property-enum" title="Possible values"><span class="json-property-enum-item">CLOSED</span></span>"<br />}</pre>
<p>The relevant fields, especially the id, the fill amount, and the fill price, are parsed from the response and returned. The return value <strong>-1</strong> indicates to Zorro that the order generated no identifer number, but an UUID. It was stored and can be retrieved with a subsequent command. <strong>G.Unit </strong>is the lot amount that was generated with the previous <strong>BrokerAsset</strong> call. </p>
<p>The remaining functions not described here &#8211; <strong>BrokerTrade</strong>, <strong>BrokerAccount</strong>, <strong>BrokerHistory2</strong>, and <strong>BrokerCommand</strong> &#8211;  are implemented in a similar way. You can find them in the full source code in the <strong>Source</strong> folder of the latest Zorro version. </p>
<p><strong>Update, November 2023:</strong> Bittrex recently announced that they will terminate their operation. So the Bittrex API plugin described herein lost its purpose, but you can still use the code as a template for connecting Zorro to any other broker or crypto exchange APIs &#8211; at least as long as they remain operational.  </p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/crypto-trading-with-rest-part-1/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>Why 90% of Backtests Fail</title>
		<link>https://financial-hacker.com/why-90-of-backtests-fail/</link>
					<comments>https://financial-hacker.com/why-90-of-backtests-fail/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Mon, 04 Apr 2022 15:55:47 +0000</pubDate>
				<category><![CDATA[System Development]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Backtest]]></category>
		<category><![CDATA[Montecarlo Methods]]></category>
		<category><![CDATA[SPY]]></category>
		<category><![CDATA[Walk forward analysis]]></category>
		<category><![CDATA[White's reality check]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4373</guid>

					<description><![CDATA[About 9 out of 10 backtests produce wrong or misleading results. This is the number one reason why carefully developed algorithmic trading systems often fail in live trading. Even with out-of-sample data and even with cross-validation or walk-forward analysis, backtest results are often way off to the optimistic side. The majority of trading systems with &#8230; <a href="https://financial-hacker.com/why-90-of-backtests-fail/" class="more-link">Continue reading<span class="screen-reader-text"> "Why 90% of Backtests Fail"</span></a>]]></description>
										<content:encoded><![CDATA[<p>About 9 out of 10 backtests produce wrong or misleading results. This is the number one reason why carefully developed algorithmic trading systems often fail in live trading. Even with out-of-sample data and even with cross-validation or walk-forward analysis, backtest results are often way off to the optimistic side. The majority of trading systems with a positive backtest are in fact unprofitable. In this article I&#8217;ll discuss the cause of this phenomenon, and how to fix it.<span id="more-4373"></span></p>
<p>Suppose you&#8217;re developing an <a href="https://zorro-project.com/algotrading.php" target="_blank" rel="noopener">algorithmic trading strategy</a>, following all rules of proper <a href="https://financial-hacker.com/build-better-strategies-part-3-the-development-process/">system development</a>. But you are not aware that your trading algorithm has no statistical edge. The strategy is worthless, the trading rules equivalent to random trading, the profit expectancy – aside from transaction costs – is zero. The problem: you will rarely get a zero result in a backtest. A random trading strategy will in 50% of cases produce a negative backtest result, in 50% a positive result. But if the result is negative, you&#8217;re normally tempted to tweak the code or select assets and time frames until you finally got a profitable backtest. Which will happen relatively soon even when applying random modifications to the system. That&#8217;s why there are so many unprofitable strategies around, with nevertheless great backtest performances.</p>
<p>Does this mean that backtests are worthless? Not at all. But it is essential to know whether you can trust the test, or not.</p>
<h3><strong>The test-the-backtest experiment<br />
</strong></h3>
<p>There are several methods for verifying a backtest. None of them is perfect, but all give insights from different viewpoints. We&#8217;ll use the <a href="https://zorro-project.com" target="_blank" rel="noopener">Zorro algo trading software</a>, and run our experiments with the following test system that is optimized and backtested with walk-forward analysis:</p>
<pre class="prettyprint">function run()
{
  set(PARAMETERS,TESTNOW,PLOTNOW,LOGFILE);
  BarPeriod = 1440;
  LookBack = 100;
  StartDate = 2012;
  NumWFOCycles = 10;

  assetList("AssetsIB");
  asset("SPY");

  vars Signals = series(LowPass(seriesC(),optimize(10,2,20,2)));
  vars MMIFast = series(MMI(seriesC(),optimize(50,40,60,5)));
  vars MMISlow = series(LowPass(MMIFast,100));

  MaxLong = 1;
  if(falling(MMISlow)) {
    if(valley(Signals))
      enterLong();
    else if(peak(Signals))
      exitLong();
  }
}</pre>
<p>This is a classic trend following algorithm. It uses a lowpass filter for trading at the peaks and valleys of the smoothed price curve, and a MMI filter (<a href="https://financial-hacker.com/the-market-meanness-index/">Market Meanness Index</a>) for distinguishing trending from non-trending market periods. It only trades when the market has switched to rend regime, which is essential for profitable trend following systems. It opens only long positions. Lowpass and MMI filter periods are <a href="https://zorro-project.com/manual/en/optimize.htm" target="_blank" rel="noopener">optimized</a>, and the backtest is a <a href="https://zorro-project.com/manual/en/numwfocycles.htm" target="_blank" rel="noopener">walk-forward analysis</a> with 10 cycles.</p>
<h3><strong>The placebo trading system<br />
</strong></h3>
<p>It is standard for experiments to compare the real stuff with a placebo. For this we&#8217;re using a trading system that has obviously no edge, but was tweaked with the evil intention to appear profitable in a walk-forward analysis. This is our placebo system:</p>
<pre class="prettyprint">void run()
{
  set(PARAMETERS,TESTNOW,PLOTNOW,LOGFILE);
  BarPeriod = 1440;
  StartDate = 2012;
  setf(TrainMode,BRUTE);
  NumWFOCycles = 9;

  assetList("AssetsIB");
  asset("SPY");

  int Pause = optimize(5,1,15,1);
  LifeTime = optimize(5,1,15,1);

// trade after a pause...
  static int NextEntry;
  if(Init) NextEntry = 0;
  if(NextEntry-- &lt;= 0) {
    NextEntry = LifeTime+Pause;
    enterLong();
  }
}</pre>
<p>This system opens a position, keeps it a while, then closes it and pauses for a while. The trade and pause durations are walk-forward optimized between 1 day and 3 weeks. <a href="https://zorro-project.com/manual/en/timewait.ht" target="_blank" rel="noopener">LifeTime</a> is a predefined variable that closes the position after the given time. If you don&#8217;t believe in lucky trade patterns, you can rightfully assume that this system is equivalent to random trading. Let&#8217;s see how it fares in comparison to the trend trading system.</p>
<h3><strong>Trend trading vs. placebo trading<br />
</strong></h3>
<p>This is the equity curve with the trend trading system from a walk forward analysis from 2012 up to 3/2022:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2022/04/040422_1441_Why90ofBack1.png" alt="" /></p>
<p>The plot begins 2015 because the preceding 3 years are used for the training and lookback periods. SPY follows the S&amp;P500 index and rises in the long term, so we could expect anyway some profit with a long-only system. But this system, with profit factor 3 and R2 coefficient 0.65 appears a lot better than random trading. Let&#8217;s compare it with the placebo system:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2022/04/040422_1441_Why90ofBack2.png" alt="" /></p>
<p>The placebo system produced profit factor 2 and R2 coefficient 0.77. Slightly less than the real system, but in the same performance range. And this result was also from a walk-forward analysis, although with 9 cycles &#8211; therefore the later start of the test period. Aside from that, it seems impossible to determine solely from the equity curve and performance data which system is for real, and which is a placebo.</p>
<h3><strong>Checking the reality<br />
</strong></h3>
<p>Methods to verify backtest results are named &#8216;reality check&#8217;. They are specific to the asset and algorithm; in a multi-asset, multi-algo portfolio, you need to enable only the component you want to test. Let&#8217;s first see how the WFO split affects the backtest. In this way we can find out whether our backtest result was just due to lucky trading in a particular WFO cycle. We&#8217;re going to plot a <strong>WFO profile</strong> that displays the effect of the number of walk-forward cycles on the result. For this we outcomment the <strong>NumWFOCycles = …</strong> line in the code, and run it in training mode with the <strong>WFOProfile.c</strong> script:</p>
<pre class="prettyprint">#define run strategy
#include "trend.c" // &lt;= your script
#undef run
#define CYCLES 20 // max WFO cycles

function run()
{
  set(TESTNOW);
  NumTotalCycles = CYCLES-1;
  NumWFOCycles = TotalCycle+1;
  strategy();
}

function evaluate()
{
  var Perf = ifelse(LossTotal &gt; 0,WinTotal/LossTotal,10);
  if(Perf &gt; 1)
    plotBar("WFO+",NumWFOCycles,NumWFOCycles,Perf,BARS,BLACK);
  else
    plotBar("WFO-",NumWFOCycles,NumWFOCycles,Perf,BARS,RED);
}</pre>
<p>We&#8217;re redefining the <strong>run</strong> function to a different name. This allows us to just include the tested script and train it with WFO cycles from 2 up to the number defined by CYCLES. A backtest is executed after training. If an <strong>evaluate</strong> function is present, Zorro runs it automatically after any backtest. It plots a histogram bar of the profit factor (y axis) from each number of WFO cycles. First, the WFO profile of the trend trading system:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2022/04/040422_1441_Why90ofBack3.png" alt="" /></p>
<p>We can see that the performance rises with the number of cycles. This is typical for a system that adapts to the market. All results are positive with a profit factor &gt; 1. Our arbitrary choice of 10 cycles produced a less than average result. So we can at least be sure that this backtest result was not caused by a particularly lucky number of WFO cycles.</p>
<p>The WFO profile of the placebo system:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2022/04/040422_1441_Why90ofBack4.png" alt="" /></p>
<p>This time the number of WFO cycles had a strong random effect on the performance. And it is now obvious why I used 9 WFO cycles for that system. For the same reason I used brute force optimization, since it increases WFO variance and thus the chance to get lucky WFO cycle numbers. That&#8217;s the opposite of what we normally do when developing algorithmic trading strategies.</p>
<p>WFO profiles give insight into WFO cycle dependency, but not into randomness or overfitting by other means. For this, more in-depth tests are required. Zorro supports two methods, the Montecarlo Reality Check (MRC) with randomized price curves, and <a href="https://financial-hacker.com/whites-reality-check/">White&#8217;s Reality Check</a> (WRC) with detrended and bootstrapped equity curves of strategy variants. Both methods have their advantages and disadvantages. But since strategy variants from optimizing can only be created without walk-forward analysis, we&#8217;re using the MRC here.</p>
<h3><strong>The Montecarlo Reality Check<br />
</strong></h3>
<p>First we test both systems with random price curves. Randomizing removes short-term price correlations and market inefficiencies, but keeps the long-term trend. Then we compare our original backtest result with the randomized results. This yields a <strong>p-value</strong>, a metric of the probability that our test result was caused by randomness. The lower the p-Value, the more confidence we can have in the backtest result. In statistics we normally consider a result significant when its p-Value is below 5%.</p>
<p>The basic algorithm of the Montecarlo Reality Check (MRC):</p>
<ol>
<li>Train your system and run a backtest. Store the profit factor (or any other <a href="https://zorro-project.com/manual/en/performance.htm" target="_blank" rel="noopener">performance metric</a> that you want to compare).</li>
<li><a href="https://zorro-project.com/manual/en/detrend.htm" target="_blank" rel="noopener">Randomize</a> the price curve by randomly swapping price changes (shuffle without replacement).</li>
<li>Train your system again with the randomized data and run a backtest. Store the performance metric.</li>
<li>Repeat steps 2 and 3 1000 times.</li>
<li>Determine the number N of randomized tests that have a better result than the original test. The p-Value is N/1000.</li>
</ol>
<p>If our backtest result was affected by an overall upwards trending price curve, which is certainly the case for this SPY system, the randomized tests will be likewise affected. The MRC code:</p>
<pre class="prettyprint">#define run strategy
#include "trend.c" // &lt;= your script
#undef run
#define CYCLES 1000

function run()
{
  set(PRELOAD,TESTNOW);
  NumTotalCycles = CYCLES;
  if(TotalCycle == 1) // first cycle = original
    seed(12345); // always same random sequence
  else
    Detrend = SHUFFLE;
  strategy();
  set(LOGFILE|OFF); // don't export files
}

function evaluate()
{
  static var OriginalProfit, Probability;
  var PF = ifelse(LossTotal &gt; 0,WinTotal/LossTotal,10);
  if(TotalCycle == 1) {
    OriginalProfit = PF;
    Probability = 0;
  } else {
    if(PF &lt; 2*OriginalProfit) // clip image at double range
      plotHistogram("Random",PF,OriginalProfit/50,1,RED);
    if(PF &gt; OriginalProfit)
      Probability += 100./NumTotalCycles;
  }
  if(TotalCycle == NumTotalCycles) { // last cycle
    plotHistogram("Original",
     OriginalProfit,OriginalProfit/50,sqrt(NumTotalCycles),BLACK);
    printf("\n-------------------------------------------");
    printf("\nP-Value %.1f%%",Probability);
    printf("\nResult is ");
    if(Probability &lt;= 1)
      printf("highly significant") ;
    else if(Probability &lt;= 5)
      printf("significant");
    else if(Probability &lt;= 15)
      printf("maybe significant");
    else
      printf("statistically insignificant");
    printf("\n-------------------------------------------");
  }
}</pre>
<p>This code sets up the Zorro platform to train and test the system 1000 times. The <a href="https://zorro-project.com/manual/en/random.htm" target="_blank" rel="noopener"><strong>seed</strong></a> setting ensures that you get the same result on any MRC run. From the second cycle on, the historical data is shuffled without replacement. For calculating the p-value and plotting a histogram of the MRC, we use the <strong>evaluate</strong> function again. It calculates the p-value by counting the backtests resulting in higher profit factors than the original system. Depending on the system, training and testing the strategy a thousand times will take several minutes with Zorro. The resulting MRC histogram of the trend following system:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2022/04/040422_1441_Why90ofBack5.png" alt="" /></p>
<p>The height of a red bar represents the number of shuffled backtests that ended at the profit factor shown on the x axis. The black bar on the right (height is irrelevant, only the x axis position matters) is the profit factor with the original price curve. We can see that most shuffled tests came out positive, due to the long-term upwards trend of the SPY price. But our test system came out even more positive. The p-Value is below 1%, meaning a high significance of our backtest. This gives us some confidence that the simple trend follower can achieve a similar result in real trading.</p>
<p>This cannot be said from the MRC histogram of the placebo system:</p>
<p><img decoding="async" src="https://financial-hacker.com/wp-content/uploads/2022/04/040422_1441_Why90ofBack6.png" alt="" /></p>
<p>The backtest profit factors now extend over a wider range, and many were more profitable than the original system. The backtest with the real price curve is indistinguishable from the randomized tests, with a p-value in the 40% area. The original backtest result of the placebo system, even though achieved with walk-forward analysis, is therefore meaningless.</p>
<p>It should be mentioned that the MRC cannot detect all invalid backtests. A system that was explicitly fitted to a particular price curve, for instance by knowing in advance its peaks and valleys, would get a low p-value by the MRC. No reality check could distinguish such a system from a system with a real edge. Therefore, neither MRC nor WRC can give absolute guarantee that a system works when it passes the check. But when it does not pass, you&#8217;re advised to better not trade it with real money.</p>
<p>I have uploaded the strategies to the 2022 script repository. The MRC and WFOProfile scripts are included in Zorro version 2.47.4 and above. You will need Zorro S for the brute force optimization of the placebo system.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/why-90-of-backtests-fail/feed/</wfw:commentRss>
			<slash:comments>22</slash:comments>
		
		
			</item>
		<item>
		<title>The COVID survival calculator</title>
		<link>https://financial-hacker.com/the-covid-survival-calculator/</link>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Sun, 12 Dec 2021 15:08:16 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Covid]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4224</guid>

					<description><![CDATA[Trading is obviously affected by global pandemics. Not only because markets tank whenever a new virus variant emerges. It&#8217;s also personal. After all, if you know that you have only a few months before you likely die, you might be motivated to trade a little more risky. To help you with this decision, I&#8217;m publishing &#8230; <a href="https://financial-hacker.com/the-covid-survival-calculator/" class="more-link">Continue reading<span class="screen-reader-text"> "The COVID survival calculator"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Trading is obviously affected by global pandemics. Not only because markets tank whenever a new virus variant emerges. It&#8217;s also personal. After all, if you know that you have only a few months before you likely die, you might be motivated to trade a little more risky. To help you with this decision, I&#8217;m publishing here a Zorro script that calculates your average survival time depending on the COVID incidence in your country and on your vaccination status.<span id="more-4224"></span></p>
<p>The algorithm is plain math, based on three variables: The <strong>vaccination percentage</strong> of your country, the vaccination percentage among cases, and the <strong>7-day incidence</strong>, i.e. the number of cases per week and per 100,000 people.&nbsp; &#8216;Case&#8217; can be infection, hospitalization, or death, dependent on what result you want to calculate. Those 3 variables are often available from health organizations in most countries, or can be derived from publicly available statistics. The script calculates the vaccinated and unvaccinated incidences and the average survival time in weeks before a vaccinated or unvaccinated person is infected, hospitalized, or dead. It makes no assumptions about the effectivity of vaccinations.</p>
<p>First, incidence calculation. Let&#8217;s assume that your country has a total 7-day incidence of 400, and that 70% of people, and 35% of the infected are vaccinated. The incidence of the vaccinated is then:</p>
<p><em>I<sub>vac</sub> = 400 * 35/70 = 200</em></p>
<p>The incidence of the unvaccinated:</p>
<p><em>I<sub>unv</sub> = 400 * (100-35)/(100-70) = 867</em></p>
<p>Thus, in that hypothetical case you&#8217;re four times more likely to catch the virus when you&#8217;re unvaccinated &#8211; despite the relatively high 35% vaccinated infection rate. But what does this mean for your survival time?</p>
<p>The probability <em>P</em> to survive a week without becoming a &#8216;case&#8217; depends on incidence <em>I</em>:</p>
<p><em>P = 1-I/100000</em></p>
<p>The chance to survive <em>N</em> weeks is thus</p>
<p><em>(1-I/100000)<sup>N</sup></em></p>
<p>The half life &#8211; the time <em>T</em> in weeks until 50% of people are infected &#8211; is given by</p>
<p><em>T = ln(0.5)/ln(P)</em></p>
<p>When we enter the above figures, first for the vaccinated:</p>
<p><em>T = ln(0.5)/ln(1-200/100000) = 346 weeks</em></p>
<p>Then for the unvaccinated:</p>
<p><em>T = ln(0.5)/ln(1-867/100000) = 80 weeks</em></p>
<p>Thus, in the given scenario most of the unvaccinated will be either dead or recovered within two years. Of course under the assumption that the incidence does not change during that time. We know that this is not the case: due to the exponential spread, pandemics tend to come and go in waves, as in the above image. Therefore, in the case of COVID, use not the current incidence, but the&nbsp; average incidence from top to valley of the most recent wave for estimating your average survival time.</p>
<p>The script in C for Zorro:</p>
<pre class="prettyprint">// Covid Vaxxed vs Unvaxxed survival calculator ///////////////////////////

void click(int Row,int Col)
{
	if(Row != -1) return; // [Result] clicked?
	sound("click.wav");
	printf("\nTotal: Vaxx %.0f%% Unvaxx %.0f%%",
		slider(1),100-slider(1));
	printf("\nCases: Vaxx %.0f%% Unvaxx %.0f%%",
		slider(2),100-slider(2));
	var Vaxx = slider(3)*slider(2)/slider(1);
	var Unvaxx = slider(3)*(100-slider(2))/(100-slider(1));
	printf("\nIncidence: Vaxx %.0f Unvaxx %.0f",
		Vaxx,Unvaxx);
	printf("\nRisk/week: Vaxx %.2f%% Unvaxx %.2f%%",
		Vaxx/1000,Unvaxx/1000);
	printf("\nSurvival/weeks: Vaxx %.0f Unvaxx %.0f",
		log(0.5)/log(1.-Vaxx/100000),
		log(0.5)/log(1.-Unvaxx/100000));
	printf("\n");
}

void main()
{
	slider(1,70,1,99,"Total %","Vaccinated in population");
	slider(2,30,1,99,"Cases %","Vaccinated cases");
	slider(3,1000,1,2000,"Incidence","Weekly cases per 100,000"); 
	while(wait(100)); // keep script alive
}</pre>


<p>Start the script and set up the 3 sliders to:</p>
<ul style="list-style-type: square;">
<li>the total vaccination percentage in the population,</li>
<li>the vaccination percentage of cases,</li>
<li>the 7-day per 100,000 case incidence.</li>
</ul>
<p>Then click on [Result]. The printout should look like this:</p>
<pre>Total: Vaxx 70% Unvaxx 30%
Cases: Vaxx 35% Unvaxx 65%
Incidence: Vaxx 200 Unvaxx 867
Risk/week: Vaxx 0.20% Unvaxx 0.87%
Survival/weeks: Vaxx 346 Unvaxx 80</pre>
<p>The script can be downloaded from the 2021 repository. Zorro can be downloaded from <a href="https://zorro-project.com/download.php" target="_blank" rel="noopener">zorro-project.com</a>.&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Monetize Alternative Facts!</title>
		<link>https://financial-hacker.com/monetize-alternative-facts/</link>
					<comments>https://financial-hacker.com/monetize-alternative-facts/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Sun, 10 Jan 2021 10:05:01 +0000</pubDate>
				<category><![CDATA[No Math]]></category>
		<category><![CDATA[Bet]]></category>
		<category><![CDATA[Censoring]]></category>
		<category><![CDATA[QAnon]]></category>
		<category><![CDATA[Twitter]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=3835</guid>

					<description><![CDATA[After last week’s events, major social media companies made another attempt at saving humanity. Twitter and Facebook booted Trump and some of his enablers, Google and Apple cancelled Parler. But is censorship the right way to stem the swell of disinformation, postfactuality, dislocation from reality? I think not. Here’s a better solution. And you can &#8230; <a href="https://financial-hacker.com/monetize-alternative-facts/" class="more-link">Continue reading<span class="screen-reader-text"> "Monetize Alternative Facts!"</span></a>]]></description>
										<content:encoded><![CDATA[
<p>After last week’s <a href="https://en.wikipedia.org/wiki/2021_United_States_Capitol_attack" target="_blank" rel="noopener">events</a>, major social media companies made another attempt at saving humanity. Twitter and Facebook booted <strong>Trump</strong> and some of his enablers, Google and Apple cancelled <strong>Parler</strong>. But is censorship the right way to stem the swell of disinformation, postfactuality, dislocation from reality? I think not. Here’s a better solution. And you can even use it to earn some extra dollars.<span id="more-3835"></span><span id="more-3835"></span></p>
<h3>If it were true&#8230;</h3>
<p>Our politics and media are controlled by elites who worship Satan and run a child sex ring. According to a <a href="https://www.npr.org/2020/12/30/951095644/even-if-its-bonkers-poll-finds-many-believe-qanon-and-other-conspiracy-theories?t=1610201470518" target="_blank" rel="noopener">recent poll</a>, 17% of Americans agree to this statement, 46% disagree, 37% say they don’t know. The 17% believers seem no  big surprise. In most groups of 100 people you&#8217;ll  find 17 crackpots . Or maybe 17 antisemitists, since &#8220;elites&#8221; or &#8220;globalists&#8221; are code for &#8220;the Jews&#8221;. But how is it possible that 37% “don’t know”?</p>
<p>You normally match a conspiration narrative with your model of reality. How plausible is it? If it were true, how would it work? How many had to be involved? How could it be hidden? Why would someone post it when it&#8217;s so secret? How trustworthy is the source? What interest has the source in spreading it? What interest have I in believing it?</p>
<p>It&#8217;s not too difficult to answer these questions. But if half of the US population still either wants to believe, or just doesn&#8217;t know whether their country is run by a satan worshipping, child abusing cabal, we have a problem.</p>
<h3>The Bear Test</h3>
<p>In the far past, alternative facts tended to correct themselves. If you propagated that cave bears don’t exist, sooner or later all your followers would end up in bears&#8217; bellies. Reality check at work. But if you today believe in QAnon, chemtrails, evil elites, or China funded election stealing conspiracies, reality won&#8217;t reach out and slap you in the face. Your belief won’t put you at an immediate disadvantage. But nevertheless it will have consequences.</p>
<p>The obvious one is incompetent political leadership. Representative democracies compete all the time with other forms of government. The United States, with their economical and military power, could be the natural leader in that competition. Instead, in the last 4 years they became the global laughingstock. Administration by bragging and alternative facts can please followers, but is ill suited for real challenges, such as handling a pandemic. And when US voters decided in November 2020 to terminate that debacle, they were unaware that the worst was yet to come&#8230;</p>
<p>There might be other, more sinister consequences of widespread conspiration belief. Real conspirations can easily hide behind the walls of disinformation. Real whistleblowers are not taken seriously because of all the crackpots. In this way, conspiration theories can become self fulfilling prophecies.<a id="twitter"></a></p>
<h3>Monetizing Twitter Likes</h3>
<p>Trump &amp; Co. are not the cause, but the effect of a global phenomenon &#8211; the emergence of bizarre parallel worlds that compete with reality. In those wolds, Trump has won the election, communists invade America, and evil scientists, pedophiles, the FBI, Fauci, and George Soros plot to take away citizens&#8217; freedom, their health, even their steaks. Far-right social platforms such as Parler or Gettr are full of invented quotes or made up &#8216;news&#8217; that endlessly confirm themselves. Those parallel worlds won&#8217;t disappear by voting, nor by censorship. Attempts by Twitter and others to shield users from the flood of misinformation are futile: People will always find ways of confirming what they want to believe. You cannot censor the Internet &#8211; and if you could, like China, it would be a questionable achievement. But it is still possible to fight disinformation. And even derive a decent income in this way. </p>
<p><a href="https://financial-hacker.com/wp-content/uploads/2021/01/christina.jpg"><img decoding="async" class="alignnone size-full wp-image-3843" src="https://financial-hacker.com/wp-content/uploads/2021/01/christina.jpg" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" srcset="https://financial-hacker.com/wp-content/uploads/2021/01/christina.jpg 602w, https://financial-hacker.com/wp-content/uploads/2021/01/christina-300x74.jpg 300w" alt="" width="602" height="149" /></a></p>
<p>This post, 8 weeks after the election, was obviously at odds with reality. Still, 128700 people apparently agreed to the alternative fact. But instead of the lame “Election officials have certified bla bla bla…”, or even worse, censoring the nice TV lady &#8211; dear Twitter, how about this? </p>
<p><a href="https://financial-hacker.com/wp-content/uploads/2021/01/Christina2-1.jpg"><img loading="lazy" decoding="async" class="alignnone wp-image-3865 size-full" src="https://financial-hacker.com/wp-content/uploads/2021/01/Christina2-1.jpg" alt="" width="602" height="149" srcset="https://financial-hacker.com/wp-content/uploads/2021/01/Christina2-1.jpg 602w, https://financial-hacker.com/wp-content/uploads/2021/01/Christina2-1-300x74.jpg 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>If you&#8217;re Twitter, imagine that you would get 50 cents for any of the 128k likes to this post. Simply add a [Buy] and [Sell] button for any post with a controversial, but easily verifiable claim. Any user that&#8217;s buying Christina’s brilliant analysis can just click [Buy] and invest one dollar in that post. Then they will be able to like or retweet it. If someone is not buying it, they click [Sell] and short the post for 1 $. After a previously defined time, Twitter will evaluate the Pennsylvania outcome and distribute 50% of the stakes to the buyers or sellers, whoever were right. The remaining 50%  stay with Twitter. </p>
<h3>The Q Opportunity</h3>
<p>You don&#8217;t need to wait for Twitter to monetize alternative facts. There are already some platforms that show how this works &#8211; check out  <a href="https://www.predictit.org/">https://www.predictit.org/</a>, <a href="https://polymarket.com/">https://polymarket.com/</a>, or <a href="https://ftx.com/trade/TRUMPGO/USD">https://ftx.com/trade/TRUMPGO/USD</a>. You can see that many conspiration believers are indeed investing money on those platforms. There are bets that Joe Biden will soon get arrested, or that Trump will soon have a comeback as president, and possibly execute some leading democrats on the way. The stakes are usually in the 80% range that this won&#8217;t happen, but a trade with 20% certain profit is still not to be sniffed at. Look out for conspiration bet opportunities! Do it before major contenders, such as Twitter or Facebook, enter that lucrative business. That will be in the interest of the common good &#8211; but it will likely reduce your profit. </p>
<p>In this way, just being reasonable minded can earn you some decent extra income. Admittedly, if you&#8217;re a cult follower, conspiration believer, and/or Trump fanboy, you might have to pay the price &#8211; but hey: consider it a proof of faith. And if you lost too much money with your bets, you could be motivated to check facts before buying them. This will possibly improve your grip on reality. And can end up, maybe, with better leadership of your country. So it’s a win-win situation.</p>
<p>That&#8217;s my comment to last week’s events, and my today’s tip for getting rich, or even richer if you’re Twitter or Facebook. Establish fact brokerages, let more people bet on facts, and let the truth win!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/monetize-alternative-facts/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>&#8220;Please Send Me a Trading System!&#8221;</title>
		<link>https://financial-hacker.com/please-send-me-a-trading-system/</link>
					<comments>https://financial-hacker.com/please-send-me-a-trading-system/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Thu, 08 Oct 2020 09:26:00 +0000</pubDate>
				<category><![CDATA[3 Most Useful]]></category>
		<category><![CDATA[Introductory]]></category>
		<category><![CDATA[No Math]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=3565</guid>

					<description><![CDATA[&#8220;It should produce 150 pips per week. With the best EAs and indicators that you know. How much does it cost? Please also send live histories of your top systems.&#8221;  Although we often get such requests, we still don&#8217;t know the best indicators, don&#8217;t believe in best EAs, and don&#8217;t sell top systems. We do &#8230; <a href="https://financial-hacker.com/please-send-me-a-trading-system/" class="more-link">Continue reading<span class="screen-reader-text"> "&#8220;Please Send Me a Trading System!&#8221;"</span></a>]]></description>
										<content:encoded><![CDATA[
<p><em>&#8220;It should produce 150 pips per week. With the best EAs and indicators that you know. How much does it cost? Please also send live histories of your top systems.&#8221;</em> <br />
Although we often get such requests, we still don&#8217;t know the best indicators, don&#8217;t believe in best EAs, and don&#8217;t sell top systems. We do not sell algo trading systems at all, but only program them for clients after their specifications. We do not trade them, except for testing. But after programming almost 1000 systems, we can see <strong>a pattern emerging</strong>. Which trading <span style="font-size: inherit;">strategies do usually work? Which will fall apart already in the backtest? Here&#8217;s a ranking of all systems we did so far, with a surprising winner.</span><span id="more-3565"></span></p>
<p>One should think that most clients come up with very similar trading systems, so we could meanwhile just click them together from ready code. But it is not so. There&#8217;s apparently no limit of trading ideas. Almost any other system uses some new trading method, unusual data source, or exotic indicator. Still, the systems can be classified in several simple categories. Any of them has its specific success and failure rate.</p>
<h3>Trading systems categorized</h3>
<p>We classify the systems by their market and by their trading rules, both specified by the client. The 4 main markets are Forex/ CFDs, cryptocurrencies, stocks/ETFs/futures, and options. And the 4 <a href="https://zorro-project.com/algotrading.php" target="_blank" rel="noopener">main algorithmic trading methods</a> are risk premia, market models, data mining, and indicator soups.  To recap:</p>
<p><strong>Risk premium systems</strong> gain higher profits by accepting higher risks. In that category fall many stock portfolio rotation and options trading systems.</p>
<p><strong>Market model systems</strong> exploit a particular market inefficiency by detecting anomalies in price curves. Mean reversion, market cycles, market events, or statistical arbitrage are typical model based trade methods. </p>
<p><strong>Data mining systems</strong> predict a price trend by evaluating signals with a machine learning algorithm (aka &#8216;artificial intelligence&#8217;). Those signals are usually derived from the order book or the price curve, but sometimes also from fundamental data or exotic data sources.</p>
<p><strong>Indicator soups</strong> are the most often demanded systems. They do not target a particular market inefficiency, except maybe for going with the trend. They generate trade signals from a combination of traditional or new invented &#8216;technical indicators&#8217;. </p>
<p>Some algo trading systems can fall in more than one category. For instance, a <a href="https://financial-hacker.com/build-better-strategies/">grid trader</a> can be considered a risk premium system (high probability of small wins against low probability of high losses), but also a model based system (exploitation of volatility anomalies). If a system cannot be clearly assigned, it is split among several categories in the table below. We can see that clients favor some of the 16 possible combinations, while others are rare:</p>
<table style="background-color: #cadbe6; width: 100%; height: 230px;">
<tbody>
<tr style="height: 55px;">
<td style="height: 55px; width: 23.0159%;"> </td>
<td style="height: 55px; width: 18.254%;">Risk<br />
premium</td>
<td style="height: 55px; width: 14.7619%;">Market<br />
model</td>
<td style="height: 55px; width: 14.9206%;">Data<br />
mining</td>
<td style="height: 55px; width: 18.254%;">Indicator<br />
soup</td>
<td style="height: 55px; width: 10.6349%;">Sum</td>
</tr>
<tr style="height: 35px;">
<td style="height: 35px; width: 23.0159%;">Forex/CFDs</td>
<td style="height: 35px; width: 18.254%; text-align: center;">21</td>
<td style="height: 35px; width: 14.7619%; text-align: center;">74</td>
<td style="height: 35px; width: 14.9206%; text-align: center;">121</td>
<td style="height: 35px; width: 18.254%; text-align: center;">235</td>
<td style="height: 35px; width: 10.6349%; text-align: center;">451</td>
</tr>
<tr style="height: 35px;">
<td style="height: 35px; width: 23.0159%;">Crypto</td>
<td style="height: 35px; width: 18.254%; text-align: center;">0</td>
<td style="height: 35px; width: 14.7619%; text-align: center;">4</td>
<td style="height: 35px; width: 14.9206%; text-align: center;">55</td>
<td style="height: 35px; width: 18.254%; text-align: center;">40</td>
<td style="height: 35px; width: 10.6349%; text-align: center;">99</td>
</tr>
<tr style="height: 35px;">
<td style="height: 35px; width: 23.0159%;">Stocks/ETFs</td>
<td style="height: 35px; width: 18.254%; text-align: center;">68</td>
<td style="height: 35px; width: 14.7619%; text-align: center;">95</td>
<td style="height: 35px; width: 14.9206%; text-align: center;">34</td>
<td style="height: 35px; width: 18.254%; text-align: center;">14</td>
<td style="height: 35px; width: 10.6349%; text-align: center;">211</td>
</tr>
<tr style="height: 35px;">
<td style="height: 35px; width: 23.0159%;">Options</td>
<td style="height: 35px; width: 18.254%; text-align: center;">48</td>
<td style="height: 35px; width: 14.7619%; text-align: center;">159</td>
<td style="height: 35px; width: 14.9206%; text-align: center;">16</td>
<td style="height: 35px; width: 18.254%; text-align: center;">12</td>
<td style="height: 35px; width: 10.6349%; text-align: center;">235</td>
</tr>
<tr style="height: 35px;">
<td style="height: 35px; width: 23.0159%;">Sum</td>
<td style="height: 35px; width: 18.254%; text-align: center;">137</td>
<td style="height: 35px; width: 14.7619%; text-align: center;">332</td>
<td style="height: 35px; width: 14.9206%; text-align: center;">226</td>
<td style="height: 35px; width: 18.254%; text-align: center;">301</td>
<td style="height: 35px; width: 10.6349%; text-align: center;">996</td>
</tr>
</tbody>
</table>
<p>For determining the success or failure rate, we used 8-years backtests for unoptimized systems, and a walk forward analysis for optimized systems. A successful system had to return at least 12% CAGR for stocks, futures, or options, or 30% annual profit for Forex, CFDs, or cryptocurrencies. The R2 parameter had to be above 0.7. If clients ordered a <a href="https://zorro-project.com/backtest.php" target="_blank" rel="noopener">Montecarlo analysis</a>, the system had to pass it at 95% confidence. If one of those conditions was not fulfilled, the system was classified as failure. </p>
<p>The percentages of successful systems:</p>
<table class=" alignleft" style="height: 230px; background-color: #cadbe6; width: 100%;" border="0" width="100%" cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 15.0pt;">
<td class="xl65" style="height: 50px; width: 23.0159%;" width="80" height="40"> </td>
<td class="xl65" style="width: 14.7619%; height: 35px;" width="80">Risk<br />
premium</td>
<td class="xl65" style="width: 15.0794%; height: 35px;" width="80">Market<br />
model</td>
<td class="xl65" style="width: 15.0794%; height: 35px;" width="80">Data<br />
mining</td>
<td class="xl65" style="width: 16.6667%; height: 35px;" width="80">Indicator<br />
soup</td>
<td class="xl66" style="width: 15.2381%; height: 50px;" width="80">Success<br />
rate</td>
</tr>
<tr style="height: 15.0pt;">
<td class="xl65" style="height: 15px; width: 23.0159%;" width="80" height="20">Forex/CFDs</td>
<td class="xl65" style="width: 14.7619%; height: 15px; text-align: center;" align="right" width="80">88 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">81 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">69 %</td>
<td class="xl65" style="width: 16.6667%; height: 15px; background-color: #ff0000; text-align: center;" align="right" width="80">31 %</td>
<td class="xl66" style="width: 15.2381%; height: 15px; text-align: center;" align="right" width="80">52 %</td>
</tr>
<tr style="height: 15.0pt;">
<td class="xl65" style="height: 15px; width: 23.0159%;" width="80" height="20">Crypto</td>
<td class="xl65" style="width: 14.7619%; height: 15px; text-align: center;" align="right" width="80">0 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">75 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">62 %</td>
<td class="xl65" style="width: 16.6667%; height: 15px; background-color: #ff0000; text-align: center;" align="right" width="80">25 %</td>
<td class="xl66" style="width: 15.2381%; height: 15px; text-align: center;" align="right" width="80">49 %</td>
</tr>
<tr style="height: 15.0pt;">
<td class="xl65" style="height: 15px; width: 23.0159%;" width="80" height="20">Stocks/ETFs</td>
<td class="xl65" style="width: 14.7619%; height: 15px; background-color: #00ff00; text-align: center;" align="right" width="80">92 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">85 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">61 %</td>
<td class="xl65" style="width: 16.6667%; height: 15px; text-align: center;" align="right" width="80">35 %</td>
<td class="xl66" style="width: 15.2381%; height: 15px; text-align: center;" align="right" width="80">80 %</td>
</tr>
<tr style="height: 15.0pt;">
<td class="xl65" style="height: 15px; width: 23.0159%;" width="80" height="20">Options</td>
<td class="xl65" style="width: 14.7619%; height: 15px; background-color: #00ff00; text-align: center;" align="right" width="80">96 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; background-color: #00ff00; text-align: center;" align="right" width="80">91 %</td>
<td class="xl65" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">75 %</td>
<td class="xl65" style="width: 16.6667%; height: 15px; text-align: center;" align="right" width="80">58 %</td>
<td class="xl66" style="width: 15.2381%; height: 15px; text-align: center;" align="right" width="80">89 %</td>
</tr>
<tr style="height: 15.0pt;">
<td class="xl66" style="height: 15px; width: 23.0159%;" width="80" height="20">Success rate</td>
<td class="xl66" style="width: 14.7619%; height: 15px; text-align: center;" align="right" width="80">93 %</td>
<td class="xl66" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">87 %</td>
<td class="xl66" style="width: 15.0794%; height: 15px; text-align: center;" align="right" width="80">67 %</td>
<td class="xl66" style="width: 16.6667%; height: 15px; text-align: center;" align="right" width="80">32 %</td>
<td class="xl66" style="width: 15.2381%; height: 15px; text-align: center;" align="right" width="80">66 %</td>
</tr>
</tbody>
</table>
<p> The average success rates at the end of the columns and rows are weighted by the number of systems. We can see that the overall success rate was only 66%. In 34% of cases we had to break the bad news to the client that it&#8217;s not advised to trade this system live. It produced no, or too little profit in the tests. Sometimes we could see what the problem was, and suggest ways to improve the system. But even total failures were no wasted money. When you know that your favorite manually traded system won&#8217;t work in the long run, you&#8217;ll save a lot more money than spent for programming and testing. </p>
<h3>And the winner is&#8230;</h3>
<p>The statistics are spoiled by the forex and crypto systems, half of which were losers. This is at least better than most such systems from trading books or trader forums, of which 90% fail already in a simple out-of-sample test, or at least in a cluster or Montecarlo analysis. We got a surprising result in the &#8216;Indicator soup&#8217; systems. You would normally expect that they all fail big time, since they are not based on a market model. But in fact almost every third indicator hodgepodge was successful, even in live trading on a test server. Maybe the clients knew more than we did. </p>
<p>It is also a bit surprising that the most complex systems of all, the data mining systems that usually employ deep learning algorithms, did not fare much better. They have an acceptable success rate, but are easily surpassed by a certain sort of much simpler systems. </p>
<p>Of all systems we tested so far, the big winners were the long-term trading systems for <strong>stocks</strong>, <strong>ETFs</strong>, or <strong>options</strong>. Of the option traders, the simpler systems had often better performance. It&#8217;s relatively hard to specify a losing option system, but some still managed it by using short expiration dates, complex entries, fancy rollovers, or intraday buying and selling. One of the very simple, but successful option traders was included in the Zorro scripts.</p>
<p>We found another trend that is not visible in the table: With a few exceptions like HFT or arbitrage, there was an almost linear correlation between <strong>time frames</strong> and performances. Systems on one, five, or ten minute bars were rarely profitable. The good systems traded mostly on 1-hour, 4-hour, or 24-hour time frames. Faster is not always better.</p>
<p>This does not mean that we all should now abandon forex and cryptos and trade only long-term options or ETF portfolios. Diversification is a key to success. All markets still have long periods of ineffectivity and plenty opportunities of trading profits. Maybe the statistics above help to look for them. </p>
<p><strong>Update (2025):</strong> This article was posted 5 years ago, and we have meanwhile more than 2000 systems programmed for clients. Due to technical progress especially with machine learning systems the overall success rate is now slightly better at 71%. But the success relations between the various trading methods are still the same.</p>
<h3>Related articles</h3>
<p><strong>⇒ </strong><a href="https://financial-hacker.com/i-hired-a-contract-coder/">I Hired a Contract Coder</a></p>
<p><strong>⇒ </strong><a href="https://financial-hacker.com/build-better-strategies/">Build Better Strategies!</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/please-send-me-a-trading-system/feed/</wfw:commentRss>
			<slash:comments>32</slash:comments>
		
		
			</item>
		<item>
		<title>The Scholz Brake: Fixing Germany&#8217;s New 1000% Trader Tax</title>
		<link>https://financial-hacker.com/the-scholz-brake-fixing-germanys-new-1000-trader-tax/</link>
					<comments>https://financial-hacker.com/the-scholz-brake-fixing-germanys-new-1000-trader-tax/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Sun, 19 Jan 2020 10:44:05 +0000</pubDate>
				<category><![CDATA[No Math]]></category>
		<category><![CDATA[System Evaluation]]></category>
		<category><![CDATA[Economy]]></category>
		<category><![CDATA[Tax]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=3197</guid>

					<description><![CDATA[Would you like to read &#8211; from begin to end &#8211; a 18 page pounderous law draft titled &#8220;Law for introducing a duty to report cross-border tax structuring&#8221;? The members of the German Bundestag apparently didn&#8217;t. After all, nothing seemed wrong with a duty to report cum-ex schemes. So the new law, proposed by finance &#8230; <a href="https://financial-hacker.com/the-scholz-brake-fixing-germanys-new-1000-trader-tax/" class="more-link">Continue reading<span class="screen-reader-text"> "The Scholz Brake: Fixing Germany&#8217;s New 1000% Trader Tax"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Would you like to read &#8211; from begin to end &#8211; a 18 page pounderous law draft titled <em>&#8220;Law for introducing a duty to report cross-border tax structuring&#8221;</em>? The members of the German Bundestag apparently didn&#8217;t. After all, nothing seemed wrong with a duty to report cum-ex schemes. So the new law, proposed by finance minister Olaf Scholz, passed legislation on December 12, 2019 without much discussion. Only afterwards its real content, hidden on page 15, became public. It caused incredulity and turmoil among traders and investors. This article deals with the new bizarre German &#8216;trader tax&#8217;, and with ways to step around it.<span id="more-3197"></span></p>
<p>News about a &#8220;1000% tax for traders&#8221; and even a &#8220;tax on losses&#8221; spread quickly in January 2020. Hopefully, fake news? This is the relevant section of the new law (Art. 5 § 20 sentence 6 number 4):</p>
<p><em>&#8220;The Income Tax Act as published on October 8, 2009 (Federal Law Gazette I p. 3366, 3862), last amended by Article 1 of the Law of August 4, 2019 (Federal Law Gazette I p. 1122), is changed as follows. The following sentences are inserted after § 20 paragraph 6 sentence 4: Losses from financial assets within the meaning of paragraph 2 sentence 1 number 3 may only be offset in the amount of 10,000 euros with profits within the meaning of paragraph 2 sentence 1 number 3 and with income within the meaning of § 20 paragraph 1 number 11; sentences 2 and 3 apply mutatis mutandis with the proviso that losses that have not been offset each year may only be offset against profits up to the amount of 10,000 euros with profits within the meaning of paragraph 2 sentence 1 number 3 and with income within the meaning of § 20 paragraph 1 number 11. &#8220;</em></p>
<p>Translation: For the income tax, trading losses cannot anymore be offset against trading profits in excess of EUR 10,000 per year.</p>
<p>Bad enough. But surely they mean that an annual loss can only be offset in 10,000 EUR portions against annual profits in subsequent years? That was at least my interpretation. It made a sort of sense, and appeared harmless if you anyway do not plan to have an annual trading loss. But rumors said that they mean to tax not the annual net profit, but the profit of every single trade. Some said it&#8217;s even a tax on every favourable price tick of any open position, since this already constitutes a profit. In any case, this would quickly sum up to an insane tax amount &#8211; no matter if you win or lose. It&#8217;s in fact not a tax on income, but a tax on volatility, portfolio diversification, and hedging. And it was not even clear for which sorts of assets that tax is due. The relevant <em>§ 2 sentence 1 number 3</em> can be applied to options, futures, and bonds, but possibly also to all leveraged assets such as forex, CFDs, ETFs, and stocks. Only the risky and ecologically damaging speculation with cryptocurrencies seems exempt.</p>
<h6>The win/loss offset mystery</h6>
<p>For getting clarification, I wrote a letter:</p>
<p><em>Dear Federal Ministry of Finance,</em></p>
<p><em>on my blog I would like to inform readers about the current &#8220;Law for introducing a duty to report cross-border tax structuring&#8221;, in particular about Art 5 § 20 sentence 6 number 4. </em><em style="font-size: inherit;">However, I am not sure that I fully understood the new law. Therefore I kindly ask you to briefly answer my subsequent questions.</em></p>
<p><em>1) Which of the following financial products fall under the referred &#8220;financial assets&#8221;: stocks, currencies (&#8216;Forex&#8217;), options, futures, CFDs, savings contracts with a limited term, German treasury bonds?</em></p>
<p><em>2)  Which tax is due in this scenario: Bob owns EUR 20,000 that he invests in options trading. He buys about 200 options per year. In one winning year, 101 of the transactions ended with a profit of EUR 1000 each, 99 transactions with a loss of EUR 1000 each. The annual result is <strong>EUR 2000</strong>. The taxable profit is <strong>EUR 101,000</strong>, for which Bob has to pay a tax of EUR 91,000 x 25% = <strong>EUR 22,750</strong> after deducting EUR 10,000 loss. The tax rate in relation to the EUR 2000 profit is <strong>1137.5%</strong>.  Is the tax calculation correct?</em></p>
<p><em>3) Same scenario, but a losing year. 101 transactions ended with a loss of EUR 1000, 99 transactions with a profit of EUR 1000. The annual loss is <strong>EUR 2000</strong>. The taxable profit is EUR 99,000. After subtracting EUR 10,000, Bob has for his loss a tax liability of EUR 89,000 x 25% = <strong>EUR 22,250</strong>.</em></p>
<p><em>4) Same scenario, but Bob now tries to outwit the new trader tax. He buys a single long-term position for EUR 20,000 at the begin of the year. Due to leverage, the total value of the position has risen by EUR 100,000 by the middle of the year, then dropped again by EUR 100,000 by the end of the year. Bob sells at the end of the year at purchase price. The year ends profit-neutral and Bob intends to pay no tax. <br />   But the finance ministry is not as easily fooled. Since the tax also applies to the value increase in the middle of the year, the taxable profit minus loss deduction is <strong>EUR 90,000</strong>. Bob gets a tax bill of EUR 90,000 x 25% = <strong>EUR 22,500</strong>.</em></p>
<p><em>5) Same scenario as 2), but for stepping around the new trader tax, Bob now avoids closing positions. Instead he exercises all options, no matter of in the money or not, shortly before expiration. The paid premium is then not a loss, but a purchase fee. Since the broker offsets simultaneous long and short positions automatically, the finance ministry can do nothing about that. <br />   At the end of the year remains a single long position in the underlying with a value of <strong>EUR 2,000</strong>, which is then sold. The taxable profit amount is EUR 2,000 x 25% = <strong>EUR 500</strong>.</em></p>
<p><em>6) Same scenario as 2), but for stepping around the new trader tax, the broker has now offered a new structured product. Instead of closing positions, they are converted directly into another asset of the client&#8217;s choice that does not fall under § 20 sentence 6 number 4 (for instance, a nonleveraged stock). The premium for selling options is also not paid in cash, but in a position of that asset. At the end of the year, a position with a value of <strong>EUR 2,000</strong> remains in Bob&#8217;s account, which is then sold. The taxable profit amount is EUR 2,000 x 25% = <strong>EUR 500</strong>.</em></p>
<p><em>I would be pleased if you could briefly tell me which of the tax calculations in the 5 scenarios are appropriate. I would also be interested in a brief explanation of the purpose and motivation behind the new law. And I would be very interested in an explanation how Bob in scenarios 2-4 is supposed to pay his taxes, since  they exceed all his capital.</em></p>
<p><em>Sincerely yours</em></p>
<p><em>Johann Christian Lotter</em></p>
<p>I was obviously not the only one who asked the ministry about the new law. I got a long formal response with little information content. It did not answer any of my questions, but confirmed that the 1137% tax and the tax on losses in scenarios 2 and 3 is for real. They did not comment on the tick tax of scenario 4.</p>
<p>Even the experts in Scholz&#8217; finance ministry seem mystified about the implementation, motivation, or objective of this new law. It does not stand alone, but is part of a bundle of similar (although slightly less absurd) laws against retail traders and small investors. Their purpose is a mystery. They seem not motivated by populism. Except for the upcoming transaction tax, few know about them. Some say that they were originally intended against tax scams and large-scale speculation, and only designed in a wrong way.  But that is of course impossible, since it would imply a remarkable intellectual incapacity of our lawmakers. Maybe Scholz just intended to show a leftist position for his election to party chairman (which failed nevertheless). Or he&#8217;s really convinced that people who live from trading are all speculators and capitalist pigs, and must be hit whenever possible. Who knows. A personal confession at this point: I, also, am responsible for the new tax. I have always voted for Olaf Scholz&#8217; party in the past. Often just out of tradition. This was apparently not always a wise decision.</p>
<h6>Four ways to fix the tax</h6>
<p>The trader tax will be in effect from 2021. It will then be unique in the world. No other country has a tax on volatility or diversification. I think it will not last long: Traders financially ruined by it, like Bob in some of the above examples, will challenge it in court. The Federal Supreme Court might eventually annul it due to unlawful overtaxation or its blatant absurdity. But until that happens, we&#8217;ll have to live with it.</p>
<p>Large-scale tax scammers, speculators, and hedge funds can laugh at Scholz&#8217; tax constructs. They just incorporate, preferably offshore, and are exempt. That&#8217;s no solution for small private investors. Scenarios 5 and 6 are two possible ways to avoid the trader tax. A third, relatively simple method would be a trading account in a cryptocurrency. As long as the tax is not applied on open positions, converting one financial asset into another should be tax-neutral, since it does not realize any profit. The problem: You never know what bitcoin, or another account base that brokers might offer for outwitting the tax, will be worth next year. And the ministry was unable to precisely describe how the tax will be applied and which assets are affected. So there&#8217;s no guarantee that these workarounds do really work. The safe way is staying below the loss limit.  </p>
<p>I know that the <a href="https://zorro-project.com" target="_blank" rel="noopener noreferrer">Zorro platform</a>, on demand of several German users, will get a new indicator, the <strong>Scholz Brake</strong>. This indicator will be implemented in the next Zorro release. It can be set up at the session start and at the begin of any year, like this:</p>
<pre class="prettyprint">if(is(INITRUN) || year(0) != year(1)) // any new year<br />  ScholzBrake = 10000; // activate the Scholz Brake</pre>
<p>Once set, the <strong>ScholzBrake </strong>variable will be counted down by all trading losses of all Zorro instances that run on the same PC and have activated it. So the script can always check the distance to the critical EUR 10,000 total loss limit, and decide what to do. If the variable reaches zero, trading is automatically suspended until the end of the year.</p>
<p>This prevents you (mostly) from the effects of the new law. Of course at the price of not trading for the rest of the year. If you live from trading and have hit the Scholz limit early in the year, you got enough time to look for a new job. Maybe as an expert in the finance ministry.</p>
<h6>References</h6>
<p>1. <a href="https://www.bundesrat.de/SharedDocs/drucksachen/2019/0601-0700/649-19.pdf;jsessionid=994163D05E496D3D58EED7A2ECCCA424.1_cid365?__blob=publicationFile&amp;v=1" target="_blank" rel="noopener noreferrer">Gesetz zur Einführung einer Pflicht zur Mitteilung</a><br /><a href="https://www.bundesrat.de/SharedDocs/drucksachen/2019/0601-0700/649-19.pdf;jsessionid=994163D05E496D3D58EED7A2ECCCA424.1_cid365?__blob=publicationFile&amp;v=1">grenzüberschreitender Steuergestaltungen</a></p>
<p>2. <a href="https://boerse.ard.de/anlagestrategie/steuern/verlustverrechnung-fuer-termingeschaefte-wird-erschwert100.html" target="_blank" rel="noopener noreferrer">ARD Börsenmagazin</a></p>
<p>3. <a href="https://manual.zorro-project.com/lots.htm#scholz" target="_blank" rel="noopener noreferrer">ScholzBrake</a></p>
<p>4. <a href="http://chng.it/xYTnxrqxJ5" target="_blank" rel="noopener noreferrer">Petition</a></p>

]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/the-scholz-brake-fixing-germanys-new-1000-trader-tax/feed/</wfw:commentRss>
			<slash:comments>33</slash:comments>
		
		
			</item>
		<item>
		<title>The Mechanical Turk</title>
		<link>https://financial-hacker.com/the-mechanical-turk/</link>
					<comments>https://financial-hacker.com/the-mechanical-turk/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Mon, 10 Dec 2018 07:17:27 +0000</pubDate>
				<category><![CDATA[Indicators]]></category>
		<category><![CDATA[System Development]]></category>
		<category><![CDATA[Options]]></category>
		<category><![CDATA[Price distribution]]></category>
		<category><![CDATA[Sentiment]]></category>
		<category><![CDATA[SPY]]></category>
		<guid isPermaLink="false">http://www.financial-hacker.com/?p=2974</guid>

					<description><![CDATA[We can see thinking machines taking over more and more human tasks, such as car driving, Go playing, or financial trading. But sometimes it&#8217;s the other way around: humans take over jobs supposedly assigned to thinking machines. Such a job is commonly referred to as a Mechanical Turk in reminiscence to Kempelen&#8217;s famous chess machine &#8230; <a href="https://financial-hacker.com/the-mechanical-turk/" class="more-link">Continue reading<span class="screen-reader-text"> "The Mechanical Turk"</span></a>]]></description>
										<content:encoded><![CDATA[<p>We can see thinking machines taking over more and more human tasks, such as car driving, Go playing, or financial trading. But sometimes it&#8217;s the other way around: humans take over jobs supposedly assigned to thinking machines. Such a job is commonly referred to as a <strong>Mechanical Turk</strong> in reminiscence to Kempelen&#8217;s famous chess machine from 1768. In our case, a Mechanical Turk is an automated trading algorithm based on human intelligence. <span id="more-2974"></span></p>
<p>Theoretically, many trend trading systems would fall in the Turk category since they are based on following the herd. But here we&#8217;re not looking into trader&#8217;s opinions of the current market situation, but into their expectations of the future. There are several methods. The most usual is evaluating the <strong>Commitment Of Traders</strong> report, for which many platforms, also Zorro, provide easy-to-use indicators. But some publications (1) found that using the COT report for predicting the markets produces mixed results at best.</p>
<p>There&#8217;s a more precise way to get the market&#8217;s expectations. It&#8217;s using <a href="https://www.financial-hacker.com/algorithmic-options-trading/">options premiums</a>. If an option expires in 6 weeks, its current premium reflects what option buyers or sellers think about the underlying price in 6 weeks.</p>
<h3>The price probability distribution</h3>
<p>For deriving the expected underlying price at expiration, we have to take all strike prices in consideration. Here&#8217;s the algorithm in short (I haven&#8217;t invented it, a longer description can be found in (2)). Assume SPY is currently trading at $200. For getting the probability that it will rise to between 210 and 220 in 6 weeks, we&#8217;re looking into the 210 call and the 220 call. Suppose they trade at $14 and $10. So we can buy the 210 call and sell the 220 call and pay $4 difference. If at expiration SPY is under 210, both contracts have no worth and we lose the 4 dollars. If it is above 220, our gain is the $10 strike difference minus $4 premium difference, so we win 6 dollars. If it is between 210 and 220, our win or loss is also inbetween, with an average of (-4+6)/2 = 1 dollar.</p>
<p>When options prices are &#8220;fair&#8221;, i.e. solely determined by probabilities where the price will end up at expiration, summing up over all possible outcomes yields zero profit or loss. So</p>
<p><em><strong>-$4×L + $1×M + $6×H = $0</strong></em></p>
<p>where <em><strong>L</strong></em> is the probability for SPY to end up below 210, <em><strong>M</strong></em> is the probability that it will be between 210 and 220, and <em><strong>H</strong></em> is the probability that it will be above 220. Since one of these three alternatives will always happen, the sum of all 3 probabilities must be 1:</p>
<p><em><strong>L + M + H = 1</strong></em></p>
<p>Now let&#8217;s assume that we know <em><strong>L</strong></em> already. Then we have two equations with two unknowns, which are easily solved:</p>
<p><em><strong>5L &#8211; 5H = 1    =&gt;  H = L &#8211; 0.2<br />
10L + 5M = 6    =&gt;  M = 1.2 -2L </strong></em></p>
<p>Assuming <em><strong>L = 50%</strong></em> yields <em><strong>H = 30%</strong></em> and <em><strong>M = 20%</strong></em>.</p>
<p>How do we now get the value <em><strong>L</strong></em>? We simply take the lowest strike offered at the market, and assume that the probability of SPY ending up even below that is zero. So our first <em><strong>L</strong></em> is 0.  We can now use the method above to calculate the <em><strong>M</strong></em> belonging to the interval between the lowest and the second-lowest strike. That <em><strong>M</strong></em> is then added to <em><strong>L</strong></em> since it&#8217;s the probability of SPY ending up at or below the second-lowest strike. We continue that process with the next interval, getting a specific <em><strong>L</strong></em> and <em><strong>M</strong></em> for any interval until we arrived at the highest strike. If the traders have been consistent with their assumptions, the final <em><strong>L</strong></em> &#8211; the sum over all <em><strong>M</strong></em>s &#8211; should be now at or close to 1.</p>
<p>Here&#8217;s a small script that displays the 6-weeks <em><strong>L</strong></em> distribution of SPY:</p>
<pre class="prettyprint">void main() 
{
	StartDate = 20170601;
	LookBack = 0;

	assetList("AssetsIB");
	asset("SPY"); 

// load today's contract chain
	contractUpdate(0,0,CALL|PUT);
	printf("\n%i contracts",NumContracts);
	if(!NumContracts) return;

// get underlying price
	var Price,Current = priceClose(0);
	printf("\nCurrent price %.2f",Current);

// plot CPD histogram	
	contractCPD(45);	// 6 weeks
	int N = 0;
	for(Price = 0.75*Current; Price &lt; 1.25*Current; N++, Price += 0.01*Current)
		plotBar("CPD",N,floor(Price),cpd(Price),BARS|LBL2,RED);
	printf("\nExpected price %.2f",cpdv(50));

// compare with real future price
	set(PEEK);
	N = timeOffset(UTC,-45,0,0);
	printf("\nFuture price %.2f",priceClose(N));
}</pre>
<p>The result is a histogram of expected probabilities, in percent, that the SPY price will be at or below the price at the x-axis six weeks in the future. I&#8217;ve marked the current price with a black bar.</p>
<p><figure id="attachment_3093" aria-describedby="caption-attachment-3093" style="width: 699px" class="wp-caption alignnone"><a href="https://www.financial-hacker.com/wp-content/uploads/2019/06/cpd.png"><img loading="lazy" decoding="async" class="wp-image-3093 size-full" src="https://www.financial-hacker.com/wp-content/uploads/2019/06/cpd.png" alt="" width="699" height="284" srcset="https://financial-hacker.com/wp-content/uploads/2019/06/cpd.png 699w, https://financial-hacker.com/wp-content/uploads/2019/06/cpd-300x122.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-3093" class="wp-caption-text">SPY 6 weeks price probability distribution at June 1, 2017</figcaption></figure></p>
<p>The <strong><a href="https://manual.zorro-project.com/contractcpd.htm">contractCPD</a></strong> function generates the distribution with the above described algorithm, <strong>cpd</strong> returns the accumulated probability <em><strong>L</strong></em> (in percent) at a given price, and <strong>cpdv</strong> returns the price at a given <em><strong>L</strong></em>. Therefore, <strong>cpdv(50)</strong> is the median of market expectations. In our case, at June 1 2017, a modest price increase to $245 was expected for mid-July (in fact the price ended up at $245.51, but don&#8217;t get too excited &#8211; often trader&#8217;s expectations fall short by several dollars). We can also see an unusal step at the begin of the histogram: about 10% of traders expected a strong drop to below $200. Maybe Trump twittered something that morning.</p>
<h3>The strategy</h3>
<p>We will now exploit trader&#8217;s expectations for a strategy, and this way check if they have any merit. This is our mechanical Turk:</p>
<pre class="prettyprint">#define Sentiment AssetVar[0]

void run() 
{
	StartDate = 20120102;
	EndDate = 20171231;
	BarPeriod = 1440;

	assetList("AssetsIB");
	asset("SPY");
	MaxLong = MaxShort = 1;

// load today's contract chain
	contractUpdate(0,0,CALL|PUT);
	int N = contractCPD(45);

// increase/decrease market sentiment 
	if(N) {
		var Expect = cpdv(50) - priceClose();
		if(Expect &lt; 0)
			Sentiment = min(Expect,Sentiment+Expect);
		else
			Sentiment = max(Expect,Sentiment+Expect);
	}
	if(Sentiment &gt; 5)
		enterLong();
	else if(Sentiment &lt; -5)
		enterShort();
	
	plot("Sentiment",Sentiment,NEW,RED);
}</pre>
<p>We&#8217;re checking the market expectation every day and add it to a previously defined <strong>Sentiment</strong> asset variable. If the expectation changes sign, so does <strong>Sentiment</strong>. If its amount has accumulated above 5, we buy a long or short position dependent on its sign. This way we&#8217;re only considering the market expectation when it&#8217;s either relatively strong or had the same direction for several days.</p>
<p>The result:</p>
<p><a href="https://www.financial-hacker.com/wp-content/uploads/2019/06/turkresult.png"><img loading="lazy" decoding="async" class="alignnone wp-image-3098 size-full" src="https://www.financial-hacker.com/wp-content/uploads/2019/06/turkresult.png" alt="" width="699" height="359" srcset="https://financial-hacker.com/wp-content/uploads/2019/06/turkresult.png 699w, https://financial-hacker.com/wp-content/uploads/2019/06/turkresult-300x154.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>The system produces about 20% annual return with profit factor 3. The red line in the lower chart is the Sentiment variable &#8211; we can see that it often steadily increases, but sometimes also decreases. Since SPY normally rises, shorting it with this strategy produces less profit than going long, but is still slightly profitable with an 1.16 profit factor.</p>
<h3>Predicting the price in 6 weeks</h3>
<p>What are traders currently thinking of the SPY price in 6 weeks? For this, the first script above needs just be slightly modified so that it does not use historical options data, but connects to IB and downloads the current options chain with all prices:</p>
<pre class="prettyprint">void main() 
{
	StartDate = NOW;
	LookBack = 0;

	assetList("AssetsIB");
	asset("SPY"); 

// load today's contract chain
	contractUpdate(0,0,CALL|PUT);
	printf("\n%i contracts",NumContracts);
	if(!NumContracts) return;

// get underlying price
	var Price,Current = priceClose(0);
	printf("\nCurrent price %.2f",Current);

// plot CPD histogram
	printf("\nWait time approx %i minutes",1+NumContracts/200);
	contractCPD(45);
	int N = 0;
	for(Price = 0.75*Current; Price &lt; 1.25*Current; N++, Price += 0.01*Current)
		plotBar("CPD",N,floor(Price),cpd(Price),BARS|LBL2,RED);
	printf("\nExpected price %.2f",cpdv(50));
}</pre>
<p>This script must be started in Zorro&#8217;s Trade mode with the IB plugin selected. Mind the displayed &#8220;wait time&#8221;. IB sometimes needs up to ten seconds for returning the price of an option contract, so downloading the prices of all 6-weeks contracts can take half an hour or more.</p>
<p>I ran that script today (Dec 11 2018) and the option traders expect the SPY price to rise to $269 in six weeks. So I&#8217;ll check the price by the end of January and post here if they have been right.</p>
<p>I&#8217;ve added the scripts to the 218 repository. You&#8217;ll need Zorro 1.99 or above, and SPY options EOD history for the first 2 scripts. You&#8217;ll really have to buy it this time, the free <a href="https://www.financial-hacker.com/algorithmic-options-trading/">artificial options history</a> won&#8217;t do for market sentiment.</p>
<h3>Conclusions</h3>
<ul>
<li>A Turk can beat a thinking machine.</li>
<li>Option traders tend to underestimate future price changes.</li>
<li>But they are often right in the price direction.</li>
</ul>
<h3>Literature</h3>
<p>(1) <a href="http://www.farmdoc.illinois.edu/nccc134/conf_2007/pdf/confp01-07.pdf">Sanders, Irwin, Merrin: Smart Money? The Forecasting Ability of CFTC Large Traders (2007)</a></p>
<p>(2) <a href="https://www.globalcapital.com/article/k6543wh6f19l/option-prices-imply-a-probability-distribution">Pat Neal, Option Prices Imply a Probability Distribution</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/the-mechanical-turk/feed/</wfw:commentRss>
			<slash:comments>39</slash:comments>
		
		
			</item>
	</channel>
</rss>
