Code: Select all
type TTradeFilters = (Slow, Fast, Both);
var
AdxDirectionPeriod: TTradeFilters
... init
RegOption('Adx Directional Period Filter', ot_EnumType, AdxDirectionPeriod);
AddOptionValue('Adx Directional Period Filter', 'Slow');
AddOptionValue('Adx Directional Period Filter', 'Fast');
AddOptionValue('Adx Directional Period Filter', 'Both');
AdxDirectionPeriod := Slow;
... end init
I have two of these filters as regoptions but this one won't hold its value even though it loads with the default value of 'Slow'. But once i run the strategy it changes to "illegal value". I've searched the code and don't assign anything to it.
The other works fine!
Thanks
entire code:
Code: Select all
library ADXBreakout;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils, graphics, StrategyInterfaceUnit, TechnicalFunctions;
// enumerations
type TTrendlinePrices = array[0..1] of double;
type TAdxValues = array[0..2] of double;
type TTradeFilters = (Slow, Fast, Both);
var
// External parameters
Currency: PChar = nil;
TrailTimeFrame: integer;
AtrTimeFrame: integer;
TrailingStopBars: integer;
UseTrailingStop: boolean;
LotSize: double;
TakeProfitTarget: double;
StopLossTarget: double;
StopLossBuffer: integer;
ProfitTargetAtr: boolean;
RiskFilter: integer;
BreakoutCandleAdjuster: double;
BreakoutCandleCloseConstant: double;
UsePyramid: boolean;
// Exit Strategy
// Adx
IndAdxSlow: integer;
AdxSlowTimeframe: integer;
IndAdxFast: integer;
AdxFastTimeframe: integer;
AdxTrigger: double;
AdxTriggerPeriod: TTradeFilters;
AdxDirectionPeriod: TTradeFilters;
// Atr for breakout
IndAtr: integer;
AtrPer: integer;
// custom variables
OrderHandle: integer;
OrderHandle2: integer;
procedure InitStrategy; stdcall;
begin
StrategyShortName('ADX Breakout');
StrategyDescription('Trade momentum using ADX');
// Register external parameters
RegOption('Currency', ot_Currency, Currency);
ReplaceStr(Currency, 'EURUSD');
RegOption('Adx Slow Timeframe', ot_Timeframe, AdxSlowTimeFrame);
AdxSlowTimeFrame := PERIOD_D1;
RegOption('Adx Fast Timeframe', ot_Timeframe, AdxFastTimeFrame);
AdxFastTimeFrame := PERIOD_M15;
RegOption('Adx Directional Period Filter', ot_EnumType, AdxDirectionPeriod);
AddOptionValue('Adx Directional Period Filter', 'Slow');
AddOptionValue('Adx Directional Period Filter', 'Fast');
AddOptionValue('Adx Directional Period Filter', 'Both');
AdxDirectionPeriod := Slow;
RegOption('Adx Trigger Period Filter', ot_EnumType, AdxTriggerPeriod);
AddOptionValue('Adx Trigger Period Filter', 'Slow');
AddOptionValue('Adx Trigger Period Filter', 'Fast');
AddOptionValue('Adx Trigger Period Filter', 'Both');
AdxTriggerPeriod := Fast;
RegOption('Adx trigger value', ot_Double, AdxTrigger);
AdxTrigger := 30.0;
RegOption('Atr Timeframe', ot_Timeframe, AtrTimeFrame);
AtrTimeFrame := PERIOD_M15;
RegOption('Atr Period', ot_Integer, AtrPer);
AtrPer := 14;
RegOption('Take profit logic (Yes ATR, No Fib)', ot_Boolean, ProfitTargetAtr);
ProfitTargetAtr := true;
RegOption('TakeProfitTarget xAtr', ot_Double, TakeProfitTarget);
TakeProfitTarget := 5.0;
RegOption('StopLossTarget xAtr', ot_Double, StopLossTarget);
StopLossTarget := 2.0;
RegOption('Trigger adjuster (sets trigger candle volatility as % of ATR)', ot_Double, BreakoutCandleAdjuster);
BreakoutCandleAdjuster := 2.0;
RegOption('Trigger close adjuster (sets close of candle relative to is end)', ot_Double, BreakoutCandleCloseConstant);
BreakoutCandleCloseConstant := 2.0;
RegOption('Use Pyramid', ot_Boolean, UsePyramid);
UsePyramid := false;
RegOption('Use Trailing Stop', ot_Boolean, UseTrailingStop);
UseTrailingStop := false;
RegOption('Trailing Stop Timeframe', ot_Timeframe, TrailTimeFrame);
TrailTimeFrame := PERIOD_M5;
RegOption('Trailing Stop Candles', ot_Integer, TrailingStopBars);
TrailingStopBars := 5;
RegOption('StopLoss Buffer for trailing stop', ot_Integer, StopLossBuffer);
StopLossBuffer := 4;
RegOption('LotSize', ot_Double, LotSize);
SetOptionDigits('LotSize', 1);
LotSize := 0.1;
end;
procedure DoneStrategy; stdcall;
begin
FreeMem(Currency);
end;
procedure ResetStrategy; stdcall;
begin
OrderHandle := -1;
IndAtr := CreateIndicator(Currency, AtrTimeFrame, 'ATR',
format('%d;Close',[AtrPer]));
IndAdxSlow := CreateIndicator(Currency, AdxSlowTimeFrame, 'ADX',
format('%d;Close',[AtrPer]));
IndAdxFast := CreateIndicator(Currency, AdxFastTimeFrame, 'ADX',
format('%d;Close',[AtrPer]));
end;
procedure GetSingleTick; stdcall;
var
iCntr: integer;
dTakeProfit: double;
dTrailHighVal: double;
dTrailLowVal: double;
dAtrVal: double;
iTradeDirection: integer;
dStopLoss: double;
dPipBuffer: double;
myPosition: TTradePosition;
dBreakoutCandleClose: double;
dCandleWidth: double;
bShortBreakoutCandle: boolean;
bLongBreakoutCandle: boolean;
tAdxSlow: TAdxValues;
tAdxFast: TAdxValues;
bAdxStrengthTrigger: boolean;
begin
// check our currency
if Symbol <> string(Currency) then exit;
// set currency and timeframe
SetCurrencyAndTimeframe(Symbol, AtrTimeFrame);
// check number of bars and SMA period
if (iBars(Currency, AtrPer) < AtrPer) then exit;
// set stop loss buffer
dPipBuffer := StopLossBuffer * Point;
// Atr Value of candle 1
dAtrVal := GetIndicatorValue(IndAtr, 1, 0);
// Adx Values
tAdxSlow[0] := GetIndicatorValue(IndAdxSlow, 0, 3);
tAdxSlow[1] := GetIndicatorValue(IndAdxSlow, 0, 4);
tAdxSlow[2] := GetIndicatorValue(IndAdxSlow, 0, 5);
tAdxFast[0] := GetIndicatorValue(IndAdxFast, 0, 3);
tAdxFast[1] := GetIndicatorValue(IndAdxFast, 0, 4);
tAdxFast[2] := GetIndicatorValue(IndAdxFast, 0, 5);
// get breakout high/low values and candle numbers
// get difference of high and low
dCandleWidth := High(1) - Low(1);
// trade direction logic determined by Adx
if (AdxDirectionPeriod = Slow) then
if (tAdxSlow[1] > tAdxSlow[2]) then
begin
iTradeDirection := 0;
dBreakoutCandleClose := High(1) - Close(1);
end
else
begin
iTradeDirection := 1;
dBreakoutCandleClose := Close(1) - Low(1);
end
else
if (tAdxFast[1] > tAdxFast[2]) then
begin
iTradeDirection := 0;
dBreakoutCandleClose := High(1) - Close(1);
end
else
begin
iTradeDirection := 1;
dBreakoutCandleClose := Close(1) - Low(1);
end;
// strength trigger determined by Adx
bAdxStrengthTrigger := false;
if (AdxTriggerPeriod = Slow) then
if (tAdxSlow[0] > AdxTrigger) then
bAdxStrengthTrigger := true
else
if (tAdxFast[0] > AdxTrigger) then
bAdxStrengthTrigger := true;
// determine if current candle is large relative to ATR multiplied by a constant
// and close is within % distance from end of candle
bShortBreakoutCandle := false;
bLongBreakoutCandle := false;
if (dCandleWidth > (dAtrVal * BreakoutCandleAdjuster)) and
((dBreakoutCandleClose * BreakoutCandleCloseConstant) < dCandleWidth) then
if (Open(1) > Close(1)) then
bShortBreakoutCandle := true
else
bLongBreakoutCandle := true;
if (OrdersTotal < 1) then
begin
// determine if breakout candle and Adx is greater than trigger value
if (bLongBreakoutCandle) and (bAdxStrengthTrigger) and (iTradeDirection = 0) then
begin
dStopLoss := Low(1) - (dAtrVal * StopLossTarget);
if (ProfitTargetAtr) then
dTakeProfit := High(1) + (dAtrVal * TakeProfitTarget)
else
dTakeProfit := High(1) + ((High(1) - Low(1)) * TakeProfitTarget);
SendInstantOrder(Currency, TInstantOrderType(iTradeDirection), 0.1,
dStopLoss, dTakeProfit, '', 0, OrderHandle);
end;
if (bShortBreakoutCandle) and (bAdxStrengthTrigger) and (iTradeDirection = 1) then
begin
dStopLoss := High(1) + (dAtrVal * StopLossTarget);
if (ProfitTargetAtr) then
dTakeProfit := Low(1) - (dAtrVal * TakeProfitTarget)
else
dTakeProfit := Low(1) - ((High(1) - Low(1)) * TakeProfitTarget);
SendInstantOrder(Currency, TInstantOrderType(iTradeDirection), 0.1,
dStopLoss, dTakeProfit, '', 0, OrderHandle);
end;
end;
// this set trailing stops
if (OrdersTotal > 0) then
begin
dTrailHighVal := iHigh(Currency, TrailTimeFrame, 1) + dPipBuffer;
dTrailLowVal := iLow(Currency, TrailTimeFrame, 1) - dPipBuffer;
// trail stop with 5 minute bar
for iCntr := 1 to TrailingStopBars - 1 do
begin
if (dTrailHighVal > iHigh(Currency, TrailTimeFrame, iCntr)) then
dTrailHighVal := iHigh(Currency, TrailTimeFrame, iCntr) + dPipBuffer;
if (dTrailLowVal > iLow(Currency, TrailTimeFrame, iCntr)) then
dTrailLowVal := iLow(Currency, TrailTimeFrame, iCntr) - dPipBuffer;
end;
// Loop through orders
for iCntr := 0 to OrdersTotal - 1 do
if (OrderSelect(iCntr, SELECT_BY_POS, MODE_TRADES)) then
begin
if (OrderType = tp_Sell) then
begin
// manage stop loss for sell active
OrderHandle := OrderTicket;
GetOrderInfo(OrderHandle, myPosition);
// close order if ma's close over
//if (iTradeDirection = 0) then
// CloseOrder(OrderHandle)
//else
if (UseTrailingStop) then
if (myPosition.StopLoss > dTrailHighVal) then
ModifyOrder(OrderHandle, 0.0, dTrailHighVal, myPosition.TakeProfit);
if (UsePyramid) and (bShortBreakoutCandle) and
(OrdersTotal < 2) then
begin
dTakeProfit := myPosition.OpenPrice -
((myPosition.OpenPrice - myPosition.TakeProfit) * 2);
ModifyOrder(OrderHandle, 0.0, High(1), dTakeProfit);
SendInstantOrder(Currency, TInstantOrderType(1), 0.1,
High(1), dTakeProfit, '', 0, OrderHandle2);
end;
// close position on reverse signal
if (bLongBreakoutCandle) then
CloseOrder(OrderHandle);
end;
if (OrderType = tp_Buy) then
begin
// manage stop loss for buy active
OrderHandle := OrderTicket;
GetOrderInfo(OrderHandle, myPosition);
// close order if ma's close over
//if (iTradeDirection = 1) then
// CloseOrder(OrderHandle)
//else
if (UseTrailingStop) then
if (myPosition.StopLoss < dTrailLowVal) then
ModifyOrder(OrderHandle, 0.0, dTrailLowVal, myPosition.TakeProfit);
if (UsePyramid) and (bLongBreakoutCandle) and
(OrdersTotal < 2) then
begin
dTakeProfit := myPosition.OpenPrice +
((myPosition.TakeProfit - myPosition.OpenPrice) * 2);
ModifyOrder(OrderHandle, 0.0, Low(1), dTakeProfit);
SendInstantOrder(Currency, TInstantOrderType(iTradeDirection), 0.1,
Low(1), dTakeProfit, '', 0, OrderHandle2);
end;
// close position on reverse signal
// if (bShortBreakoutCandle) then
// CloseOrder(OrderHandle);
end;
end;
end;
end;
exports
InitStrategy,
DoneStrategy,
ResetStrategy,
GetSingleTick;
end.