Tag Trading

Posts: 10

Python Skills

The thing about coding is that you'll never want to do it unless you have to solve something with it. This is why Python has become an indispensable language for all sorts of Data munging. There's a ton of data generated every day and you can use it for gain (or loss).

Over the past month my Python skills have made a big leap forward. This is because I need to manipulate data inside my organization. I'm putting the finishing touches on a BDR (Business Development Rep) Bot that I built to help my AE (Account Exec). We get a ton of leads everyday and this Python script cuts through the noise to the higher quality leads. Why? So we can focus our limited time and effort on the right leads. I managed to whip this up in about two days. It took that long because I had to teach myself Browser Automation, which is in itself is cool.

I also spent time this week resurrecting the pieces of a Forex Trading Bot. After 12 years of blogging and and wanting to do it, I'm finally putting my Trading Bot into 'production.' I use the word production in quotes because it'll run on Oanda's Practice Account first. I want to see if my initial Momentum Strategy will work or not. If it doesn't, I'll come up with another strategy class and go from there.

The best part? I cobbled it all together with the help of Python and Google. Python for scripting it and Google for figuring out where I got stuck. In reality, I owe all my coding skills to Google search (or DuckDuckGo). Stackoverflow and countless blogs have been invaluable to me.

We live in such amazing times. We can learn so many things online now. It requires YOU to take an interest and have the will to learn.


AI Trading & Lehman Brothers?

WOW! I posted this over 12 years ago. Talk about being spot on the money! I hate to do this but I'm going to quote myself here:

I firmly believe that data mining, AI, and machine learning trading will accelerate over the years. Who knows, maybe my little model will move markets one day! :)

As far as the trend in AI goes, it's really getting started now. AI is being adopted by the next tier of companies. We're out of the "innovator" and now "early adopter" phases. We're starting to move into the "early majority" phase, and this is where it gets good.

Adoption Phases Adoption Phase Cycle

I'll write more on this late but I want to go on a tangent here. I'm cracking up. LEH-FUCKING-MAN BROTHERS. WOW. It's amazing what I can find in my archives back then. Remember Lehman Brothers? They blew the fuck up because of bad bets in the MBS markets.

They used to be so 'bad ass' but then they kept too much risk on their balance sheet and the Fed refused to bail them out, they set off the financial crisis. I posted a link to an article a few days later where Richard (Dick) Fuld got punched in the face at the gym. A 150 year company that was destroyed in a matter of days because everyone was greedy.

LEH filed for bankruptcy on September 15, 2008, a little over a year later from my AI post. It's mind boogling, it had $639 Billion in assets with $619 Billion in debt. The charts are damn right frightening but the good news is that AI is still here.

LEH, Daily Chart to collapse Lehman Bros. (LEH) Daily Chart prior to collapse

LEH, Daily Chart prior to collapse Lehman Bros. (LEH) Weekly Chart prior to collapse


Revisiting FXI from 2007

Back in 2007 I thought I had a great trend following system. I was feeling pretty smug about the direction that my AI trend models were giving me (because it was up). Little did I know that I was just lucky. The markets were trending upwards and I was riding their coat tails. So it's fitting that to revisit my FXI calls from 2007 and see where are they now.

FXI then

Back in 2007 I made at least two posts about FXI. I posted this chart and noted that the trend remains still up. FXI was trading around $115 per share.

FXI, 5/12/2007

A little bit later in 2007, FXI split 3:1, so the price got cut by a third. For today's argument, assume the split happened at $115 (it was a bit higher than that).

FXI now

Today FXI is trading at $39.93, which is just over $1 higher than if FXI split at $115. So it did a whole hell of nothing over 12 years. If you look at the chart, it's been nothing but a roller coaster. Up, then down, then up, etc.

FXI, 5/27/2019

Sure you could've picked up some FXI at the bottom of 2009 but who knew it would recover? Sure you could've picked it up when it touched $30 a share a few times over the years but maybe it would've gone lower.

