Test 1 strategy rules (Shorting with the insiders):
- Short on a stop tomorrow at today’s low when insider selling is more than $20,000,000 and is equal to or greater than the highest level of the past 200 days.
- Cover short position on a stop equal to the entry price plus three times the 14-day average true range (ATR).
- Cover short position at a limit equal to the price of entry minus three times the 14-day ATR.
- Or exit the trade after 30 days.
Note: Insider selling is an aggregated dollar value of combined insider sell transactions on the open market of a security.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using WealthLab.Rules;
namespace WealthLab.Strategies
{
public class ShortTheInsiders : WealthScript
{
private StrategyParameter paramThreshold;
private StrategyParameter paramExitAfter;
public ShortTheInsiders()
{
paramThreshold = CreateParameter("Threshold $", 20000000, 1000000, 50000000, 1000000);
paramExitAfter = CreateParameter("Exit after, days", 30, 5, 50, 5);
}
protected override void Execute()
{
/*
Insider transactions series are not split-adjusted neither in WLP4 nor in WLP5.
Therefore the need to create the adjusted series by multipling the insider trade volume
by an adjustment factor. This adjustment factor is created using the 'split' item,
so the insider trade volume would remain relative to the stock's split-adjusted volume.
*/
DataSeries reverseAdjustment;
DataSeriesOp.SplitReverseFactor( this, "split", out reverseAdjustment);
DataSeries dsAdjusted = Close * reverseAdjustment;
ChartPane adjPane = PricePane;
if( Close.Description.Contains("Volume") )
{
dsAdjusted = Close / reverseAdjustment;
adjPane = VolumePane;
}
// Now let's create the adjusted insider buying data series.
IList<FundamentalItem> fListS = FundamentalDataItems("insider sell");
DataSeries InsiderSellingSeries = new DataSeries( Bars, "Insider Selling" );
InsiderSellingSeries.Description = "Insider Selling $";
for (int bar = 0; bar < Bars.Count; bar++)
{
double sumS = 0;
foreach (FundamentalItem fi in fListS)
{
if( fi.Bar == bar )
{
sumS += fi.Value;
InsiderSellingSeries[bar] = sumS * dsAdjusted[bar];
}
}
}
ChartPane iS = CreatePane( 20, true, true );
int high = 200;
DataSeries isSumHighest = Highest.Series( InsiderSellingSeries, high );
isSumHighest.Description = high.ToString() + "-day Highest Aggregated Insider Selling ($)";
PlotSeries( iS, InsiderSellingSeries, Color.Red, LineStyle.Histogram, 2 );
PlotSeries( iS, isSumHighest, Color.Blue, LineStyle.Dashed, 2 );
// Split-adjusted price
PlotSeries(adjPane, dsAdjusted, Color.FromArgb( 50, Color.Blue ), LineStyle.Solid, 1);
// A dollar threshold for insider selling activity
double threshold = paramThreshold.Value;
// Time-based exit
int daysToExit = paramExitAfter.ValueInt;
for(int bar = high; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
Position p = LastPosition;
if ( bar+1 - p.EntryBar >= daysToExit )
{
CoverAtMarket( bar+1, p, "Timed" );
} else
{
if( !CoverAtStop( bar+1, p, p.EntryPrice + ATR.Series( Bars, 14 )[bar] * 3, "Loss 3*ATR" ) )
CoverAtLimit( bar+1, p, p.EntryPrice - ATR.Series( Bars, 14 )[bar] * 3, "Profit 3*ATR" );
}
}
else
{
if( InsiderSellingSeries[bar] > threshold )
if( InsiderSellingSeries[bar] >= isSumHighest[bar] )
ShortAtStop( bar+1, Low[bar] );
}
}
}
}
}
Test 2 strategy rules (Fading the insiders):
- Buy tomorrow at market when insider selling today is more than $20,000,000 and is equal to or greater than the highest level of the past 200 days.
- Exit long position after 30 days.
Note: Insider selling is an aggregated dollar value of combined insider sell transactions on the open market of a security.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using WealthLab.Rules;
namespace WealthLab.Strategies
{
public class InsiderBuying : WealthScript
{
private StrategyParameter paramThreshold;
private StrategyParameter paramExitAfter;
public InsiderBuying()
{
paramThreshold = CreateParameter("Threshold $", 20000000, 1000000, 50000000, 1000000);
paramExitAfter = CreateParameter("Exit after, days", 30, 5, 50, 5);
}
protected override void Execute()
{
/*
Insider transactions series are not split-adjusted neither in WLP4 nor in WLP5.
Therefore the need to create the adjusted series by multipling the insider trade volume
by an adjustment factor. This adjustment factor is created using the 'split' item,
so the insider trade volume would remain relative to the stock's split-adjusted volume.
*/
DataSeries reverseAdjustment;
DataSeriesOp.SplitReverseFactor( this, "split", out reverseAdjustment);
DataSeries dsAdjusted = Close * reverseAdjustment;
ChartPane adjPane = PricePane;
if( Close.Description.Contains("Volume") )
{
dsAdjusted = Close / reverseAdjustment;
adjPane = VolumePane;
}
// Now let's create the adjusted insider buying data series.
IList<FundamentalItem> fListS = FundamentalDataItems("insider sell");
DataSeries InsiderSellingSeries = new DataSeries( Bars, "Insider Selling" );
InsiderSellingSeries.Description = "Insider Selling $";
for (int bar = 0; bar < Bars.Count; bar++)
{
double sumS = 0;
foreach (FundamentalItem fi in fListS)
{
if( fi.Bar == bar )
{
sumS += fi.Value;
InsiderSellingSeries[bar] = sumS * dsAdjusted[bar];
}
}
}
int high = 200;
ChartPane iS = CreatePane( 20, true, true );
DataSeries isSum = InsiderSellingSeries;
DataSeries isSumHighest = Highest.Series( isSum, high );
isSum.Description = "Insider Selling ($)";
isSumHighest.Description = high.ToString() + "-day Highest Aggregated Insider Selling ($)";
PlotSeries( iS, isSum, Color.Red, LineStyle.Histogram, 2 );
PlotSeries( iS, isSumHighest, Color.Blue, LineStyle.Dashed, 2 );
// Split-adjusted price
PlotSeries(adjPane, dsAdjusted, Color.FromArgb( 50, Color.Blue ), LineStyle.Solid, 1);
// Finally, some action!
double threshold = paramThreshold.Value;
int daysToExit = paramExitAfter.ValueInt;
for(int bar = high; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
Position p = LastPosition;
if ( bar+1 - p.EntryBar >= daysToExit )
SellAtMarket( bar+1, p, "Timed" );
}
else
{
{
if( isSum[bar] > threshold )
if( isSum[bar] >= isSumHighest[bar] )
if( BuyAtMarket( bar+1 ) != null )
LastPosition.Priority = Close[bar];
}
}
}
}
}
}