Traders' Tip text
This month's issue puts the focus on a set of price pivot levels called “Camarilla Points”. In contrast with classic pivots, they bring the benefit of being closer together, thus providing more action to intraday traders.
Our rendition of the Camarilla Point idea requires intraday data. The support and resistance levels are determined using previous trading session's daily high, low and close prices. However, trades are entered on an intraday basis and always closed at the end of trading session. Additionally, we introduced a limit of a single trade per day to avoid whipsaws. It's possible to choose any type of trade: inside S3/R3, outside S3/R3, and breakouts from S4/R4 levels.
Figure 1. This 5-minute chart of QQQ illustrates the application of the multi-timeframe Camarilla Points breakout & reversion trading system. The two trades was caused by the market opening inside S3/R3 thresholds.The system's unabridged C# code for Wealth-Lab can be found below. On a closing note, motivated traders may also want to explore “Woodies Pivots” – whose difference from the rest of the breed (floor trader pivots, Camarilla points or Fibonacci pivots) is that they introduce today's open price into the formula.
WealthScript Code (C#)
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
/// <summary>
/// Camarilla Point calculation
/// </summary>
public class Camarilla
{
#region Properties
private double _r1;
public double R1
{
get { return _r1;}
set { _r1 = value;}
}
private double _r2;
public double R2
{
get { return _r2;}
set { _r2 = value;}
}
private double _r3;
public double R3
{
get { return _r3;}
set { _r3 = value;}
}
private double _r4;
public double R4
{
get { return _r4;}
set { _r4 = value;}
}
private double _r5;
public double R5
{
get { return _r5;}
set { _r5 = value;}
}
private double _s1;
public double S1
{
get { return _s1;}
set { _s1 = value;}
}
private double _s2;
public double S2
{
get { return _s2;}
set { _s2 = value;}
}
private double _s3;
public double S3
{
get { return _s3;}
set { _s3 = value;}
}
private double _s4;
public double S4
{
get { return _s4;}
set { _s4 = value;}
}
private double _s5;
public double S5
{
get { return _s5;}
set { _s5 = value;}
}
#endregion
public Camarilla()
{
Clear();
}
public void FindPivotLevels( double high, double low, double close )
{
R1 = 0; R2 = 0; R3 = 0; R4 = 0; R5 = 0;
S1 = 0; S2 = 0; S3 = 0; S4 = 0; S5 = 0;
double Range = high - low;
R5 = ( high / low ) * close;
R4 = close + Range * 1.1 / 2;
R3 = close + Range * 1.1 / 4;
R2 = close + Range * 1.1 / 6;
R1 = close + Range * 1.1 / 12;
S1 = close - Range * 1.1 / 12;
S2 = close - Range * 1.1 / 6;
S3 = close - Range * 1.1 / 4;
S4 = close - Range * 1.1 / 2;
S5 = close - (R5 - close);
}
public void Clear()
{
R1 = 0; R2 = 0; R3 = 0; R4 = 0; R5 = 0;
S1 = 0; S2 = 0; S3 = 0; S4 = 0; S5 = 0;
}
}
public class CamarillaPointsStrategy : WealthScript
{
enum Entry { Inside, Outside, Breakout };
private StrategyParameter paramEntryType;
public CamarillaPointsStrategy()
{
paramEntryType = CreateParameter("In/Out/Brk", 0, 0, 2, 1);
}
protected override void Execute()
{
if ( !Bars.IsIntraday )
{
DrawLabel( PricePane, "For use on intraday data", Color.Red );
Abort();
}
// Change scale to Daily
HideVolume();
SetScaleDaily();
Bars dailyBars = Bars;
DataSeries CompBar = new DataSeries(Bars, "Compressed Bar Numbers");
for (int bar = 0; bar < Bars.Count; bar++)
CompBar[bar] = bar;
RestoreScale();
dailyBars = Synchronize(dailyBars);
DataSeries GetDailyBar = Synchronize(CompBar);
// Initialize an instance of the CamarillaPoint class
Camarilla c = new Camarilla();
double tick = Bars.SymbolInfo.Tick;
bool enterTrades = true;
bool canTrade = true;
Entry e = paramEntryType.ValueInt == 0 ? Entry.Inside : paramEntryType.ValueInt == 1 ? Entry.Outside : Entry.Breakout;
// Main (trading) loop
SetBarColors( Color.Silver, Color.DarkGray );
for(int bar = 1; bar < Bars.Count; bar++)
{
#region Variables
int dailyBar = (int)GetDailyBar[bar];
int firstBarToday = bar - Bars.IntradayBarNumber(bar);
double openToday = Open[firstBarToday];
bool lastBarToday = Bars.IsLastBarOfDay( bar );
if( ( bar == 1 || lastBarToday ) )
canTrade = true;
if( lastBarToday )
enterTrades = false;
#endregion
#region Determine Camarilla Point levels
if( firstBarToday > -1 )
{
if( Bars.IntradayBarNumber(bar) == 0 )
{
c.FindPivotLevels( dailyBars.High[bar], dailyBars.Low[bar], dailyBars.Close[bar] );
}
if( Bars.IsLastBarOfDay(bar) )
{
DrawLine( PricePane, bar, c.S3, firstBarToday, c.S3, Color.Blue, LineStyle.Dashed, 1 );
DrawLine( PricePane, bar, c.R3, firstBarToday, c.R3, Color.Red, LineStyle.Dashed, 1 );
DrawLine( PricePane, bar, c.S4, firstBarToday, c.S4, Color.FromArgb(100,Color.Blue), LineStyle.Dashed, 1 );
DrawLine( PricePane, bar, c.R4, firstBarToday, c.R4, Color.FromArgb(100,Color.Red), LineStyle.Dashed, 1 );
DrawLine( PricePane, bar, c.S5, firstBarToday, c.S5, Color.FromArgb(60,Color.Blue), LineStyle.Dashed, 1 );
DrawLine( PricePane, bar, c.R5, firstBarToday, c.R5, Color.FromArgb(60,Color.Red), LineStyle.Dashed, 1 );
AnnotateChart( PricePane, "S3", firstBarToday, c.S3, Color.Blue );
AnnotateChart( PricePane, "R3", firstBarToday, c.R3, Color.Red );
AnnotateChart( PricePane, "S4", firstBarToday, c.S4, Color.FromArgb(100,Color.Blue) );
AnnotateChart( PricePane, "R4", firstBarToday, c.R4, Color.FromArgb(100,Color.Red) );
AnnotateChart( PricePane, "S4", firstBarToday, c.S5, Color.FromArgb(60,Color.Blue) );
AnnotateChart( PricePane, "R4", firstBarToday, c.R5, Color.FromArgb(60,Color.Red) );
}
}
#endregion
if (IsLastPositionActive)
{
Position p = LastPosition;
if( lastBarToday )
ExitAtClose(bar, p, "At Close");
else
if( !ExitAtStop( bar+1, p, p.RiskStopLevel, "Risk stop" ) )
ExitAtLimit( bar+1, p, p.AutoProfitLevel, "Profit" );
}
else
{
if( !enterTrades && canTrade && firstBarToday > 0 && !lastBarToday)
{
bool openInsideS3R3 = openToday > c.S3 && openToday < c.R3;
bool openOutsideS3R3 = openToday < c.S3 || openToday > c.R3;
bool openBetweenR3R4 = openToday > c.R3 && openToday < c.R4;
bool openBetweenS3S4 = openToday < c.S3 && openToday > c.S4;
enterTrades = ( !lastBarToday &&
( (e == Entry.Inside) && openInsideS3R3 ) ||
( (e == Entry.Outside) && openOutsideS3R3 ) ||
( (e == Entry.Breakout) && (openBetweenR3R4 || openBetweenS3S4) ) );
}
if( enterTrades && dailyBar > 1 && firstBarToday > 0 && !lastBarToday )
{
if( e == Entry.Outside )
{
#region Outside S3/R3
if( openToday < c.S3 )
{
if( BuyAtStop( bar + 1, c.S3, "Outside S3/R3" ) != null )
{
AnnotateBar( "Outside\nbuy", bar, false, Color.Magenta );
LastPosition.RiskStopLevel = c.S4 - tick;
LastPosition.AutoProfitLevel = c.R3 + tick;
enterTrades = false;
canTrade = false;
}
}
else
if( openToday > c.R3 )
{
if( ShortAtStop( bar + 1, c.R3, "Outside S3/R3" ) != null )
{
AnnotateBar( "Outside\nshort", bar, false, Color.Magenta );
LastPosition.RiskStopLevel = c.R4 + tick;
LastPosition.AutoProfitLevel = c.S3 - tick;
enterTrades = false;
canTrade = false;
}
}
#endregion
}
else
if( e == Entry.Inside )
{
#region Inside S3/R3
if( BuyAtLimit( bar + 1, c.S3, "Inside S3/R3" ) != null )
{
AnnotateBar( "Inside\nbuy", bar, false, Color.Magenta );
LastPosition.RiskStopLevel = c.S4 - tick;
LastPosition.AutoProfitLevel = c.R4 + tick;
enterTrades = false;
canTrade = false;
}
else
if( ShortAtLimit( bar + 1, c.R3, "Inside S3/R3" ) != null )
{
AnnotateBar( "Inside\nshort", bar, false, Color.Magenta );
LastPosition.RiskStopLevel = c.R4 + tick;
LastPosition.AutoProfitLevel = c.S4 - tick;
enterTrades = false;
canTrade = false;
}
#endregion
}
else
if( e == Entry.Breakout )
{
#region Breakout from S4/R4
if( BuyAtStop( bar + 1, c.R4, "Breakout R4" ) != null )
{
AnnotateBar( "Breakout\nbuy", bar, false, Color.Magenta );
LastPosition.RiskStopLevel = c.R3 - tick;
LastPosition.AutoProfitLevel = c.R5 + tick;
enterTrades = false;
canTrade = false;
}
else
if( ShortAtStop( bar + 1, c.S4, "Breakout S4" ) != null )
{
AnnotateBar( "Breakout\nshort", bar, false, Color.Magenta );
LastPosition.RiskStopLevel = c.S3 + tick;
LastPosition.AutoProfitLevel = c.R5 - tick;
enterTrades = false;
canTrade = false;
}
#endregion
}
}
}
}
}
}
}