Category Archives: strategy

Quantshare Trading Software on Amazon’s EC2

I wrote an article on how to automate the process of updating quotes, updating multiple trading strategies and e-mailing next day signals form the cloud to our own e-mail boxes. This time I am using QuantShare as the trading software and an Amazon EC2 micro instance as the host cloud.

You can read the article at the QuantShare Blog.
More…

QuantShare is a fairly new piece of software that can be used to develop and backtest trading strategies. It has many features (I will get into them in another article/review). I will just go through a few that interest me. Keep in mind that most of my system backtesting and development has been done in Amibroker.

1. It has a similar “language” and array based logic as Amibroker. That means one can develop quickly in Amibroker and then “detail” the strategy in QuantShare. More…

2. You can write a Money Management script in C# to extend the rules of the main strategy.
 More…

3. You can write your own indicators in C# and then call them from the array based language as functions.

4. It has a genetic optimizer that works with a “Rules” list. You can combine rules and “auto-generate” systems in minutes. Or better, take your existing system and “look” for filters or additional rules that might improve it.
 More

5. QS uses custom databases. They can hold quotes, fundamentals  Yahoo news, tweets, COT data, whatever. It has a downloaded tool that can be customized to handle all kinds of downloads and update the database. Ready made downloaders exists for different markets. These historical databases can then be called from the backtester. More…

6. There is a community and ready made “scripts” that can be downloaded through the “Sharing Server“.

7. You can “combine” systems. So you can see the equity curve of trading MySystem1 with MySystem2 and… MySystemN.  More…

8. Reasonably priced.

So what’s the downside?
The real-time version is still in Beta as of this writing ( 28/10/2012).  So you cannot connect to a broker or auto-trade, yet.

Amibroker – From Backtest to Trading – Going Live

Going Into Production 

So you have a system in Amibroker that you backtested and you are happy with. You now want to go “into production”.
How do you get your signals? How do you keep track of open orders, position sizes, ranking rules, etc. It’s not as easy as it may seem.

Explore or Scan?

If you try to run scans or explorations you will get Buy/Sell signals but how many? If you have 500 symbols and you trade the top 10 and your size varies with each stock’s ATR, you will have to rank the first 10 and compute, atr’s and position sizes and bla..bla..bla.. Do that day in day out… You will make a mistake.


Just Backtest!

In every Backtested system there are assumptions. Position Sizing, Ranking rules, skipping signals or not, etc. One way to keep track of all those things is to let Amibroker do it for you.

The following example assumes 
a. You use no stops
b You trade End Of Day at tommorow’s open or tommorow’s close.



Here are the steps.
1. Go to Amibroker and backtest your formula as usual. Check everything is ok, Commisions, Initial Equity, etc… Check that your backtested equity curve is what it should be.

2.Open the Backtester Setting.

3. In the Portfolio Tab, check the “Add artificial future bar” box.

** If you are trading ETF’s you might want to set “Limit trade size as % of entry bar volume” to 0.

4. Under Report select “Detailed  Log”.

5. From to Dates: Start today or a month ago depending on wether you are starting from 0 or synching with the current state of your system** (i.e. it is a long term system that holds Gold for 3 years now).
End day can be sometime in the far future: 1/1/2020

6. Check your margin if you are trading stocks. Max should be 50 (i.e.2x leverage) or higher if your broker allows for that. If you want no leverage set it to 100.

6a. Run the backtest. You should see a list. The last item should be for tommorow’s trade.

Here you have the orders ready for you to follow. The Position sizing rules and ranking are done for you. All you have to do is synch to the system (the first time) and then follow it every day (or week or month depending on your system).

Automating it

7. Save the .apx file that incorporates all your setting.
While the Analysis Window is selected and you are happy with all the settings go to Amibroker menu, and select File—>Save As.  A window will ask you where to save the file. Choose the folder where your AFL system formula is (or any other folder you want). Give it a name (My_System_1_Live) and save it as .apx, the default. Now you should have a My_System_1_Live.apx file that is all you need to backtest this strategy.

8. Write a Jscript.
a. Create a new NotePad test document
b. Paste this code and save it not as txt but as .js. Replace the file locations with your own.

//——-Code adapted form Thomaz’s code