What moral?

What's the moral here? I don't think there is any except that dollar cost averaging is good and buying when people are scared is better.

Seriously though, dollar cost averaging is WAY easier than buying when people are scared because sometimes it's better to stay out of their way. No one wants to catch a falling knife, now do they?


The Ye Old Blog List

Back when I started blogging in 2005-ish, I had a few blogs that destructed due to bad software or databases. My Sixth World News and Commentary site just stopped working one day and I couldn't recover any posts. I was a tech newbie so I didn't know how to do SQL dumps and try to save over a years worth of work.

Wordpress came along and changed all that by making blogging more robust and fun. Then the blog explosion happened. We had Blog Carnivals, blog circle links, many new blogs popping up every week. Over time I made many online friends with many bloggers. I had found my tribe. I posted about the markets, Forex, investing, and machine learning. Suddenly my blog took off because of my RapidMiner tutorials and the rest is history.

12 years later and I discover some old posts that I had archived. I started reposting (backfilling) a lot of those posts and inadvertently took a stroll down memory late. I noticed that a lot of the old links to blogs that no longer work but some still do.

I decided to do some digging and find out whatever happened too...


One of my most favorite blogs was UglyChart. Mike was one of the first people to code all kinds of neat trading intelligence stuff. His 'new all-time highs' and 'new all-time lows' daily list was invaluable. He built a trading bot and posted the trials and tribulations of it on a weekly basis. He's since shut down the blog and is now a successful Domain catcher. Good for him.


Maoxian started his daily day-trading tips back in 2005 with his "Dummy method.' He posted pretty regularly for a long time till he moved to China and back. He was offline for a few years and his posting suffered. Luckily, his blog has survived and he posts semi-weekly now, mostly about movie reviews. Rumor has it he's day trading again and he does share some tidbits here and there. His notes on Trader Interviews are invaluable.


I loved TraderMike's blog. His daily market recaps were the best and he was so sharing with everything he did. He was an electrical engineer turned software developer turned swing trader. He automated a lot of his stock selection and traded the 'swings.' He sold TraderMike several years ago and it's not the same anymore. He's moved on to SwingTradeBot now and appears to be living the dream.


TraderGav is still kicking around but he doesn't post as much as he used too. He's a full-time Forex trader and trading platform developer. We're friends on Facebook and he's busy being a Dad. I loved his Forex chart reads and he's one of the reasons why I got into Forex trading in the first place. Hopefully his blog will be re-energized one day.

Grace Cheng

Grace had a great Forex trading website where she posted her mechanical trading tips for currencies. She wrote a book and become a small sensation in the Forex circles. She has since redirected her site to some credit card reward program site. It looks like she's a busy mom now of two kids and travels the world with her partner. Good for her.


Jaloti cracked me up. Jaloti was just short for "Just another loser on the Internet." He had a brief but funny blog but then disappeared.

Howard Lindzon

Howard burst on the blogging scene back in 2007 with his Wall Strip video show. It was great, hilarious, and he sold it for $60 million to CBS. CBS promptly shut it down (dumbasses). He remains a blogging force to be reckoned with and remade himself from a hedge fund manager to a VC guy that manages a hedge fund. He's the right mix of humor and self-deprecating humor that I love. I have still yet to meet him but I have his mobile number somewhere.

From Blogs too?

It's amazing how fast time goes. Taking a minute to look from where you came from is equally important than just charging ahead too somewhere in the future. Like a lot of the bloggers above, I wrote a lot of blog posts between 2007 and 2010 and then dropped off. I was lucky enough to discover my love of machine learning by writing here. This love landed me a gig with RapidMiner and now H2O.ai.

I'm happy that many of the old bloggers have transformed themselves into some better and/or cooler from their writings as well. That makes me happy. It's amazing what you can do when you're passionate about something. You learn, you create, you make. You see, kids, it's possible to 'live the dream' if you put your passion to paper. At least it is for me.


