RegOption ot_Enumtype

How to create strategies and indicators
Message
Author
dfstone32
Posts: 5
Joined: Thu Jun 12, 2008 12:28 pm

RegOption ot_Enumtype

#1 Postby dfstone32 » Wed Nov 19, 2008 2:30 pm

Is there some thing wrong with this:


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.

User avatar
Terranin
Site Admin
Posts: 833
Joined: Sat Oct 21, 2006 4:39 pm

Re: RegOption ot_Enumtype

#2 Postby Terranin » Fri Nov 21, 2008 11:27 pm

dfstone32 wrote:Is there some thing wrong with this:


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.



Yes, it is incorrect usage of enumerated type, should be:

Code: Select all

var
  AdxDirectionPeriod: integer;

... 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 := 0;

... end init


Enumeration type in Delphi could be various size (byte, word, integer) depending on settings, while ForexTester assumes that it is always integer.

Possible you can use next construction if you want to use your types:

Code: Select all

type
  TTradeFilters = (Slow, Fast, Both);

var
  dummy0: integer = 0;
  AdxDirectionPeriod: TTradeFilters absolute dummy0;


where dummy0 will reserve 4 bytes for you AdxDirectionPeriod variable.
Hasta la vista
Mike


Return to “FT API”

Who is online

Users browsing this forum: No registered users and 8 guests