var WshShell= new ActiveXObject(“Wscript.Shell”);
AB = new ActiveXObject( “Broker.Application” ); // creates AmiBroker object
try
{
// opens previously saved analysis project file
    NewA = AB.AnalysisDocs.Open(“C:Program FilesAmiBrokerFormulasMy_System_1_Live.apx ” );
    // NewA represents the instance of New Analysis document/window
    if ( NewA )
    {
         NewA.Run( 2 ); // start backtest asynchronously
         while ( NewA.IsBusy ) WScript.Sleep( 500 ); // check IsBusy every 0.5 second
        NewA.Export( “C:UsersUserMeDesktopLiveSystemsMy_System_1_Live .csv” );
         NewA.Close(); // close new Analysis
     }
else
     WshShell.Popup (“NewA problem”, 3,”Active X problem”,0);
}
catch ( err )

{
   //Email_Event(” failed to run”,”Exception: ” + err.message);
     WshShell.Popup (“Active X problem”+”Exception: ” + err.message, 3,”Active X problem”,0);
}
//end code

For example save it as “Run_Backtest_Sys_1.js
Saving it as a “.js” make it an executable JScript under windows.

9. Double clicking on it will run run it. It will launch Amibroker, open the .apx file you specified, backtest your system and export a report at the location you also specify.

10. Open the .csv file. You should see the backtester’s results. The last lines should be tommorow’s trades.

11. (Oprional) Parse the .csv file.
If you are good at jScript or VBscript you can write a script that will go to tommorow’s entries and parse them into arrays. You can then export clean csv’s or e-mail yourself the signals or drive a virtual system at Collective 2 or email your broker.

What about Stops?  
Using the Custom Backtester Object.

There’s many ways to do teh same thing. Here’s teh code for retrieving tommorow’s trades (and stops or other variables) using Amibroker’s Custom Backtester.

//-One way to get tommorow’s signals – 
//Make sure “Add artificial bar for tommorow”, under Backtest Settings–>Portfolio Tab is checked to //get tommorow’s trade
///////////////Put your system HERE/////////////////////
Buy=Cross(30,RSI(15));
Sell=Cross(RSI(15),70);
SetTradeDelays(1,1,1,1);
BuyPrice=SellPrice=0;
/////////////////////End System ///////////////////

////////////Variable that you need to report/////////////
stoploss=C-3*ATR(10);
StaticVarSet(Name()+”SL”,(stoploss));//place the stoploss inside a staticvar array. Include Name!
/////////////////////////////////////////////////

////////////////////////////Code for custom report///////////
//Make sure “Add artificial bar for tommorow”, under Backtest Settings–>Portfolio Tab is checked to //get tommorow’s trade
idx = BarIndex();
d = Day();
m = Month();
y = Year();
trace=1;
action=””;
Datestr=””;
report=””;

SetCustomBacktestProc( “” );
if ( Status( “action” ) == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.PreProcess();
    for ( bar = 0; bar < BarCount; bar++ )
    {
        bo.ProcessTradeSignals( bar );
        CurEquity = bo.Equity;
//if bar is the last bar on the chart set Date
     if(bar==BarCount-1)  Datestr= “n” + “n” + d[bar] + “/” + m[bar] + “/” + y[bar] ;

        for ( openpos = bo.GetFirstOpenPos(); openpos; openpos = bo.GetNextOpenPos() )
        {
SL=LastValue(Nz(StaticVarGet(Openpos.Symbol()+”SL”))); // Get the stop loss from the static array
if(Openpos.IsLong()) action=”Buy”; else action=”Sell”;

              if(bar==BarCount-1)  //only continue if we are at the last bar (i.e tommorow’s trade)
{
report= action+”  “+Openpos.Symbol()+ ”  “+ openpos.Shares()+” shares”+” Set Stop Loss @: “+ SL+”n” ;

PopupWindow(datestr+” n “+report,”Your Trades”,10);
Say(report+” and please remember to enjoy the rest of your day”, purge = True) ;
//AlertIf( True, “EMAIL”, datestr+” n “+report, 1 );

}
            
        }
    }

    bo.PostProcess(); // Finalize backtester
}

Uncover Hidden Market Relationships Using Fuzzy Logic

