I met a very very weird problem
I coded a strategy that place long when month/day is bullish and W% in H1 oversold, and place short when month/day is bearish and W% in H1 overbought----very simple one.
The code is attached, and it is a working strategy with only 1 issue:
in the AddPosition() procedure, the SL and TP always return 0, though these two variables are external and specified. I don't understand why this happened, and I tried different ways (as you can see in the code) to define these two external var. the SL and TP value is printed correctly in GetSingleTick(), but is returning only 0 if referred from AddPosition().
shed me a light, comrades!
Thanks.
Code: Select all
library TriScreen;
uses
Math,
SysUtils,
DateUtils,
Graphics,
Dialogs,
Classes,
StrategyInterfaceUnit,
TechnicalFunctions;
var
// External parameters
Currency: PChar = nil;
Lot: double;
MagicNumber: integer;
//SL: integer;
//TP: integer;
SL: integer = 250;
TP: integer = 350;
HiTF: integer;
MiTF: integer;
LoTF: integer;
MACDpara1: integer;
MACDpara2: integer;
MACDpara3: integer;
WPpara1: integer;
EntryInterval: integer;
PosCAP: integer;
// custom variables
OrderHandle1, OrderHandle2, MACDhandle, WPhandle: integer;
OrderStyle: TTradePositionType;
WeekTrend, DailyTrend, HourlyTrend: integer;
LongEntryValid, ShortEntryValid: boolean;
pairPoint: double;
{-----Init strategy-----------------------------------------}
procedure InitStrategy; stdcall;
begin
StrategyShortName('Tri_Screen');
StrategyDescription('Tripple Screen');
// Register external parameters
RegOption('Currency', ot_Currency, Currency);
ReplaceStr(Currency, 'EURUSD');
RegOption('LotSize', ot_Double, Lot);
SetOptionDigits('LotSize', 1);
Lot := 0.1;
RegOption('stop loss', ot_Integer, SL);
RegOption('take profit', ot_Integer, TP);
//RegOption('stop loss', ot_Integer, SL);
//SetOptionRange('stop loss', 2, MaxInt);
//SL := 250;
//RegOption('take profit', ot_Integer, TP);
//SetOptionRange('take profit', 2, MaxInt);
//TP := 350;
RegOption('magic number', ot_Integer, MagicNumber);
SetOptionRange('magic number', 2, MaxInt);
MagicNumber := 301;
RegOption('Weekly', ot_Timeframe, HiTF);
HiTF := 10080;
RegOption('Daily', ot_Timeframe, MiTF);
MiTF := 1440;
RegOption('Hourly', ot_Timeframe, LoTF);
LoTF := 60;
RegOption('MACD parameter 1', ot_Integer, MACDpara1);
SetOptionRange('MACD parameter 1', 2, MaxInt);
MACDpara1 := 12;
RegOption('MACD parameter 2', ot_Integer, MACDpara2);
SetOptionRange('MACD parameter 2', 2, MaxInt);
MACDpara2 := 9;
RegOption('MACD parameter 3', ot_Integer, MACDpara3);
SetOptionRange('MACD parameter 3', 2, MaxInt);
MACDpara3 := 7;
RegOption('W% Parameter', ot_Integer, WPpara1);
SetOptionRange('W% parameter', 2, MaxInt);
WPpara1 := 14;
RegOption('Entry Interval', ot_Integer, EntryInterval);
SetOptionRange('Entry Interval', 2, MaxInt);
EntryInterval := 12;
RegOption('Position Limit', ot_Integer, PosCAP);
SetOptionRange('Position Limit', 2, MaxInt);
PosCAP := 5;
end;
{-----Done strategy---------------------------------------}
procedure DoneStrategy; stdcall;
begin
FreeMem(Currency);
end;
{-----Reset strategy--------------------------------------}
procedure ResetStrategy; stdcall;
begin
OrderHandle1 := -1;
MACDhandle := CreateIndicator(Currency, MiTF, 'MACD', '5;10;5;Close');
WPhandle := CreateIndicator(Currency, LoTF, 'WPR', '14;Close');
end;
{-----Calculate SMA---------------------------------------}
function GetSMA(period: integer): double;
var
i: integer;
sum: double;
begin
sum := 0;
for i:=0 to period - 1 do
sum := sum + Close(i);
result := sum/period;
end;
procedure SetPoint(sym: string);
begin
if (MarketInfo(sym, Mode_Bid) > 20) then pairPoint := 0.01
else pairPoint := 0.0001;
end;
function ReadWeekly(sym: string): integer;
begin
if (iOpen(sym, 43200, 1) < iClose(sym, 43200, 1)) then
Result := 1;
if (iOpen(sym, 43200, 1) > iClose(sym, 43200, 1)) then
Result := -1;
if (iOpen(sym, 43200, 1) = iClose(sym, 43200, 1)) then
Result := 0;
end;
function ReadDaily(sym: string): integer;
var
vMACD: double;
begin
vMACD := GetIndicatorValue(MACDhandle, 1, 2);
if (vMACD < 0) then Result := -1;
if (vMACD > 0) then Result := 1;
end;
function ReadHourly(sym: string): integer;
var
vWP: double;
begin
vWP := GetIndicatorValue(WPhandle, 1, 0);
if (vWP >= -80) and (vWP <= -20) then Result := 0;
if (vWP > -20) then Result := -1;
if (vWP < -80) then Result := 1;
end;
// this function considers "time": in Delphi, Tdatetime is 'double',
// the most recent 'time' is largest, the integral is NO of days, the fractional part is fraction of 24 hour passed
// e.g. if today's 8 am is 28943.3333333, then tomorrow's 8 pm is 28944.666666; so in my base below, i need two entries' Ddatetime has a difference more than 0.5, that is, 12 hours.
function EntryLimitsMet(dir: integer): boolean;
var
n, NOofSells, NOofBuys: integer;
temp: boolean;
LatestEntryTime: TDateTime;
begin
NOofSells := 0;
NOofBuys := 0;
//Print('Before Checking, n :{' + inttostr(n) + '}.');
for n := 0 to OrdersTotal - 1 do
begin
OrderSelect(n, Select_By_Pos, mode_trades);
if (OrderMagicNumber = MagicNumber) and (OrderLots = Lot) then
begin
if (dir = 1) and (OrderType = tp_Buy) then
begin
NOofBuys := NOofBuys + 1; // Print('# of Buys :{' + IntToStr(NOofBuys) + '}.');
if (LatestEntryTime < OrderOpenTime) then LatestEntryTime := OrderOpenTime;
end;
if (dir = -1) and (OrderType = tp_Sell) then
begin
NOofSells := NOofSells + 1;
if (LatestEntryTime < OrderOpenTime) then LatestEntryTime := OrderOpenTime;
end;
end
end;
if (dir = 1) then Print('Latest Entry @:{' + floattostr(LatestEntryTime) + '}, while NOW is:{' + floattostr(TimeCurrent) + '}, NO of Pos:{' + inttostr(NOofBuys) + '}.');
if (dir = -1) then Print('Latest Entry @:{' + floattostr(LatestEntryTime) + '}, while NOW is:{' + floattostr(TimeCurrent) + '}, NO of Pos:{' + inttostr(NOofSells) + '}.');
temp := false;
if (dir = 1) and ( (TimeCurrent - LatestEntryTime < 0.5) or (NOofBuys >= PosCAP) ) then temp := true;
if (dir = -1) and ( (TimeCurrent - LatestEntryTime < 0.5) or (NOofSells >= PosCAP) ) then temp := true;
Result := temp;
end;
procedure AddPosition(dir: integer);
var
tp, sl: double;
begin
if (dir = 1) then
begin
Print('before, SL:{' + floatToStr(SL) + '}');
sl := MarketInfo(Currency, MODE_ASK) - SL*pairPoint;
Print('after, sl:{'+floattostr(sl)+'}');
tp := MarketInfo(Currency, MODE_ASK) + TP*pairPoint;
SendInstantOrder(Currency, OP_BUY,Lot, sl, tp, 'TriScreen',MagicNumber,OrderHandle1);
end;
if (dir = -1) then
begin
sl := MarketInfo(Currency, MODE_BID) + SL * pairPoint;
tp := MarketInfo(Currency, MODE_BID) - TP * pairPoint;
SendInstantOrder(Currency, OP_SELL,Lot, sl, tp, 'TriScreen',MagicNumber,OrderHandle1);
end;
end;
{-----Process single tick----------------------------------}
procedure GetSingleTick; stdcall;
begin
//Print(' @ begin, SL:{' + floatToStr(SL) + '}'); //Print(' @ begin, TP:{' + IntToStr(TP) + '}');
SetPoint(Currency); // menu, help, or regular way: SetCurrencyAndTimeframe(Currency, LoTF); //any TF will do;
WeekTrend := ReadWeekly(Currency);
DailyTrend := ReadDaily(Currency);
HourlyTrend := ReadHourly(Currency);
//if (DailyTrend = 1) and (HourlyTrend = 1) then LongEntryValid := true;
if (WeekTrend = 1) and (DailyTrend = 1) and (HourlyTrend = 1) then LongEntryValid := true;
if (WeekTrend = -1) and (DailyTrend = -1) and (HourlyTrend = -1) then ShortEntryValid := true;
//if (DailyTrend = -1) and (HourlyTrend = -1) then ShortEntryValid := true;
if (LongEntryValid) and (not EntryLimitsMet(1)) then AddPosition(1);
if (ShortEntryValid) and (not EntryLimitsMet(-1)) then AddPosition(-1);
//reset! a MUST!
LongEntryValid := false;
ShortEntryValid := false;
end;
exports
InitStrategy,
DoneStrategy,
ResetStrategy,
GetSingleTick;
end.