Mean Reversion Trading Process in RapidMiner

{{<}}RapidMinerLately I've been think about becoming more active in trading again. I was reviewing some strategies and decided to recreate a mean reversion trading process in RapidMiner. I found a mean reversion trading stategy that uses Python here and just recreated it in RapidMiner.

The Process

The process is quite simple. You do the following:

  1. Load in stock quote data via CSV;
  2. Calculate daily returns;
  3. Calculate a 20 day moving average;
  4. Calculate a rolling 90 day standard deviation;
  5. Generate Trading Criteria per the article;
  6. Wrap it all together and look at the Buy vs Hold and Buy Signals.

Mind you, this doesn't include commission costs and slippage. I suspect that once I add that in, the Buy and Hold strategy will be the best.

    <?xml version="1.0" encoding="UTF-8"?><process version="8.1.001">
      <operator activated="true" class="process" compatibility="8.1.001" expanded="true" name="Process">
        <parameter key="encoding" value="SYSTEM"/>
        <process expanded="true">
          <operator activated="true" class="subprocess" compatibility="8.1.001" expanded="true" height="82" name="Load Data" width="90" x="45" y="34">
            <process expanded="true">
              <operator activated="true" class="read_csv" compatibility="8.1.000" expanded="true" height="68" name="Read Downloaded S&amp;P500" width="90" x="45" y="34">
                <parameter key="csv_file" value="C:\Users\TomOtt\Downloads\INTC.csv"/>
                <parameter key="column_separators" value=","/>
                <parameter key="first_row_as_names" value="false"/>
                <list key="annotations">
                  <parameter key="0" value="Name"/>
                <parameter key="encoding" value="windows-1252"/>
                <list key="data_set_meta_data_information">
                  <parameter key="0" value="Date.true.polynominal.attribute"/>
                  <parameter key="1" value="Open.true.real.attribute"/>
                  <parameter key="2" value="High.true.real.attribute"/>
                  <parameter key="3" value="Low.true.real.attribute"/>
                  <parameter key="4" value="Close.true.real.attribute"/>
                  <parameter key="5" value="Adj Close.true.real.attribute"/>
                  <parameter key="6" value="Volume.true.real.attribute"/>
                <description align="center" color="transparent" colored="false" width="126">Due to Yahoo changes, must download CSV file manually for now!</description>
              <operator activated="true" class="series:lag_series" compatibility="7.4.000" expanded="true" height="82" name="Lag Series" width="90" x="179" y="34">
                <list key="attributes">
                  <parameter key="Close" value="1"/>
              <operator activated="true" class="generate_attributes" compatibility="8.1.001" expanded="true" height="82" name="Returns" width="90" x="313" y="34">
                <list key="function_descriptions">
                  <parameter key="Returns" value="(Close-Open)/Open"/>
              <operator activated="true" class="select_attributes" compatibility="8.1.001" expanded="true" height="82" name="Select Attributes for ETL" width="90" x="447" y="34">
                <parameter key="attribute_filter_type" value="single"/>
                <parameter key="attribute" value="^GSPC_CLOSE-1"/>
                <parameter key="invert_selection" value="true"/>
              <operator activated="true" class="series:moving_average" compatibility="7.4.000" expanded="true" height="82" name="MA 20 DAY" width="90" x="581" y="34">
                <parameter key="attribute_name" value="Close"/>
                <parameter key="window_width" value="20"/>
              <operator activated="true" class="series:windowing" compatibility="7.4.000" expanded="true" height="82" name="Window for 90 Day STDEV" width="90" x="715" y="34">
                <parameter key="window_size" value="90"/>
                <parameter key="label_attribute" value="Close"/>
              <operator activated="true" class="generate_aggregation" compatibility="8.1.001" expanded="true" height="82" name="Calc STD Dev for 90 day window" width="90" x="849" y="34">
                <parameter key="attribute_name" value="StDev"/>
                <parameter key="attribute_filter_type" value="regular_expression"/>
                <parameter key="attributes" value="Log Returns-0|Log Returns-1|Log Returns-2|Log Returns-3|Log Returns-4"/>
                <parameter key="regular_expression" value="Close\-[0-9]"/>
                <parameter key="aggregation_function" value="standard_deviation"/>
              <operator activated="true" class="select_attributes" compatibility="8.1.001" expanded="true" height="82" name="Select Attributes" width="90" x="983" y="34">
                <parameter key="attribute_filter_type" value="subset"/>
                <parameter key="attributes" value="Close-0|Date-0|High-0|Low-0|Open-0|StDev|Volume-0|average(Close)-0|Log Returns-0|Returns-0"/>
              <operator activated="true" class="rename" compatibility="8.1.001" expanded="true" height="82" name="Rename a bunch of stuff" width="90" x="1117" y="34">
                <parameter key="old_name" value="Date-0"/>
                <parameter key="new_name" value="Date"/>
                <list key="rename_additional_attributes">
                  <parameter key="Close-0" value="Close"/>
                  <parameter key="High-0" value="High"/>
                  <parameter key="Returns-0" value="Returns"/>
                  <parameter key="Volume-0" value="Volume"/>
                  <parameter key="Low-0" value="Low"/>
                  <parameter key="Open-0" value="Open"/>
                  <parameter key="average(Close)-0" value="MA20"/>
                  <parameter key="StDev" value="90daySTDEV"/>
              <operator activated="true" class="nominal_to_date" compatibility="8.1.001" expanded="true" height="82" name="Convert dates" width="90" x="1251" y="34">
                <parameter key="attribute_name" value="Date"/>
                <parameter key="date_format" value="yyyy-MM-dd"/>
              <operator activated="true" class="series:lag_series" compatibility="7.4.000" expanded="true" height="82" name="Lag Low" width="90" x="1385" y="34">
                <list key="attributes">
                  <parameter key="Low" value="1"/>
              <operator activated="true" class="replace_missing_values" compatibility="8.1.001" expanded="true" height="103" name="Replace Missing Values" width="90" x="1519" y="34">
                <parameter key="attribute_filter_type" value="value_type"/>
                <parameter key="value_type" value="numeric"/>
                <parameter key="default" value="zero"/>
                <list key="columns"/>
              <connect from_op="Read Downloaded S&amp;P500" from_port="output" to_op="Lag Series" to_port="example set input"/>
              <connect from_op="Lag Series" from_port="example set output" to_op="Returns" to_port="example set input"/>
              <connect from_op="Returns" from_port="example set output" to_op="Select Attributes for ETL" to_port="example set input"/>
              <connect from_op="Select Attributes for ETL" from_port="example set output" to_op="MA 20 DAY" to_port="example set input"/>
              <connect from_op="MA 20 DAY" from_port="example set output" to_op="Window for 90 Day STDEV" to_port="example set input"/>
              <connect from_op="Window for 90 Day STDEV" from_port="example set output" to_op="Calc STD Dev for 90 day window" to_port="example set input"/>
              <connect from_op="Calc STD Dev for 90 day window" from_port="example set output" to_op="Select Attributes" to_port="example set input"/>
              <connect from_op="Select Attributes" from_port="example set output" to_op="Rename a bunch of stuff" to_port="example set input"/>
              <connect from_op="Rename a bunch of stuff" from_port="example set output" to_op="Convert dates" to_port="example set input"/>
              <connect from_op="Convert dates" from_port="example set output" to_op="Lag Low" to_port="example set input"/>
              <connect from_op="Lag Low" from_port="example set output" to_op="Replace Missing Values" to_port="example set input"/>
              <connect from_op="Replace Missing Values" from_port="example set output" to_port="out 1"/>
              <portSpacing port="source_in 1" spacing="0"/>
              <portSpacing port="sink_out 1" spacing="0"/>
              <portSpacing port="sink_out 2" spacing="0"/>
              <description align="center" color="yellow" colored="false" height="174" resized="false" width="180" x="24" y="231">The goal is to pull this data from a database in the future.&lt;br/&gt;&lt;br/&gt;The database will be populated with stock data from the Nasdaq automatically overnight using EOD</description>
            <description align="center" color="transparent" colored="false" width="126">Load CSV data</description>
          <operator activated="true" class="generate_attributes" compatibility="8.1.001" expanded="true" height="82" name="Generate Trading Signal" width="90" x="179" y="34">
            <list key="function_descriptions">
              <parameter key="Criteria1" value="if((Open&lt;[Low-1]) &amp;&amp; (Open-[Low-1])&lt;-[90daySTDEV],1,0)"/>
              <parameter key="Criteria2" value="if(Open&gt;MA20,1,0)"/>
              <parameter key="Signal" value="if(([Criteria1]+[Criteria2])==2,1,0)"/>
          <operator activated="true" class="select_attributes" compatibility="8.1.001" expanded="true" height="82" name="Select Final Col" width="90" x="313" y="34">
            <parameter key="attribute_filter_type" value="subset"/>
            <parameter key="attributes" value="Close|Date|Signal|Returns"/>
          <operator activated="true" class="multiply" compatibility="8.1.001" expanded="true" height="82" name="Multiply (2)" width="90" x="447" y="34"/>
          <operator activated="true" class="subprocess" compatibility="8.1.001" expanded="true" height="103" name="Cum Sum of Returns" width="90" x="581" y="34">
            <process expanded="true">
              <operator activated="true" class="multiply" compatibility="8.1.001" expanded="true" height="103" name="Multiply (3)" width="90" x="112" y="34"/>
              <operator activated="true" class="series:integrate_series" compatibility="7.4.000" expanded="true" height="82" name="All Signals" width="90" x="447" y="289">
                <parameter key="attribute_name" value="Returns"/>
              <operator activated="true" class="filter_examples" compatibility="8.1.001" expanded="true" height="103" name="Filter Examples (2)" width="90" x="313" y="34">
                <list key="filters_list">
                  <parameter key="filters_entry_key" value="Signal.eq.1"/>
              <operator activated="true" class="series:integrate_series" compatibility="7.4.000" expanded="true" height="82" name="Buy Signal Only" width="90" x="447" y="34">
                <parameter key="attribute_name" value="Returns"/>
              <operator activated="true" class="rename" compatibility="8.1.001" expanded="true" height="82" name="Buy Returns" width="90" x="581" y="34">
                <parameter key="old_name" value="cumulative(Returns)"/>
                <parameter key="new_name" value="Buy Signals Returns"/>
                <list key="rename_additional_attributes"/>
              <operator activated="true" class="rename" compatibility="8.1.001" expanded="true" height="82" name="Buy and Hold Returns" width="90" x="581" y="289">
                <parameter key="old_name" value="cumulative(Returns)"/>
                <parameter key="new_name" value="Buy and Hold"/>
                <list key="rename_additional_attributes"/>
              <connect from_port="in 1" to_op="Multiply (3)" to_port="input"/>
              <connect from_op="Multiply (3)" from_port="output 1" to_op="Filter Examples (2)" to_port="example set input"/>
              <connect from_op="Multiply (3)" from_port="output 2" to_op="All Signals" to_port="example set input"/>
              <connect from_op="All Signals" from_port="example set output" to_op="Buy and Hold Returns" to_port="example set input"/>
              <connect from_op="Filter Examples (2)" from_port="example set output" to_op="Buy Signal Only" to_port="example set input"/>
              <connect from_op="Buy Signal Only" from_port="example set output" to_op="Buy Returns" to_port="example set input"/>
              <connect from_op="Buy Returns" from_port="example set output" to_port="out 1"/>
              <connect from_op="Buy and Hold Returns" from_port="example set output" to_port="out 2"/>
              <portSpacing port="source_in 1" spacing="0"/>
              <portSpacing port="source_in 2" spacing="0"/>
              <portSpacing port="sink_out 1" spacing="0"/>
              <portSpacing port="sink_out 2" spacing="0"/>
              <portSpacing port="sink_out 3" spacing="0"/>
              <description align="center" color="yellow" colored="false" height="105" resized="false" width="180" x="337" y="147">Set the previous value to the missing value</description>
          <operator activated="false" class="subprocess" compatibility="8.1.001" expanded="true" height="103" name="Subprocess" width="90" x="581" y="289">
            <process expanded="true">
              <operator activated="true" class="series:windowing" compatibility="7.4.000" expanded="true" height="82" name="Window for Training" width="90" x="45" y="187">
                <parameter key="window_size" value="1"/>
                <parameter key="create_label" value="true"/>
                <parameter key="label_attribute" value="Signal"/>
                <parameter key="add_incomplete_windows" value="true"/>
              <operator activated="true" class="concurrency:optimize_parameters_grid" compatibility="8.1.001" expanded="true" height="124" name="Optimize Parameters (Grid)" width="90" x="179" y="34">
                <list key="parameters">
                  <parameter key="Backtesting.test_window_width" value="[2;5;4;linear]"/>
                  <parameter key="Backtesting.training_window_step_size" value="[1;5;4;linear]"/>
                  <parameter key="Backtesting.training_window_width" value="[2;5;4;linear]"/>
                  <parameter key="SVM for HV Calc.kernel_gamma" value="[0.01;1000;5;logarithmic]"/>
                  <parameter key="SVM for HV Calc.C" value="[0;10000;2;linear]"/>
                <process expanded="true">
                  <operator activated="true" class="series:sliding_window_validation" compatibility="7.4.000" expanded="true" height="124" name="Backtesting" width="90" x="179" y="34">
                    <parameter key="training_window_width" value="6"/>
                    <parameter key="test_window_width" value="6"/>
                    <parameter key="cumulative_training" value="true"/>
                    <process expanded="true">
                      <operator activated="true" class="support_vector_machine" compatibility="8.1.001" expanded="true" height="124" name="SVM for HV Calc" width="90" x="179" y="34">
                        <parameter key="kernel_type" value="radial"/>
                        <parameter key="kernel_gamma" value="0.10000000000000002"/>
                        <parameter key="C" value="200.0"/>
                      <connect from_port="training" to_op="SVM for HV Calc" to_port="training set"/>
                      <connect from_op="SVM for HV Calc" from_port="model" to_port="model"/>
                      <portSpacing port="source_training" spacing="0"/>
                      <portSpacing port="sink_model" spacing="0"/>
                      <portSpacing port="sink_through 1" spacing="0"/>
                    <process expanded="true">
                      <operator activated="true" class="apply_model" compatibility="7.1.001" expanded="true" height="82" name="Apply Model In Testing" width="90" x="45" y="34">
                        <list key="application_parameters"/>
                      <operator activated="true" class="series:forecasting_performance" compatibility="7.4.000" expanded="true" height="82" name="Forecast Performance" width="90" x="246" y="34">
                        <parameter key="horizon" value="1"/>
                        <parameter key="main_criterion" value="prediction_trend_accuracy"/>
                      <connect from_port="model" to_op="Apply Model In Testing" to_port="model"/>
                      <connect from_port="test set" to_op="Apply Model In Testing" to_port="unlabelled data"/>
                      <connect from_op="Apply Model In Testing" from_port="labelled data" to_op="Forecast Performance" to_port="labelled data"/>
                      <connect from_op="Forecast Performance" from_port="performance" to_port="averagable 1"/>
                      <portSpacing port="source_model" spacing="0"/>
                      <portSpacing port="source_test set" spacing="0"/>
                      <portSpacing port="source_through 1" spacing="0"/>
                      <portSpacing port="sink_averagable 1" spacing="0"/>
                      <portSpacing port="sink_averagable 2" spacing="0"/>
                  <connect from_port="input 1" to_op="Backtesting" to_port="training"/>
                  <connect from_op="Backtesting" from_port="model" to_port="model"/>
                  <connect from_op="Backtesting" from_port="averagable 1" to_port="performance"/>
                  <portSpacing port="source_input 1" spacing="0"/>
                  <portSpacing port="source_input 2" spacing="0"/>
                  <portSpacing port="sink_performance" spacing="0"/>
                  <portSpacing port="sink_model" spacing="0"/>
                  <portSpacing port="sink_output 1" spacing="0"/>
              <operator activated="true" class="series:windowing" compatibility="7.4.000" expanded="true" height="82" name="Window for Prediction" width="90" x="179" y="289">
                <parameter key="window_size" value="1"/>
              <operator activated="true" class="apply_model" compatibility="7.1.001" expanded="true" height="82" name="Apply SVM model" width="90" x="380" y="136">
                <list key="application_parameters"/>
              <connect from_port="in 1" to_op="Window for Training" to_port="example set input"/>
              <connect from_op="Window for Training" from_port="example set output" to_op="Optimize Parameters (Grid)" to_port="input 1"/>
              <connect from_op="Window for Training" from_port="original" to_op="Window for Prediction" to_port="example set input"/>
              <connect from_op="Optimize Parameters (Grid)" from_port="performance" to_port="out 1"/>
              <connect from_op="Optimize Parameters (Grid)" from_port="model" to_op="Apply SVM model" to_port="model"/>
              <connect from_op="Window for Prediction" from_port="example set output" to_op="Apply SVM model" to_port="unlabelled data"/>
              <connect from_op="Apply SVM model" from_port="labelled data" to_port="out 2"/>
              <portSpacing port="source_in 1" spacing="0"/>
              <portSpacing port="source_in 2" spacing="0"/>
              <portSpacing port="sink_out 1" spacing="0"/>
              <portSpacing port="sink_out 2" spacing="0"/>
              <portSpacing port="sink_out 3" spacing="0"/>
          <connect from_op="Load Data" from_port="out 1" to_op="Generate Trading Signal" to_port="example set input"/>
          <connect from_op="Generate Trading Signal" from_port="example set output" to_op="Select Final Col" to_port="example set input"/>
          <connect from_op="Select Final Col" from_port="example set output" to_op="Multiply (2)" to_port="input"/>
          <connect from_op="Multiply (2)" from_port="output 1" to_op="Cum Sum of Returns" to_port="in 1"/>
          <connect from_op="Cum Sum of Returns" from_port="out 1" to_port="result 1"/>
          <connect from_op="Cum Sum of Returns" from_port="out 2" to_port="result 2"/>
          <portSpacing port="source_input 1" spacing="0"/>
          <portSpacing port="sink_result 1" spacing="0"/>
          <portSpacing port="sink_result 2" spacing="0"/>
          <portSpacing port="sink_result 3" spacing="0"/>
          <description align="center" color="yellow" colored="false" height="120" resized="false" width="180" x="31" y="195">Position Sizing?&lt;br&gt;Need to add: &lt;br&gt;Volatility based position sizing&lt;br&gt;buy and sell = $7, no slippage</description>

PS: to test this, just go to Yahoo Finance and download historical quote data for a stock and then repath it in the Read CSV operator. Use at least a 2 year time period.

Next Steps

I still have several 'kink's to work out but I can definitely see the opportunity for optimization here, such as:

  • Why use a rolling 90 day window? Use parameter optimization to vary that value from 50 to 100.
  • Why use a 20 day moving average? You could vary between a 10 or 30 day MA?
  • Write a python script to download EOD stock data and then have RapidMiner loop through it.
  • Write an commission and slippage subprocess to see if this method IS really profitable or not.
  • Offload the processes to a RapidMiner Server and have it spit out trading recommendations on a daily basis


Neural Market Trends is the online home of Thomas Ott.