In the previous posts (pt1, pt.2,  pt.3) we talked a bit about how to take various indicators and fuzzify them.

Now I will show how we can quickly test for relationships in indicators.
So the question is: Can we only use RSI(3) and RSI(14) (short term and medium term Relative Strength Index) to trade the S&P500?
So in the Fuzzy Model afl script that I wrote, we input rsi3 and rsi14 as inputs and “Low,Neutral,High” as qualifiers.

We then let it optimize using the  CM-AES non-exhaustive optimizer (with all default settings). After a couple of minutes we get the results:

So the rules that the optimizer came up with are:

rule   0   rsi3  Low  AND  rsi14   Low  Then  SELL
rule   1   rsi3  Low  AND  rsi14   Neutral  Then  Do NOTHING
rule   2   rsi3  Low  AND  rsi14   High  Then  BUY
rule   3   rsi3  Neutral  AND  rsi14   Low  Then  Do NOTHING
rule   4   rsi3  Neutral  AND  rsi14   Neutral  Then  BUY
rule   5   rsi3  Neutral  AND  rsi14   High  Then  Do NOTHING
rule   6   rsi3  High  AND  rsi14   Low  Then  Do NOTHING
rule   7   rsi3  High  AND  rsi14   Neutral  Then  SELL
rule   8   rsi3  High  AND  rsi14   High  Then  SELL

Do these make sense? Unlike Neural Networks, these rules can be read and checked by common sense. What the above rules tell us is that:

Rule 2:
Buy when rsi14 is high (meaning we are in a mid-term bullish move) and rsi3 is low (meaning we are at a short-term correction). That does make sense!
rule   4 :
  rsi3  Neutral  AND  rsi14   Neutral  Then  BUY – Hmmm… This is another way of saying that SPY has a positive bias overall.

Many more possibilities

No-ones restricts us to a 2 input model (although complexity goes up extremely fast). No one also restricts us to oscillator-type of indicators. One can try the same with COT (commitment of traders) data or with the price of Gold vs Price of Bonds ratio or whatever. The bottom line is that this tool can help you search for fairly robust and linguistic base strategies that can be cross-checked with common sense.

Here is some interesting links:

http://www.nisis.risk-technologies.com/events/symp2007/papers/BB25_p_kaymak.pdf
http://www.iaeng.org/publication/WCE2007/WCE2007_pp142-147.pdf
http://www.cs.wayne.edu/~mdong/fuzzytech.pdf
http://sedok.narod.ru/s_files/poland/Dourra_Siy.pdf

* I am neither a programmer nor a fuzzy logic expert. The information given is to the best of my ability/knowledge and meant to un-intimidate and motivate self directed investors to use tools that proffesional Quants use. The information is not necessarily written with accuracy in mind but with practical usability for someone who trades.

The case for Fuzzy Logic in Trading – Pt. 2: Amibroker

Backtesting Fuzzy Logic in Amibroker

In pt.1 we backtested a “fuzzified” trading strategy in Matlab (read part 1):

Buy when RSI(3) is Low and it’s before Expiration week.

Although it was easy to develop this fuzzy model in Matlab, due to the intuitive GUI, it is difficult to get meaningful backtest results, visual signals, statistics and, of course, portfolio level backtesting. Everything is possible in Matlab but it takes considerable time and effort. I would rather backtest in Amibroker and get all my usual statistics, equity curves, visual arrows, as well as 1 click portfolio backtesting.

So how do we code this in Amibroker?

Again here’s the basic idea:

You can say buy when RSI(3)<25
Or you can say Buy when  RSI(3)  is fairly Low
You can say Buy on Monday of Expiration Week
Or Buy around the middle of the month.

I will be using some custom functions I developed:

//Let’s keep these for reference
 indicators = “rsi3,Day_M”;
Property_ind1 = “Low,Neutral,High”;
Property_ind2 = “EarlyMonth,AroundExpirationWeek,EndMonth”;

Output = “Action”;
Property_Action = “Buy,Hold,Sell”;

  RSI3 = RSI( 3 ); //0-100
  Day_M = Day(); //1-31

 SetMember(  “rsi3”, “Low”, TRIMember( rsi3, -40.5, 0.475, 40.34 ) );
 SetMember(  “rsi3”, “Neutral”, TRIMember( rsi3, 10, 50, 90 ) );
 SetMember(  “rsi3”, “High”, TRIMember( rsi3, 60, 100, 140 )  );
 SetMember( “Day_M”, “EarlyMonth”,  GaussMember( Day_M, 5.27, -0.164 )  );
 SetMember( “Day_M”, “AroundExpirationWeek”,  GaussMember( Day_M, 3.94, 15.83 ) );
 SetMember( “Day_M”, “EndMonth”, GaussMember( Day_M, 5.266, 31) );
Now, these are custom functions:
SetMember() creates an array named “rsi3Low”, and fills it with values from TRIMember() function.
TRIMember() function “transforms” the RSI(3) values to a membership function [0 1] of ‘Low” Rsi.
If the above make no sense, don’t worry, it’s much easier than you think.
Now, how did these numbers come up: TRIMember( rsi3, -40.5, 0.475, 40.34 ).
Well if you look at the Matlab membership function we created in the last post, these are the numbers under “parameters”.
In other words   
SetMember(  “rsi3”, “Low”, TRIMember( rsi3, -40.5, 0.475, 40.34 ) );
 SetMember(  “rsi3”, “Neutral”, TRIMember( rsi3, 10, 50, 90 ) );
 SetMember(  “rsi3”, “High”, TRIMember( rsi3, 60, 100, 140 )  );
is basically this:

and

 SetMember( “Day_M”, “EarlyMonth”,  GaussMember( Day_M, 5.27, -0.164 )  );
 SetMember( “Day_M”, “AroundExpirationWeek”,  GaussMember( Day_M, 3.94, 15.83 ) );
 SetMember( “Day_M”, “EndMonth”, GaussMember( Day_M, 5.266, 31) );
is this:

So now we’ll use two more custom functions that create the rules
1. FuzzyAndInf() – Stands for Fuzzy “AND” inference
2.FuzzyInf()

   FuzzyAndInf( 0, “rsi3”, “Low”, “Day_M”, “AroundExpirationWeek”, “Action”, 1 );
   FuzzyAndInf( 1, “rsi3”, “High”, “Day_M”, “EarlyMonth”, “Action”, -1 );
   FuzzyInf(    2, “rsi3”, “High” , “Action”, -1 );

that roughly corresponds to these statements:
If RSI(3) is Low and it’s AroundExpirationWeek then Action is Buy 
If RSI(3) is High and it’s  EarlyMonth  then Action is Sell
If RSI(3) is High then Sell

Then we have to weight the rules and defuzzify. Here  I will simplify things since I cannot yet code a proper output membership function and de-fuzzify algorithm (help would be appreciated from math inclined people…).

Anyways, here are the reults. Remember this is a very simple concept of low RSI and expiration week positive bias…

1. SPY from 1995-August 2012
2. $0.006 commission per trade
3. Start with 100,000. Long only

Profit = 1359462.71 (1359.46%),
CAR = 16.37%,
MaxSysDD = -358582.04 (-43.88%),
CAR/MDD = 0.37,
# winners = 363 (68.75%),
 # losers = 165 (31.25%)

So here’s the whole code:

 indicators = “rsi3,Day_M”;
Property_ind1 = “Low,Neutral,High”;
Property_ind2 = “EarlyMonth,AroundExpirationWeek,EndMonth”;
Output = “Action”;
Property_Action = “Buy,Hold,Sell”;

    RSI3 = RSI( 3 ); //0-100
    Day_M = Day(); //1-31

    SetMember(  “rsi3”, “Low”, TRIMember( rsi3, -40.5, 0.475, 40.34 ) );
    SetMember(  “rsi3”, “Neutral”, TRIMember( rsi3, 10, 50, 90 ) );
    SetMember(  “rsi3”, “High”, TRIMember( rsi3, 60, 100, 140 )  );

    SetMember( “Day_M”, “EarlyMonth”,  GaussMember( Day_M, 5.27, -0.164 )  );
    SetMember( “Day_M”, “AroundExpirationWeek”,  GaussMember( Day_M, 3.94, 15.83 ) );
    SetMember( “Day_M”, “EndMonth”, GaussMember( Day_M, 5.266, 31) );

    FuzzyAndInf( 0, “rsi3”, “Low”, “Day_M”, “AroundExpirationWeek”, “Action”, 1 );
  FuzzyAndInf( 1, “rsi3”, “High”, “Day_M”, “EarlyMonth”, “Action”, -1 );
    FuzzyInf(    2, “rsi3”, “High” , “Action”, -1 );
//FuzzyAndInf( 3, “rsi3”, “Low”, “Day_M”, “EndMonth”, “Action”, 0 );

   weight=0;
    weight[0]=Param( “w0”, 1, 0.1, 1, 0.1 );
    weight[1]=Param( “w1”, 1, 0.1, 1, 0.1 );
    weight[2]=Param( “w2”, 1, 0.1, 1, 0.1 );
   // weight[3]=Param( “w3”, 1, 0.1, 1, 0.1 );

 Sellout = Holdout = Buyout = 0;

    for ( k = 0;k <= 2;k++ )
    {
        Buyout = Buyout +( Nz( getRuleRes( 1, k ) ) ) * weight[k];
        Holdout = Holdout +( Nz( getRuleRes( 0, k ) ) ) * weight[k];
        Sellout = Sellout + (Nz( getRuleRes( -1, k ) ) )* weight[k];
    }

    decision = ( 0 * Sellout + 0.5 * Holdout + 1 * Buyout ) / ( Sellout + Holdout + Buyout );
   decision=IIf( ( Sellout + Holdout + Buyout )==0,0 ,decision );

//Plot(decision,”decision”,colorRed);

Buy=decision>0.5;
Sell=decision<0.5;

Trading with Fuzzy Logic

The case for Fuzzy Logic in Trading

The more I backtest strategies the more I feel the need for robustness in a system. There is no point to optimize return. One should optimize certainty of positive return. Most strategies that do really well in the past are over complicated and over-fitted and tend to loose money.

One way to achieve robust results is to use approximate values.

You can say buy when RSI(3)<25
Or you can say Buy when  RSI(3)  is fairly Low

You can say Buy on Monday of Expiration Week
Or Buy around the middle of the month.

So here’s a system:
Buy when RSI(3) is Low and we are before Expiration week. Let’s test it.
How do we code this in
1. Matlab
2. Amibroker

1. Matlab –
First we construct a Fuzzy Model that will take 2 Inputs
a. RSI(3)
b.DayofMonth     (i.e., 1…31)

Type “fuzzy” in the Terminal and voila…
We then add a second input and name both.


Set the ranges, 0-100 for rsi3 and 1-31 for day of month.
We then move around the MF’s (memebership functions) until we come up with this:

We then come up with the rules:
If rsi is low and month is around the middle then Buy
If rsi is high and month is early Sell
if rsi is High then Sell

Here’s what the rules look like visually:

The Lower the RSI the closer to 1 the output.
The More in the middle of the month the closer to 1 the output.
Keep in mind the Output ranges from 0 to 1. Towards 1 is Buy, towards 0 is Sell.

Here’s how the fuzzy model incorporates the “Common sense” non linearity (for a simple 2 input model)

This may look “scientific” but all it does is say “I like Mid-month and Low RSI”.

So now we have our model. We will save it as “RSI3_ExpWeek_Fis.fis”.

Now on to the script. We need daily prices of SPY to calculate RSI(3) and the day number. We ‘ll get it from Yahoo.

%START CODE

 %Download “SPY” from Yahoo
ticker_fints=GetTickerV(‘SPY’,’15y’,’d’);

DatesinCode=ticker_fints.dates;
close=fts2mat(ticker_fints.close);
open=fts2mat(ticker_fints.open);
dayofmonth=day(DatesinCode);
rsi3=rsi(close,3);

inputs=[rsi3 dayofmonth];

%open the fis model
b = readfis(‘RSI3_ExpWeek_Fis.fis’);

%Feed the inputs and get result (0…1)
result=evalfis(inputs,b);

%if result <0.5 Buy, else Sell
signal=iif(result>0.5,1,iif(result<0.5,-1,0));

[pnl,pnlvector, sh]= backtestlongAmount(ticker_fints,signal,’open’,1,100000);

%END CODE

*This code uses Custom Functions. Read the article and download them  here.
So how did we do?

On the next post I will show how to code this in Amibroker.