Price Data Components
Indicators Used
Miscellaneous
1
Views
3
Downloads
0
Favorites
ChartBuilder
//+------------------------------------------------------------------+
//| ChartBuilder.mq4 | 2.1
//| Navoykov Alexey |
//| alemail@yandex.ru |
//+------------------------------------------------------------------+
#property copyright "NavAlex"
#property link "alemail@yandex.ru"
#property indicator_separate_window
#property indicator_buffers 8
#define CURRENT_SYMBOL "%symbol%"
extern string Formula1 = CURRENT_SYMBOL;
extern string Formula2 = "";
extern string Formula3 = "";
extern string Formula4 = "";
extern string Formula5 = "";
extern string Formula6 = "";
extern string Formula7 = "";
extern string Formula8 = "";
extern string OnlyNumbers = ""; // ðàçðåø¸ííûå íîìåðà ôîðìóë. Åñëè íè÷åãî íå óêàçàíî, òî èñïîëüçóþòñÿ âñå ôîðìóëû
extern int PrecisionDigits = -1; // òî÷íîñòü çíà÷åíèé (÷èñëî çíàêîâ ïîñëå çàïÿòîé). Åñëè -1, òî íàçíà÷àåòñÿ àâòîìàòè÷åñêè
extern bool AutoScale = false; // àâòîìàñøòàáèðîâàíèå âñåõ ãðàôèêîâ
extern double TimeShiftFromMainChart_minutes = 0; // ñäâèæêà â ìèíóòàõ îòíîñèòåëüíî îñíîâíîãî ãðàôèêà
extern bool BarTimeSyncMode_ByMinutes = true; // åñëè true, òî ñèíõðîíèçàöèÿ ïî ìèíóòàì, èíà÷å ïî áàðàì
extern int BarTimeSyncSize = -1; // èíòåðâàë ïðèâÿçêè äëÿ ñèíõðîíèçàöèè áàðîâ ÷óæèõ ñèìâîëîâ (êîëè÷åñòâî ìèíóò ëèáî êîëè÷åñòâî áàðîâ, â çàâèñèìîñòè îò ïàðàìåòðà BarTimeSyncMode_ByMinutes)
extern bool OnlyClosePrice = true; // îòîáðàæàòü òîëüêî öåíû îòêðûòèÿ
extern int DrawMode = 0; // ðåæèì îòðèñîâêè
extern string DrawModeDescription = "0-LINE, 1-SECTION, 2-HISTOGRAM, 3-POINTS";
extern color Color1 = Yellow;
extern color Color2 = Lime;
extern color Color3 = Aqua;
extern color Color4 = DodgerBlue;
extern color Color5 = Magenta;
extern color Color6 = Red;
extern color Color7 = Orange;
extern color Color8 = White;
extern bool LabelsOnTheRight = 0; // îòîáðàæàòü íàçâàíèÿ ãðàôèêîâ ñ ïðàâîé ñòîðîíû, èíà÷å ñ ëåâîé
extern bool ShowBidAsk = true; // ïîêàçûâàòü áèä è àñê (ñèíòåòè÷åñêèå)
extern string Signal_ChartNumber = "1"; // íîìåð ãðàôèêà, äëÿ êîòîðîãî óñòàíîâëåí ñèãíàë (ìîæíî óêàçàòü íåñêîëüêî ãðàôèêîâ)
extern string Signal_HighValue = ""; // âåðõíåå ñèãíàëüíîå çíà÷åíèå
extern string Signal_LowValue = ""; // íèæíåå cèãíàëüíîå çíà÷åíèå
extern string Signal_HighLine = ""; // âåðõíÿÿ ñèãíàëüíàÿ ëèíèÿ
extern string Signal_LowLine = ""; // íèæíÿÿ ñèãíàëüíàÿ ëèíèÿ
extern int SaveToFile_ChartNumber= 0; // íîìåð ãðàôèêà, çíà÷åíèÿ êîòîðîãî ñîõðàíÿþòñÿ â ôàéë
extern string SaveToFile_FileName = "ChartBuilder.csv";
extern string SaveToFile_Delimiter = ";";
double buffer0[], buffer1[], buffer2[], buffer3[], buffer4[], buffer5[], buffer6[], buffer7[];
bool Exit;
bool WrongWindow;
int Window;
int MainChartIndex;
int IndDigits;
int InitTime;
int MaxCharts=8;
int BuffersPerChart=1;
int VLineTime;
bool AllowGetPriceLine=0;
string VLine=" ";
string StatusLabel=" ";
string SignalLabel="";
string IndicatorName="";
string IndicatorPrefix="";
string DropWindowIdObject="ChartBuilder_DroppedWindowID";
string StartMessage="";
#define MAXCHARTS 8
string Formulas [MAXCHARTS];
string ChartLabels [MAXCHARTS];
string ChartLabels_ [MAXCHARTS];
string ChartErrorLabels [MAXCHARTS];
string ErrorChartText [MAXCHARTS];
string LineAsk [MAXCHARTS];
string LineBid [MAXCHARTS];
bool ChartAllow [MAXCHARTS];
bool ChartValid [MAXCHARTS];
color Colors [MAXCHARTS];
int PrintedError [MAXCHARTS][10];
bool ChartCheckSignal[MAXCHARTS];
double AutoScaleRatio [MAXCHARTS];
double AutoScaleShift [MAXCHARTS];
int AutoScale_BaseChart= 0;
#define FUNC_CLOSE 0
#define FUNC_OPEN 1
#define FUNC_HIGH 2
#define FUNC_LOW 3
#define FUNC_LINEOPEN 4
#define FUNC_LINECLOSE 5
#define FUNC_LINEHIGH 6
#define FUNC_LINELOW 7
#define FUNC_ATR 8
#define FUNC_MA 9
#define FUNC_STDDEV 10
#define FUNC_AD 11
#define FUNC_ADX 12
#define FUNC_CCI 13
#define FUNC_DEMARKER 14
#define FUNC_MACD 15
#define FUNC_RSI 16
#define FUNC_STOCHASTIC 17
#define FUNC_BANDS 18
#define FUNC_MOMENTUM 19
#define FUNC_ENVELOPES 20
#define FUNC_MYATR 21
#define FUNC_VOLUME 22
#define FUNC_ASK 23
#define FUNC_BID 24
#define FUNC_LAST 25
#define FUNC_MAXIMUM 26
#define FUNC_MINIMUM 27
#define FUNC_ABS 40
#define FUNC_LOG 41
#define FUNC_EXP 42
#define FUNC_MAX 43
#define FUNC_MIN 44
#define FUNC_RND 45
#define FUNC_ROUND 46
#define FUNC_FIXVALUE 50
#define DEFAULTFUNCCOUNT 100
#define PARAMCOUNT 10
string DefaultFuncName [DEFAULTFUNCCOUNT];
int DefaultFuncSymCount [DEFAULTFUNCCOUNT];
string TemplateFuncName [200];
int TemplateFuncParam [200][PARAMCOUNT];
double FuncParam [][PARAMCOUNT];
double FuncParam1 [][PARAMCOUNT];
double FuncParam2 [][PARAMCOUNT];
double FuncParam3 [][PARAMCOUNT];
int FuncTimeSerie[];
int FuncCacheMinSize[];
int FuncLastTime[100];
int FuncLastType[100];
double FuncLastValue[100];
#define CELLVALUE 0
#define CELLTYPE 1
#define CELLOPERATION 2
#define CELLNEXTCELL 3
#define SUMMAND 0
#define MULTIPLIER 1
#define POW 2
#define TYPE_VALUE 1
#define TYPE_FUNC 2
#define ERROR_FORMULA 1
#define ERROR_SYMBOL 2
#define ERROR_HISTORY 3
#define ERROR_ZERODIVIDE 4
#define ERROR_POW 5
#define ERROR_RECURSION 6
#define ALGORANGE1 100
#define ALGORANGE2 4
#define FUNCRANGE1 50
int AlgoRange0;
double Algorithms [][ALGORANGE1][ALGORANGE2]; // [formula][pos][cellparam]
double AlgorithmsTotalPowRatio [][ALGORANGE1][2]; // [formula][pos][pow/ratio]
int AlgoFunctions [][FUNCRANGE1]; // [formula][function]
bool AlgoEnabled [100]; // [formula]
string AlgoNames[];
int Algo_BidAskAlgoIndex [100][4]; // [formula][pricetype]
string Symbols[];
int TimeSeries[][2]; //[][symindex/tf];
int SymbolsIndexes [][FUNCRANGE1][2]; // [formula][symindex][param]
int SymbolsFuncPos [][FUNCRANGE1][10]; // [formula][symindex][pos]
bool FirstStart;
string ErrorString;
int Error;
double CacheValueBuffer[];
int CacheTimeBuffer[];
int CacheStartPos[];
int CachePos[];
int CacheMinSize[];
bool IsFormulaUsing[9];
bool IsIndicator;
bool Debug= 0;
bool MyRatesAllow; // ðàçðåøàåò ïîäñòàíîâêó ïîëüçîâàòåëüñêèõ ìàññèâîâ Rates âìåñòî èìåþùèõñÿ êîòèðîâîê ÌÒ4
double MyRates[][6]; // ñþäà ïîìåùàåòñÿ ñòðóêòóðà Rates ñ ïîëüçîâàòåëüñêèìè çíà÷åíèÿìè äëÿ âñåõ èñïîëüçóåìûõ ñèìâîëîâ (äðóã çà äðóãîì)
int MyRatesPos[][2]; // ñþäà ïîìåùàþòñÿ: íà÷àëüíàÿ ïîçèöèÿ ìàññèâà Rates äëÿ êàæäîãî ñèìâîëà (ñóáèíäåêñ 0) è ðàçìåð ìàññèâà Rates äëÿ êàæäîãî ñèìâîëà (ñóáèíäåêñ 1)
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//Debug=false;
ArrayResize(Algorithms,0);
ArrayResize(FuncParam,0);
ArrayResize(Symbols,0);
ArrayResize(TimeSeries,0);
AlgoRange0=0;
Exit=false;
FirstStart=true;
Window=-1;
WrongWindow=false;
StartMessage="";
MaxCharts=0;
int inittime=InitTime;
InitTime=TimeLocal();
if (inittime>0) return(0);
SetFuncParameters("AD", FUNC_AD, 0);
SetFuncParameters("ADX", FUNC_ADX, 0, 100);
SetFuncParameters("ATR", FUNC_ATR, 0, 100);
SetFuncParameters("ATRD", FUNC_ATR, PERIOD_D1, 100);
SetFuncParameters("ATR2", FUNC_MYATR, 1, 0, 100, 1);
SetFuncParameters("Bands", FUNC_BANDS, 0, 100);
SetFuncParameters("CCI", FUNC_CCI, 0, 100);
SetFuncParameters("DeMarker", FUNC_DEMARKER, 0, 100);
SetFuncParameters("Envelopes", FUNC_ENVELOPES, 0, 100);
SetFuncParameters("MA", FUNC_MA, 0, 100);
SetFuncParameters("MAD", FUNC_MA, PERIOD_D1, 100);
SetFuncParameters("MACD", FUNC_MACD, 0, 100, 200, 100);
SetFuncParameters("Momentum", FUNC_MOMENTUM, 0, 100);
SetFuncParameters("RSI", FUNC_RSI, 0, 100);
SetFuncParameters("StdDev", FUNC_STDDEV, 0, 100);
SetFuncParameters("StdDevD", FUNC_STDDEV, PERIOD_D1, 100);
SetFuncParameters("Stochastic",FUNC_STOCHASTIC, 0, 100, 100, 1);
SetFuncParameters("Open", FUNC_OPEN);
SetFuncParameters("Close", FUNC_CLOSE);
SetFuncParameters("High", FUNC_HIGH);
SetFuncParameters("Low", FUNC_LOW);
SetFuncParameters("Volume", FUNC_VOLUME);
SetFuncParameters("LineOpen", FUNC_LINEOPEN);
SetFuncParameters("LineClose", FUNC_LINECLOSE);
SetFuncParameters("LineHigh", FUNC_LINEHIGH);
SetFuncParameters("LineLow", FUNC_LINELOW);
SetFuncParameters("Maximum", FUNC_MAXIMUM, 0, 100, 0, MODE_CLOSE); // timeframe, period, shift
SetFuncParameters("Minimum", FUNC_MINIMUM, 0, 100, 0, MODE_CLOSE);
SetFuncParameters("MaxClose", FUNC_MAXIMUM, 0, 100, 0, MODE_CLOSE); //"Close");
SetFuncParameters("MinClose", FUNC_MINIMUM, 0, 100, 0, MODE_CLOSE);//"Close");
SetFuncParameters("MaxOpen", FUNC_MAXIMUM, 0, 100, 0, MODE_OPEN);//"Open");
SetFuncParameters("MinOpen", FUNC_MINIMUM, 0, 100, 0, MODE_OPEN);//"Open");
SetFuncParameters("MaxHigh", FUNC_MAXIMUM, 0, 100, 0, MODE_HIGH);//"High");
SetFuncParameters("MinHigh", FUNC_MINIMUM, 0, 100, 0, MODE_HIGH);
SetFuncParameters("MaxLow", FUNC_MAXIMUM, 0, 100, 0, MODE_LOW);
SetFuncParameters("MinLow", FUNC_MINIMUM, 0, 100, 0, MODE_LOW);
SetFuncParameters("MaxVolume", FUNC_MAXIMUM, 0, 100, 0, MODE_VOLUME);
SetFuncParameters("MinVolume", FUNC_MINIMUM, 0, 100, 0, MODE_VOLUME);
SetFuncParameters("Abs", FUNC_ABS);
SetFuncParameters("Log", FUNC_LOG);
SetFuncParameters("Exp", FUNC_EXP);
SetFuncParameters("Rnd", FUNC_RND);
SetFuncParameters("Round", FUNC_ROUND);
SetFuncParameters("Max", FUNC_MAX);
SetFuncParameters("Min", FUNC_MIN);
SetFuncParameters("Ask", FUNC_ASK);
SetFuncParameters("Bid", FUNC_BID);
SetFuncParameters("Last", FUNC_LAST);
ArrayInitialize(DefaultFuncSymCount,1);
DefaultFuncSymCount[FUNC_RND]=0;
DefaultFuncSymCount[FUNC_MAX]=2;
DefaultFuncSymCount[FUNC_MIN]=2;
}
//--------------------------------------------------------------------
int Indicator_init()
{
IndicatorShortName("");
for (int i=1; i<1000; i++)
{
IndicatorName="ChartBuilder ("+i+")";
if (WindowFind(IndicatorName)<0) break;
}
IndicatorShortName(IndicatorName);
IndicatorPrefix=IndicatorName;
MainChartIndex=i;
InitObjects(i,0);
Signal_HighValue= StringTrimLeft(StringTrimRight(Signal_HighValue));
Signal_LowValue= StringTrimLeft(StringTrimRight(Signal_LowValue));
Signal_HighLine= StringTrimLeft(StringTrimRight(Signal_HighLine));
Signal_LowLine= StringTrimLeft(StringTrimRight(Signal_LowLine));
if (Signal_HighValue=="" && Signal_LowValue=="" && Signal_HighLine=="" && Signal_LowLine=="")
Signal_ChartNumber= "";
Formulas[0]=Formula1;
Formulas[1]=Formula2;
Formulas[2]=Formula3;
Formulas[3]=Formula4;
Formulas[4]=Formula5;
Formulas[5]=Formula6;
Formulas[6]=Formula7;
Formulas[7]=Formula8;
Colors[0]=Color1;
Colors[1]=Color2;
Colors[2]=Color3;
Colors[3]=Color4;
Colors[4]=Color5;
Colors[5]=Color6;
Colors[6]=Color7;
Colors[7]=Color8;
if (ArraySize(SymbolsIndexes)>0) ArrayInitialize(SymbolsIndexes,-1);
ArrayInitialize(ChartAllow,0);
ArrayInitialize(AlgoEnabled,0);
ArrayInitialize(PrintedError,0);
ArrayInitialize(ChartCheckSignal, 0);
MaxCharts=8;
if (!OnlyClosePrice) MaxCharts=2;
else if (Formulas[4]+Formulas[5]+Formulas[6]+Formulas[7]=="") MaxCharts=4;
BuffersPerChart= 8/MaxCharts;
int charts=0;
ArrayInitialize(IsFormulaUsing,false);
IsIndicator=true;
OnlyNumbers= StringTrimLeft(StringTrimRight(OnlyNumbers));
for (int n=0; n<MaxCharts; n++)
{
ErrorChartText[n]="";
charts++;
if (Formulas[n]=="") continue;
if (SetFormula(Formulas[n],n+1)==true) //FormulaAlgoIndex[n]=AddFormula(Formulas[n]);
{ charts++; ChartAllow[n]=true; }
else { ErrorChartText[n]= "- " +ErrorString; Print(Formulas[n],": ",ErrorString); }//Formulas[n]="";
if (StringSubstr(Formulas[n], 0, 1)=="'") ChartAllow[n]=false;
}
SetLevelStyle(STYLE_SOLID, 1, DarkGray);
for (i=0; i<8; i++)
{
if (OnlyNumbers!="")
if (!FindWordInString(OnlyNumbers,i+1)) { ChartAllow[i]=false; if (!IsFormulaUsing[i+1]) Formulas[i]=""; }
if (IsFormulaUsing[i]==true && CacheMinSize[i]==0) CacheMinSize[i]=1;
SetLevelValue(i, 0);
if (FindWordInString(Signal_ChartNumber, ""+(i+1)) == true)
ChartCheckSignal[i]= true;
}
if (IsFormulaUsing[ArrayMaximum(IsFormulaUsing)] > 0)
for (i=0; i<8; i++) if (Formulas[i]!="")
if (!LabelsOnTheRight) Formulas[i]= "F" +(i+1) +"= " +Formulas[i];
else Formulas[i]= Formulas[i] +" =" +"F" +(i+1);
//if (!true)
//for (n=1; n<=ArrayRange(Algorithms,0); n++)
//Alert(n," ",AlgoNames[n]," ",CacheStartPos[n]," ",CachePos[n]," ",CacheMinSize[n]);
if (charts==0)
{
StartMessage="No formula"; //"Íå çàäàíà íè îäíà ôîðìóëà";
Exit=true; return(0);
}
string txt="";
if (!OnlyClosePrice && ArraySize(FuncParam)>0)
{
ArrayCopy(FuncParam1,FuncParam);
ArrayCopy(FuncParam2,FuncParam);
ArrayCopy(FuncParam3,FuncParam);
for (int f=0; f<ArrayRange(FuncParam,0); f++)
{
if (FuncParam1[f][0]==FUNC_CLOSE && FuncParam1[f][2]==0) FuncParam1[f][0]=FUNC_OPEN;
if (FuncParam2[f][0]==FUNC_CLOSE && FuncParam2[f][2]==0) FuncParam2[f][0]=FUNC_HIGH;
if (FuncParam3[f][0]==FUNC_CLOSE && FuncParam3[f][2]==0) FuncParam3[f][0]=FUNC_LOW;
}
}
int SymbolsCount= ArraySize(Symbols);
IndDigits=PrecisionDigits;
string errsymbols="";
for (int s=0; s<SymbolsCount; s++)
{
string symbol= Symbols[s];
if (symbol==StringUpperCase(CURRENT_SYMBOL)) Symbols[s]=Symbol();
if (MarketInfo(symbol, MODE_TIME)<0 || GetLastError()==4106) // íåèçâåñòíûé ñèìâîë
if (MarketInfo(StringUpperCase(symbol), MODE_TIME) <0 || GetLastError()==4106)
{ errsymbols=errsymbols+symbol+" "; continue; }
else symbol= StringUpperCase(symbol);
if (PrecisionDigits==-1) IndDigits= MathMax(IndDigits, MarketInfo(symbol,MODE_DIGITS));
}
if (errsymbols!="")
{ errsymbols="Symbols not found in MarketWatch: "+errsymbols; Print(errsymbols); StartMessage=errsymbols; } //"Ñèìâîëû íå íàéäåíû â "Îáçîðå Ðûíêà": "
if (IndDigits==-1) IndDigits=2;
IndicatorDigits(IndDigits);
AllowGetPriceLine=false;
for (f=ArrayRange(FuncParam,0)-1; f>=0; f--)
switch (FuncParam[f][0])
{ case FUNC_LINEOPEN: case FUNC_LINECLOSE: case FUNC_LINEHIGH: case FUNC_LINELOW:
AllowGetPriceLine=true; f=0;
}
VLineTime=0;
SetIndexBuffer(0, buffer0); ArrayInitialize(buffer0,EMPTY_VALUE);
SetIndexBuffer(1, buffer1); ArrayInitialize(buffer1,EMPTY_VALUE);
SetIndexBuffer(2, buffer2); ArrayInitialize(buffer2,EMPTY_VALUE);
SetIndexBuffer(3, buffer3); ArrayInitialize(buffer3,EMPTY_VALUE);
SetIndexBuffer(4, buffer4); ArrayInitialize(buffer4,EMPTY_VALUE);
SetIndexBuffer(5, buffer5); ArrayInitialize(buffer5,EMPTY_VALUE);
SetIndexBuffer(6, buffer6); ArrayInitialize(buffer6,EMPTY_VALUE);
SetIndexBuffer(7, buffer7); ArrayInitialize(buffer7,EMPTY_VALUE);
InitBuffersProperties();
ArrayInitialize(AutoScaleRatio,0);
ArrayInitialize(AutoScaleShift,0);
AutoScale_BaseChart=0;
return(0);
// Ôóíêöèè, èñïîëüçóåìûå äëÿ ýêñïîðòà â äðóãèå ñîâåòíèêè
double dblarr[]; int intarr[]; string strarr[];
AddFormulaForOwnRates("");
CountFormulaValue("",0);
CountMyFormulaValue(0,0,dblarr);
CountMyFormulaWithOwnValues(0,0,dblarr,strarr,dblarr);
CountFormulaWithOwnSymRates(0,0,intarr,dblarr,intarr,dblarr);
GetFormulaSymbols(0,strarr);
GetFormulaSymIndexes(0,intarr);
GetAllFormulasSymbols(strarr);
GetFormulaSymFuncNames(0,0,strarr);
GetFormulaSymPowRatio(0,0,dblarr);
}
//--------------------------
void InitBuffersProperties()
{
if (OnlyClosePrice)
for (int i=0; i<8; i++)
{
int chart= i/BuffersPerChart+1;
int drawmode=DrawMode;
if (i%BuffersPerChart >0) drawmode=DRAW_ARROW;
SetIndexLabel(i, "Chart "+chart+" Close");
SetIndexStyle(i, drawmode, STYLE_SOLID, 1, Colors[chart-1]); //DRAW_ARROW
SetIndexArrow(i, 158);
}
else
for (i=0; i<8; i+=4)
{
chart= i/4+1;
SetIndexStyle(i, DRAW_ZIGZAG, STYLE_SOLID, 1, Colors[chart-1]);
SetIndexStyle(i+1, DRAW_ZIGZAG, STYLE_SOLID, 1, Colors[chart-1]);
SetIndexStyle(i+2, DRAW_HISTOGRAM, STYLE_SOLID, 1, Colors[chart-1]);//DRAW_HISTOGRAM
SetIndexStyle(i+3, DRAW_HISTOGRAM, STYLE_SOLID, 0, Black); // ,STYLE_DOT
SetIndexLabel(i, "Chart "+chart+" Open");
SetIndexLabel(i+1, "Chart "+chart+" Close");
SetIndexLabel(i+2, "Chart "+chart+" High");
SetIndexLabel(i+3, "Chart "+chart+" Low");
}
}
//--------------------------------------------------------------------
void InitObjects(int mainchart, int subchart)
{
string chartprefix= "ChartBuilder" +mainchart;
if (subchart>0) chartprefix= chartprefix +"-" +subchart;
for (int n=0; n<8; n++)
{
string prefix= chartprefix +"-" +(n+1) +" ";
ChartLabels[n]= prefix +" Label";
ChartLabels_[n]= prefix +" Label_";
ChartErrorLabels[n]= prefix +" ErrorLabel";
LineAsk[n]= prefix +" Ask";
LineBid[n]= prefix +" Bid";
VLine= chartprefix +" GetPriceLine";
ObjectDelete(ChartLabels[n]);
ObjectDelete(ChartLabels_[n]);
ObjectDelete(ChartErrorLabels[n]);
ObjectDelete(LineAsk[n]);
ObjectDelete(LineBid[n]);
}
StatusLabel= chartprefix +" StatusLabel";
SignalLabel= chartprefix +" SignalLabel";
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
if (!IsIndicator) return(0);
DeleteObjects();
ObjectDelete(DropWindowIdObject);
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
if (FirstStart) Indicator_init();
Window= FindIndicatorWindow();
FirstStart=false;
if (Exit) return(0);
int ticks0= GetTickCount();
//if (WrongWindow) Window=-1;
if (Window>-1) DrawStatusLabel("");
if (StartMessage!="" && Window>-1)
{ DrawStatusLabel(StartMessage); StartMessage=""; }
if (!AllowGetPriceLine) ObjectDelete(VLine);
int counting_bars= Bars-IndicatorCounted();
int ChartMinTime[];
if (!CheckValidCharts(ChartMinTime, ChartValid, counting_bars)) return(0);
if (Signal_ChartNumber!="")
DrawChartLabel(8, "Signal chart: "+Signal_ChartNumber);
if (IndicatorCounted()==0)
{
InitBuffersProperties();
ArrayInitialize(CachePos,-1);
}
if (AllowGetPriceLine && Window>=0)
{
if (ObjectFind(VLine)==-1)
{
int LineBar= MathMax(0, WindowFirstVisibleBar()-WindowBarsPerChart()/2);
ObjectCreate(VLine,OBJ_VLINE,Window,Time[LineBar],0);
if (GetLastError()==4206) { WrongWindow=true; AllowGetPriceLine=false; }
ObjectSet(VLine,OBJPROP_BACK,0);
ObjectSetText(VLine,"Get Price");
}
int time=ObjectGet(VLine,OBJPROP_TIME1);
if (time!=VLineTime) counting_bars=Bars;
VLineTime=time; //VLineBar=iBarShift(NULL,0,time);
}
double PriceAsk[8], PriceBid[8];
bool PriceAskOK[8], PriceBidOK[8];
int PriceTypes[]={ PRICE_OPEN, PRICE_CLOSE, PRICE_HIGH, PRICE_LOW};
ArrayInitialize(FuncLastTime,-1); // î÷èùàåì êýø ôóíêöèé
int barsynctime=BarTimeSyncSize;
if (BarTimeSyncSize>0)
{
barsynctime=BarTimeSyncSize*60; // ïðèâÿçêà ïî ìèíóòàì
if (!BarTimeSyncMode_ByMinutes) barsynctime*=Period(); // ïðèâÿçêà ïî áàðàì
}
int param[3];
param[0]= Period();
param[1]= barsynctime;
param[2]= barsynctime;
int timeshift= TimeShiftFromMainChart_minutes*60; // timeshift
int pricetype=PRICE_CLOSE;
//int autoscale_basechart=-1;
for (int chart=0; chart<8; chart++) SetLevelValue(chart,0);
//if (autoscale_basechart<0 && ChartValid[chart]==true && ChartAllow[chart]==true) autoscale_basechart=chart;
//if (autoscale_basechart != AutoScale_BaseChart) { counting_bars= Bars; AutoScale_BaseChart= autoscale_basechart; }
int ticks1=GetTickCount();
//if (counting_bars!=1) return(0);
for (int i=counting_bars-1; i>=-3; i--)
{
if (i==-1 || i==-2) if (!ShowBidAsk) continue; // Bid/Ask
int pricetypeindex=0;
int lastchart=-1;
for (chart=0; chart<MaxCharts; chart++)
{
if (i<0) if (AutoScale && chart>0) break;
if (!ChartAllow[chart]) continue;
if (!ChartValid[chart]) continue;
if (chart!=lastchart) pricetypeindex=0;
lastchart=chart;
int buf0= chart * BuffersPerChart;
if (Time[i]<ChartMinTime[chart] && i>=0) // âûøëè çà ïðåäåëû ãðàôèêà îäíîãî èç ñèìâîëîâ
{
for (int b=0; b<BuffersPerChart; b++) SetBuffer(buf0+b, i, EMPTY_VALUE); // î÷èùàåì çíà÷åíèå áóôåðà
continue;
}
if (i>=0)
if (OnlyClosePrice)
for (b=0; b<BuffersPerChart; b++) SetBuffer(buf0+b, i, EMPTY_VALUE);
else
pricetype=PriceTypes[pricetypeindex];
if (i<0) { pricetype=PRICE_CLOSE; if (pricetypeindex>0) continue; }
double result[2];
//if (!CountMyFormulaValueExt(chart,i,param,result)) continue;
int f= chart+1;
time= Time[i]-timeshift;
if (i<0) time=i;
bool ok=0;
switch (pricetype)
{
case PRICE_CLOSE: ok= CountFormula(f, Algorithms, FuncParam, Symbols, time, param, MyRates, MyRatesPos, result); break;
case PRICE_OPEN: ok= CountFormula(f, Algorithms, FuncParam1, Symbols, time, param, MyRates, MyRatesPos, result); break;
case PRICE_HIGH: ok= CountFormula(f, Algorithms, FuncParam2, Symbols, time, param, MyRates, MyRatesPos, result); break;
case PRICE_LOW: ok= CountFormula(f, Algorithms, FuncParam3, Symbols, time, param, MyRates, MyRatesPos, result); break;
}
if (!ok)
{
if (i>=0) SetBuffer(buf0+pricetypeindex, i, EMPTY_VALUE);
if (Error>0) DrawErrorChartLabel(chart,"- "+ErrorString);
if (Error>0 && Error!=ERROR_HISTORY && !PrintedError[chart][Error])
{ Print(AlgoNames[f]," : ",ErrorString); PrintedError[chart][Error]=true; }
ErrorString="";
if (Error==ERROR_FORMULA || Error==ERROR_RECURSION) { ChartValid[chart]=false; Error=0; break; }
Error=0;
continue;
}
double value=result[0];
if (PrecisionDigits>=0) value= NormalizeDouble(value,IndDigits);
if (i==-1) { PriceAsk[chart]=value; DrawLine(Window,LineAsk[chart],value,"Ask",Colors[chart]); PriceAskOK[chart]=true; } // Ask
if (i==-2) { PriceBid[chart]=value; DrawLine(Window,LineBid[chart],value,"Bid",Colors[chart]); PriceBidOK[chart]=true; } // Bid
if (i==-3) { SetLevelValue(chart, value); // Last
if (!ShowBidAsk) { PriceAsk[chart]=value; PriceBid[chart]=value; PriceAskOK[chart]=true; PriceBidOK[chart]=true; }
}
if (i<0) continue;
if (AutoScale && chart != AutoScale_BaseChart) if (AutoScaleRatio[chart]>0)
if (counting_bars!=Bars)
if (value!=EMPTY_VALUE)
value= value *AutoScaleRatio[chart] +AutoScaleShift[chart];
if (OnlyClosePrice)
{
SetBuffer(buf0,i,value); // çàïîëíÿåì òåêóùóþ ÿ÷åéêó îñíîâíîãî áóôåðà
if (BuffersPerChart==1) continue;
if (DrawMode!=DRAW_SECTION && DrawMode!=DRAW_ARROW && DrawMode!=DRAW_HISTOGRAM)
if (GetBuffer(buf0,i+1)==EMPTY_VALUE) // åñëè ïðåäûäóùàÿ ÿ÷åéêà îñíîâíîãî áóôåðà ïóñòàÿ (ò.å. îáðàçîâàëñÿ ðàçðûâ)
SetBuffer(buf0+1, i, GetBuffer(buf0,i)); // çàïîëíÿåì òåêóùóþ ÿ÷åéêó äîïîëíèòåëüíîãî áóôåðà (ðèñóåì arrow)
else
SetBuffer(buf0+1, i+1, EMPTY_VALUE); // èíà÷å î÷èùàåì ïðåäûäóùóþ ÿ÷åéêó äîïîëíèòåëüíîãî áóôåðà (âîçìîæíî îíà áûëà çàïîëíåíà çðÿ íà ïðåäûäóùåì áàðå)
}
else
{
int bufindex=buf0+pricetypeindex;
if (pricetype==PRICE_LOW)
{
double highvalue= GetBuffer(buf0+2, i);
if (MathAbs(value)>MathAbs(highvalue)) { SetBuffer(buf0+2, i, value); value=highvalue; } // ìåíÿåì áóôåðû ìåñòàìè
}
SetBuffer(bufindex,i,value);
pricetypeindex= (pricetypeindex+1)%BuffersPerChart;
if (pricetypeindex>0) chart--;
}
}
}
ObjectDelete(StatusLabel);
if (AutoScale && counting_bars==Bars)
AutoScale_BaseChart= SetAutoScale(); //AutoScale_BaseChart);
for (chart=0; chart<MAXCHARTS; chart++)
if (ChartCheckSignal[chart]==true)
CheckSignalLevels(chart, PriceBid[chart], PriceAsk[chart]);
//if (WrongWindow && Window>=0) Print("Wrong window (",Window,")");
if (SaveToFile_ChartNumber>0 && SaveToFile_ChartNumber<=8 && counting_bars==Bars)
SaveToFile(SaveToFile_FileName, SaveToFile_ChartNumber, counting_bars);
/*
int ticks2=GetTickCount();
static bool firsttime=1;
if (Debug && firsttime)
{
double res=0;
for (int bar_=0; bar_<Bars; bar_++)
for (int buf_=0; buf_<8; buf_++)
{
double res_= GetBuffer(buf_, bar_);
if (res != EMPTY_VALUE) res += res_;
}
Alert("checksum: ", res," ",counting_bars," bars ",ticks1-ticks0," ms, ",ticks2-ticks1," ms");
}
firsttime=0;
*/
return(0);
}
//---------------------------------------------------------------------------------
bool CheckValidCharts(int& ChartMinTime[], bool& ChartValid[], int& counting_bars)
{
int validcharts=0;
bool loadinghistory=false;
int SymbolsCount= ArraySize(Symbols);
int Periods[]={ 1, 5, 15, 30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1 };
static int LastSymBars[100][9]; ArrayResize(LastSymBars,SymbolsCount);
bool AccountConnected= (AccountNumber()>0);
int timeshift= TimeShiftFromMainChart_minutes*60;
ArrayResize(ChartMinTime, MaxCharts);
ArrayInitialize(ChartMinTime, 0);
ArrayInitialize(ChartValid, 1);
//ArrayResize(MySymRatesPos, SymbolsCount);
//ArrayInitialize(MySymRatesPos, -1);
static int ReadRatesPos[][2];
static int inittime;
int ts_count= ArrayRange(TimeSeries, 0);
if (inittime!=InitTime && ts_count>0) { ArrayResize(ReadRatesPos, ts_count); ArrayInitialize(ReadRatesPos, -2); } //ArrayInitialize(MySymRatesPos, -2);
inittime= InitTime;
if (ArraySize(ReadRatesPos)>0) ArrayCopy(MyRatesPos, ReadRatesPos); else ArrayResize(MyRatesPos, 0);
int ratespos=0;
for (int n=0; n<MaxCharts; n++)
{
if (Formulas[n]=="") continue;
DrawChartLabel(n, Formulas[n]);
if (ChartAllow[n]==0) { DrawErrorChartLabel(n,ErrorChartText[n]); continue; }
string UnknownCharts="";
string UnknownSymbols="";
int unknownsymbolscount=0;
ErrorString="";
string LoadingSymbolsStr="";
bool error=0;
int nestinglevel=0; // óðîâåíü âëîæåííîñòè ôóíêöèè
int nestingparam[20][3]; // ïàðàìåòðû âëîæåííîñòè
int a=n+1;
for (int f=0; f< ArrayRange(AlgoFunctions,1); f++)
{
int s=1;
if (AlgoFunctions[a][f]<0) // âëîæåííàÿ ôîðìóëà
{
nestinglevel--; if (nestinglevel<0) break;
a= nestingparam[nestinglevel][0]; f= nestingparam[nestinglevel][1]; s= nestingparam[nestinglevel][2]+1;
}
int func= AlgoFunctions[a][f];
int functype= FuncParam[func][0];
for (s=s; s<=DefaultFuncSymCount[functype]; s++)
{
int sym=FuncParam[func][s];
if (sym==EMPTY_VALUE) continue;
if (sym<0) // âëîæåííàÿ ôóíêöèÿ
{
int algo=-sym-1;
if (algo<=8) continue;
nestingparam[nestinglevel][0]= a; nestingparam[nestinglevel][1]= f; nestingparam[nestinglevel][2]= s;
nestinglevel++; a=algo; f=-1;
break;
}
string symbol= Symbols[sym];
int ts= FuncTimeSerie[func];
//Alert(symbol);
int tf= FuncParam[func][2];
if (tf==0) tf= Period();
int ibars, mintime;
if (MarketInfo(symbol,MODE_TIME)<0 || GetLastError()==4106)
{
if (MarketInfo(StringUpperCase(symbol),MODE_TIME)>=0 && GetLastError()!=4106)
{ symbol= StringUpperCase(symbol); Symbols[sym]=symbol; }
else
if (FindSymbolInSymbolsRow(symbol)==false) // ñèìâîë íå íàéäåí â ôàéëå symbols.row
{
int readcount=0;
if (ReadRatesPos[ts][1]==-2) // çíà÷èò ýòî ïåðâàÿ ïðîâåðêà
{
readcount= ReadSymbolHistory(symbol, tf, MyRates, ratespos);
ReadRatesPos[ts][0]= ratespos;
ReadRatesPos[ts][1]= readcount;
ArrayCopy0Int(MyRatesPos, ReadRatesPos, ts, ts, 1);
}
if (MyRatesPos[ts][1]<0) { UnknownSymbols=UnknownSymbols+symbol+" "; unknownsymbolscount++; continue; }
ratespos += readcount;
ibars= MyRatesPos[ts][1];
mintime= MyRates [MyRatesPos[ts][0]] [0];
}
}
if (MyRatesPos[ts][1]<=0)
{
ibars= iBars(symbol,tf);
if (ibars>0)
if (functype==FUNC_CLOSE || functype==FUNC_OPEN || functype==FUNC_HIGH || functype==FUNC_LOW)
{ // Ñîõðàíÿåì öåíîâûå çíà÷åíèÿ â ìàññèâ, ÷òîáû ïðè ðàñ÷¸òå áðàòü èõ îòòóäà - ýòî çíà÷èòåëüíî áûñòðåå, ÷åì èñïîëüçîâàòü ôóíêöèè äîñòóïà ê òàéìñåðèÿì
double rates[][6];
ibars= ArrayCopyRates(rates, symbol, tf);
if (ibars>0)
{
int newratespos=0;
int maxratesposserie= ArrayMaximum(MyRatesPos, ts_count);
//for (int ss=0; ss<SymbolsCount; ss++)
//if (ss==sym) break;
if (MyRatesPos[maxratesposserie][0]>=0 && MyRatesPos[maxratesposserie][1]>=0)
newratespos= MyRatesPos[maxratesposserie][0] + MyRatesPos[maxratesposserie][1];
//ArraySetAsSeries(MyRates, 1);
ArrayCopy0(MyRates, rates, newratespos, 0, ibars);
ArraySetAsSeries(MyRates, 0);
//Alert(ibars," ",newratespos," ",TimeToStr(MySymRates[0][0]));
MyRatesPos[ts][0]= newratespos;
MyRatesPos[ts][1]= ibars;
//Alert(func," ",ts," ",(MyRates[newratespos][4])," ",(MyRates[newratespos+ibars-1][4]));//," ",MyRatesPos[ts][1]);
}
}
mintime= iTime(symbol, tf, ibars-1);
}
int tfindex= ArrayBsearch(Periods, tf);
if (ibars< LastSymBars[sym][tfindex] || ibars> LastSymBars[sym][tfindex]+1) // âåðîÿòíî áûëè ïîäãðóæåíû íîâûå áàðû
counting_bars= Bars;
LastSymBars[sym][tfindex]= ibars;
if (GetLastError()==4066 && AccountConnected) // èñòîðèÿ ïîäãðóæàåòñÿ
{
error=true;
loadinghistory=true;
LoadingSymbolsStr= LoadingSymbolsStr+symbol+", "+GetPeriodName(tf)+" ";
LastSymBars[sym][tfindex]=0;
}
else if (ibars<=0)
UnknownCharts= UnknownCharts+symbol+", "+GetPeriodName(tf)+" ";
if (ibars>0)
ChartMinTime[n]= MathMax(ChartMinTime[n], mintime+timeshift);
}
}
if (UnknownCharts!="") { ErrorString="Charts not found: "+UnknownCharts+ErrorString; error=true; } //"Íå íàéäåí ÷àðò: "
else
if (unknownsymbolscount==1) { ErrorString="Unknown symbol: "+UnknownSymbols+ErrorString; error=true; } else //"- Íåèçâåñòíûé ñèìâîë: "
if (unknownsymbolscount>1) { ErrorString="Unknown symbols: "+UnknownSymbols+ErrorString; error=true; } // "- Íåèçâåñòíûå ñèìâîëû: "
if (LoadingSymbolsStr!="") ErrorString="Loading history... "+LoadingSymbolsStr; // - Ïîäãðóçêà èñòîðèè... "
if (ErrorString!="") DrawErrorChartLabel(n,"- "+ErrorString); else DrawErrorChartLabel(n,"");
if (error==0) { validcharts++; continue; }
ChartValid[n]=false;
}
//Alert(OwnSymRatesParam[0][0]," ",OwnSymRatesParam[0][1]);
//int x=OwnSymRatesParam[0][1]-1;
//Alert(TimeToStr(OwnSymRates[x][0])," ",OwnSymRates[x][1]," ",OwnSymRates[x][2]," ",OwnSymRates[x][3]," ",OwnSymRates[x][4]," ",OwnSymRates[x][5]);
if (loadinghistory) return(0);
if (validcharts==0) return(0);
return(true);
}
//-----------------
int SetAutoScale()
{
int leftvisiblebar= WindowFirstVisibleBar();
int rightvisiblebar= MathMax(leftvisiblebar-WindowBarsPerChart()+1, 0);
int visiblebars= leftvisiblebar-rightvisiblebar+1;
double max[MAXCHARTS], min[MAXCHARTS];
int chartbufcount= MAXCHARTS/MaxCharts;
int firstchart=-1;
for (int chart=-1; chart<MaxCharts; chart++)
{
if (!ChartAllow[chart] || !ChartValid[chart]) continue;
if (firstchart==-1) firstchart=chart;
int startbuf=chart*chartbufcount;
int maxbuf=startbuf;
int minbuf=startbuf;
if (!OnlyClosePrice)
{
maxbuf=startbuf+2;
minbuf=startbuf+3;
}
max[chart]=EMPTY_VALUE;
min[chart]=EMPTY_VALUE;
for (int b=leftvisiblebar; b>=rightvisiblebar; b--)
{
double maxvalue=GetBuffer(maxbuf,b);
if (maxvalue==EMPTY_VALUE) continue;
if (maxvalue>max[chart] || max[chart]==EMPTY_VALUE) max[chart]=maxvalue;
double minvalue=GetBuffer(minbuf,b);
if (minvalue==EMPTY_VALUE) continue;
if (minvalue<min[chart] || min[chart]==EMPTY_VALUE) min[chart]=minvalue;
}
if (chart==0) continue;
if (max[chart]==min[chart]) continue;
double ratio= (max[firstchart]-min[firstchart])/(max[chart]-min[chart]);
double shift= min[firstchart]-min[chart]*ratio;
for (int subbuf=0; subbuf<chartbufcount; subbuf++)
{
int buf= startbuf+subbuf;
for (b=0; b<Bars; b++)
{
double value= GetBuffer(buf, b);
if (value!=EMPTY_VALUE)
SetBuffer(buf, b, value*ratio+shift);
}
}
AutoScaleRatio[chart]= ratio;
AutoScaleShift[chart]= shift;
}
return(firstchart);
}
//--------------------------------------------------------------------------------------
bool CountMyFormulaValueExt(int n, int time, int param[], double& results[])
{
if (AlgoRange0==0) { Error=ERROR_FORMULA; return(0); }
if (!IsIndicator)
{ if (ArraySize(CachePos)>0) ArrayInitialize(CachePos,-1); if (ArraySize(FuncLastTime)>0) ArrayInitialize(FuncLastTime,-1); }
Error=0;
double rates[][]; int ratespos[][];
bool ok= CountFormula(n, Algorithms, FuncParam, Symbols, time, param, rates, ratespos, results);
return(ok);
}
//-----------------------------------------------------------
bool CountMyFormulaValue(int n, int time, double& results[])
{
int param[3]= {0, -1, -1};
bool result= CountMyFormulaValueExt(n, time, param, results);
return(result);
}
//----------------------------------------------------------------------------------------------
bool CountMyFormulaWithOwnValuesEx(int n, int time, int param[], double& results[], string symbols[], double ownvalues[])
{
if (AlgoRange0==0) { Error=ERROR_FORMULA; return(0); }
double FuncParamOwn[][PARAMCOUNT];
if (ArrayRange(FuncParam,0)>0) ArrayCopy(FuncParamOwn,FuncParam);
int v=0;
for (int i=0; i<ArrayRange(AlgoFunctions,1); i++)
{
int func=AlgoFunctions[n][i];
if (func<0) break;
int symindex=FuncParam[func][1];
switch (FuncParam[func][0])
{
case FUNC_OPEN: case FUNC_CLOSE: case FUNC_HIGH: case FUNC_LOW:
for (int s=0; s<ArraySize(symbols); s++)
if (symbols[s]==Symbols[symindex]) break;
if (s==ArraySize(symbols)) continue;
FuncParamOwn[func][0]= FUNC_FIXVALUE;
FuncParamOwn[func][1]= ownvalues[v];
v++;
}
}
ArrayInitialize(CachePos,-1); ArrayInitialize(FuncLastTime,-1);
Error=0;
double rates[][]; int ratespos[][];
bool ok= CountFormula(n ,Algorithms, FuncParamOwn, Symbols, time, param, rates, ratespos, results);
return(ok);
}
//----------------------------------------
bool CountMyFormulaWithOwnValues(int n, int time, double& results[], string symbols[], double myvalues[])
{
int param[2];
bool result= CountMyFormulaWithOwnValuesEx(n, time, param, results, symbols, myvalues);
return(result);
}
//--------------------------------------------------------------------------
double CountFormulaValue(string formula, int time)
{
int n= AddFormula(formula);
double results[2];
CountMyFormulaValue(n, time, results);
return(results[0]);
}
//--------------------------------------------------------
bool CountFormulaWithOwnSymRates(int n, int time, int param[], double myrates[][], int myratespos[][2], double& results[])
{
if (ArraySize(myrates)==0) return(0);
Error=0;
//UseOwnSymRates=true;
bool result= CountFormula(n, Algorithms, FuncParam, Symbols, time, param, myrates, myratespos, results);
return(result);
}
//--------------Ðàñ÷¸ò ôîðìóëû ------------------------------------
bool CountFormula(int n, double algorithms[][][], double funcparam[][], string symbols[],
int maintime, int& parameters[], double history[][6], int historypos[][2], double& result[])
{
int period= parameters[0];
int synctime= parameters[1]; // ìàêñèìàëüíàÿ ñèíõðîíèçàöèÿ ìåæäó çàäàííûì âðåìåíåì è âðåìåíåì ñàìîé ðàííåé ôóíêöèè
int synctime1= parameters[2]; // ìàêñèìàëüíàÿ ñèíõðîíèçàöèÿ ìåæäó âñåì ôóíêöèÿìè ôîðìóëû
if (period==0) period=Period();
int maintime0= maintime;
if (maintime <0) //maintime= (maintime/period/60)*period*60;
{
n= GetBidAskFormula(n,maintime);
if (n<0) return(0);
ArrayInitialize(CachePos,-1);
maintime=TimeCurrent();
}
static bool CacheAllow=true;
int mycachepos=CachePos[n];
if (false)
if (maintime0>=0)
if (mycachepos>=CacheStartPos[n])
if (CacheTimeBuffer[mycachepos]==maintime) { result[0]=CacheValueBuffer[mycachepos]; result[1]=maintime; return(true); }
int maxfunctime=0; // íàèáîëüøåå âðåìÿ áàðà, ïîëó÷åííîå èç ôóíêöèè
result[0]=EMPTY_VALUE;
for (int f=0; f<FUNCRANGE1; f++) // Âû÷èñëÿåì çíà÷åíèÿ âñåõ ôóíêöèé
{
int funcindex= AlgoFunctions[n][f];
if (funcindex<0) break;
int functype= funcparam[funcindex][0];
if (!true)
if (functype==FuncLastType[funcindex] && maintime==FuncLastTime[funcindex]) continue; // åñëè ðåçóëüòàò ôóíêöèè óæå åñòü â êýø-áóôåðå, òî áåð¸ì åãî îòòóäà
FuncLastTime[funcindex]=-1;
FuncLastType[funcindex]=functype;
if (functype==FUNC_FIXVALUE)
{ FuncLastValue[funcindex]=funcparam[funcindex][1]; continue; }
int funcsymindexcount=DefaultFuncSymCount[functype];
for (int s=1; s<=funcsymindexcount; s++)
{
int symindex= funcparam[funcindex][s];
if (symindex==EMPTY_VALUE) break;
int findtime= maintime;
if (functype==FUNC_LINECLOSE || functype==FUNC_LINEOPEN || functype==FUNC_LINEHIGH || functype==FUNC_LINELOW)
if (!WrongWindow) findtime=VLineTime; else return(0);
//if (functype!=FUNC_OPEN && functype!=FUNC_LINEOPEN) findtime= (maintime/period/60+1)*60*period-1;
//if (symindex>=0 && maintime0<0) return(0);
if (symindex<0) // çíà÷èò èñïîëüçóåòñÿ ññûëêà íà ôîðìóëó
{
static int recurslevel=0;
int formindex= -symindex-1;
if (!AlgoEnabled[formindex])
{
Error=ERROR_FORMULA; ErrorString="Wrong formula!"; if (recurslevel>0) ErrorString="Wrong formula: "+AlgoNames[n]; // Íåêîððåêòíàÿ ôîðìóëà
return(0);
}
//if (maintime0<0) return(0);
int formtf= funcparam[funcindex][2]; if (formtf==0) formtf=period;
if (funcsymindexcount>1) formtf=period;
static int param[3];
param[0]= formtf;
param[1]= synctime;//-1; // synctime
param[2]= synctime1;
recurslevel++;
if (recurslevel>20) { recurslevel--; Error=ERROR_RECURSION; ErrorString="Recursion overflow!"; return(0); } //"Ïðåâûøåí ïðåäåë ðåêóðñèè"
int funccachesize= FuncCacheMinSize[funcindex];
int newbars=funccachesize;
if (CachePos[formindex]>=CacheStartPos[formindex] && CachePos[n]>=CacheStartPos[n] && funccachesize>0)
newbars= (maintime-CacheTimeBuffer[CachePos[n]])/formtf/60; // fillcache=true; // || formtf<period
bool cachefilled=true;
if (newbars==1) cachefilled= CountFormula(formindex,algorithms,funcparam,symbols,findtime,param,history,historypos,result);
if (newbars>1)
{
int lefttimelimit=0;
if (CachePos[n]>=CacheStartPos[n]) lefttimelimit= CacheTimeBuffer[CachePos[n]];
if (CachePos[formindex] >=CacheStartPos[formindex])
{ lefttimelimit= MathMax(lefttimelimit, CacheTimeBuffer[CachePos[formindex]]); }
int formcachesize= CacheMinSize[formindex];
CacheMinSize[formindex]= 0; // âðåìåííî îòêëþ÷àåì êýøèðîâàíèå äëÿ ôîðìóëû, ò.ê. áóäåì ñàìè çàïîëíÿòü áóôåð
double pricebuffer[1000];
int timebuffer[1000];
static int buffersize=0;
int startbuffersize=buffersize; // çíà÷åíèå buffersize ìîæåò ìåíÿòüñÿ â õîäå ðåêóðñèâíûõ âûçîâîâ, ïîýòîìó ñîõðàíÿåì åãî íà÷àëüíîå çíà÷åíèå
if (funccachesize>0) buffersize+=funccachesize; else buffersize+=1000;
if (buffersize > ArraySize(pricebuffer)) { ArrayResize(pricebuffer,buffersize); ArrayResize(timebuffer,buffersize); }
findtime= findtime/60/formtf*formtf*60;
int ftime=findtime;
for (int count=0; count<funccachesize || funccachesize<0; count++)
{
if (!CountFormula(formindex, algorithms, funcparam, symbols, ftime, param, history, historypos, result)) break;
if (count==buffersize) // áóôåð çàïîëíåí
{
ArrayCopy(pricebuffer, pricebuffer, 1000, 0);
ArrayCopy(timebuffer, timebuffer, 1000, 0); // ñäâèíóëè âåñü ìàññèâ íà 1000 ýëåìåíòîâ âïðàâî
buffersize+=1000;
}
if (result[1]<=lefttimelimit) break;
pricebuffer[buffersize-count-1]= result[0]; // çàïîëíÿåì ëåâóþ ÷àñòü ìàññèâà â îáðàòíîì ïîðÿäêå (ñïðàâà íàëåâî)
timebuffer[buffersize-count-1]= result[1]; //if (result[1]==timebuffer[buffersize-(count-1)-1]) Alert(TimeToStr(lefttimelimit)," !!! ",TimeToStr(ftime)," ",TimeToStr(result[1]));
ftime= result[1]-formtf*60;
param[2]= formtf; // òàéìôðåéì
}
if (count>0) // && (mainbar>=0 || mainbar<-3))
{
if (CacheStartPos[formindex]+count > CacheStartPos[formindex+1] && formindex < ArraySize(CacheStartPos)-1)
ResizeCache(formindex,+1000);
if (CachePos[formindex]<0) CachePos[formindex]= CacheStartPos[formindex]-1;
int oldcount= CachePos[formindex]-CacheStartPos[formindex]+1; // èìåþùèåñÿ ñòàðûå ýëåìåíòû â áóôåðå
if (funccachesize>0) oldcount= MathMin(oldcount, funccachesize-count); // îñòàâëÿåì òîëüêî ìèíèìàëüíî íåîáõîäèìîå êîëè÷åñòâî ñòàðûõ ýëåìåíòîâ
if (oldcount>0 && funccachesize>0)
{ // ñîõðàíÿåì ÷àñòü ñòàðûõ çíà÷åíèé (ñäâèãàåì èõ ê íà÷àëüíîé ïîçèöèè áóôåðà)
ArrayCopy(CacheValueBuffer, CacheValueBuffer, CacheStartPos[formindex], CachePos[formindex]-oldcount+1, oldcount);
ArrayCopy(CacheTimeBuffer, CacheTimeBuffer, CacheStartPos[formindex], CachePos[formindex]-oldcount+1, oldcount);
} // ñîõðàíÿåì íîâûå çíà÷åíèÿ ñëåäîì çà ñòàðûìè
ArrayCopy(CacheValueBuffer, pricebuffer, CacheStartPos[formindex]+oldcount, buffersize-count, count);
ArrayCopy(CacheTimeBuffer, timebuffer, CacheStartPos[formindex]+oldcount, buffersize-count, count);
CachePos[formindex]= CacheStartPos[formindex]+oldcount+count-1;
}
CacheMinSize[formindex]=formcachesize; //{ Alert(formindex," ",formcachesize); }
buffersize=startbuffersize;
if (lefttimelimit==0) if (count<funccachesize) cachefilled=false;
}
recurslevel--;
if (!cachefilled) return(0);
}
}
if (s<=funcsymindexcount) return(0);
double value=0;
if (!CountFunction(funcparam, funcindex, period, findtime, synctime, history, historypos, value)) return(0); // â ïåðåìåííóþ cellvalue ïîëó÷àåì çíà÷åíèå
if (GetLastError()==4066) { Error=ERROR_HISTORY; ErrorString="Loading history..."; return(0); } // Ïîäãðóçêà èñòîðèè...
if (maxfunctime-findtime > synctime1 && synctime1>=0) return(0);
maxfunctime= MathMax(findtime, maxfunctime);
FuncLastTime[funcindex]= maintime;
FuncLastValue[funcindex]= value; // êýøèðóåì ïîëó÷åííîå çíà÷åíèå ôóíêöèè
}
static double array[][ALGORANGE1][ALGORANGE2];
int totalrange= ALGORANGE1 * ALGORANGE2;
ArrayCopy(array, algorithms, 0, n*totalrange, totalrange);
for (int i=0; ; i++) // Ðàññ÷èòûâàåì àëãîðèòì ôîðìóëû
{
double cellvalue= array[0][i][CELLVALUE];
int maincell= array[0][i][CELLNEXTCELL];
int celltype= array[0][i][CELLTYPE];
funcindex=cellvalue;
if (celltype==TYPE_FUNC) cellvalue= FuncLastValue[funcindex];
if (maincell <=0) break;
if (array[0][maincell][CELLTYPE]==TYPE_FUNC)
{
funcindex= array[0][maincell][CELLVALUE];
array[0][maincell][CELLVALUE]= FuncLastValue[funcindex];
array[0][maincell][CELLTYPE]= TYPE_VALUE;
}
switch (array[0][i][CELLOPERATION])
{
case '+': array[0][maincell][CELLVALUE]+=cellvalue; break;
case '-': array[0][maincell][CELLVALUE]= cellvalue - array[0][maincell][CELLVALUE]; break;
case '*': array[0][maincell][CELLVALUE]*=cellvalue; break;
case '/': if (array[0][maincell][CELLVALUE]==0) { Error=ERROR_ZERODIVIDE; ErrorString="Zero divide!"; return(0); }
array[0][maincell][CELLVALUE]= cellvalue / array[0][maincell][CELLVALUE]; break;
case '^':
double pow= array[0][maincell][CELLVALUE];
if (cellvalue==0 && pow<0) { Error=ERROR_ZERODIVIDE; ErrorString="Zero divide!"; Exit=true; return(0); } // "Äåëåíèå íà íîëü!"
if (cellvalue<0) if (MathMod(pow,1)>0) { Error=ERROR_POW; ErrorString="Exponentiation error!"; return(0); } //Îøèáêà âîçâåäåíèÿ â ñòåïåíü! (äðîáíûé ïîêàçàòåëü è îòðèöàòåëüíîå îñíîâàíèå)");
if (pow==-1) array[0][maincell][CELLVALUE]= 1/cellvalue;
else array[0][maincell][CELLVALUE]= MathPow(cellvalue, array[0][maincell][CELLVALUE]);
break;
default: return(0);
}
}
result[0]=cellvalue;
result[1]=maxfunctime;
if (maintime0<0) return(true); //if (mainbar<0 && mainbar>=-3) return(true);
if (CacheMinSize[n]==0) return(true);
// Êýøèðóåì ïîëó÷åííîå çíà÷åíèå ôîðìóëû
//maintime= maintime/period/60*period*60;
int cachepos= CachePos[n];
if (cachepos==-1) cachepos= CacheStartPos[n]-1;
if (CacheMinSize[n]!=1)
{
if (cachepos>=0) if (maxfunctime<=CacheTimeBuffer[cachepos]) cachepos--;
cachepos++;
int endcache= CacheStartPos[n+1];
if (endcache==0) endcache=ArraySize(CacheValueBuffer);
if (cachepos >= endcache) //CacheStartPos[n]+CacheMinSize[n]);
if (CacheMinSize[n]<0) ResizeCache(n,+1000);
else
{
int newcachepos= CacheStartPos[n] + CacheMinSize[n]-1;
ArrayCopy(CacheValueBuffer, CacheValueBuffer, CacheStartPos[n], cachepos-CacheMinSize[n], CacheMinSize[n]);
ArrayCopy(CacheTimeBuffer, CacheTimeBuffer, CacheStartPos[n], cachepos-CacheMinSize[n], CacheMinSize[n]);
cachepos=newcachepos;
}
}
else cachepos= CacheStartPos[n];
CachePos[n]= cachepos;
CacheValueBuffer[cachepos] = cellvalue;
CacheTimeBuffer[cachepos] = maxfunctime;//maintime;
return(true);
}
//---------------------------------------
bool ResizeCache(int index, int addsize)
{
int buffersize=ArraySize(CacheValueBuffer);
if (index+1>=ArraySize(CacheStartPos))
{ ArrayResize(CacheValueBuffer,buffersize+addsize); ArrayResize(CacheTimeBuffer,buffersize+addsize); return(0); }
int nextstartpos=CacheStartPos[index+1];
ArrayCopy(CacheTimeBuffer, CacheTimeBuffer, nextstartpos+addsize, nextstartpos);
ArrayCopy(CacheValueBuffer, CacheValueBuffer, nextstartpos+addsize, nextstartpos);
for (int i=index+1; i<ArraySize(CacheStartPos); i++)
{
CacheStartPos[i]+=addsize;
CachePos[i]+=addsize;
}
}
//------ Ðàñ÷¸ò çíà÷åíèÿ ôóíêöèè ----------------------------------------------------
bool CountFunction(double Param[][], int n, int maintf, int& findtime, int synctime, double Rates[][], int RatesPos[][], double& value)
{
int oldtime=findtime;
int functype= Param[n][0];
int bartime;
int symindex=EMPTY_VALUE;
int symindexcount= DefaultFuncSymCount[functype];
int pos[PARAMCOUNT];
if (symindexcount==1) int tf= Param[n][2];
if (tf==0) tf=maintf;
int maxtime=0;
int ts= FuncTimeSerie[n];
for (int s=1; s<=symindexcount; s++)
{
symindex= Param[n][s];
if (symindex==EMPTY_VALUE) return(0);
if (maintf==0) maintf=Period();
if (functype==FUNC_BID || functype==FUNC_ASK || functype==FUNC_LAST)
{
if (symindex<0) return(0);
if (RatesPos[tf][1]>0) return(0);
string symbol= Symbols[symindex];
if (functype==FUNC_BID || functype==FUNC_ASK) symbol= GetQuoteSymbol(symbol);
if (functype==FUNC_BID || functype==FUNC_LAST) value= MarketInfo(symbol,MODE_BID); else
if (functype==FUNC_ASK) value= MarketInfo(symbol,MODE_ASK); else return(0);
if (GetLastError()==4106) { Error=ERROR_SYMBOL; ErrorString="Unknown symbol: "+symbol; return(0); } // íå íàéäåí òàêîé èíñòðóìåíò
findtime= MarketInfo(symbol,MODE_TIME);
return(true);
}
if (symindex>=0) // òðåáóåòñÿ ðàññ÷èòàòü ôóíêöèþ íà äàííûõ èç òàéì-ñåðèè ëèáî èç ïîëüçîâàòåëüñêîãî ìàññèâà
{
if (RatesPos[ts][1]<=0) //if (!UseOwnSymRates)
{
symbol= Symbols[symindex];
int bar= iBarShift(symbol,tf,findtime);
bartime= iTime(symbol,tf,bar);
int ibars= iBars(symbol,tf);
}
else
{ // áàðû èäóò ñëåâà íàïðàâî
int i= ArrayBsearch(Rates, findtime, RatesPos[ts][1], RatesPos[ts][0], MODE_ASCEND);
bartime= Rates[i][0];
bar= i-RatesPos[ts][0];
ibars= RatesPos[ts][1];
}
if (bartime>findtime || ibars==0) { findtime=0; return(0); }
}
else // òðåáóåòñÿ ðàññ÷èòàòü ôóíêöèþ íà äàííûõ èç êýø-áóôåðà
{
int formula_index= -symindex-1;
int formula_cachepos= CachePos[formula_index];
if (formula_cachepos==-1) formula_cachepos= CacheStartPos[formula_index]-1;
int formula_cachestartpos= CacheStartPos[formula_index];
if (findtime < CacheTimeBuffer[formula_cachestartpos]) { findtime=0; return(0); }
int formula_cachesize= formula_cachepos - formula_cachestartpos + 1;
i= formula_cachepos;
if (formula_cachesize > 0)
i= ArrayBsearch(CacheTimeBuffer, findtime, formula_cachesize, formula_cachestartpos, MODE_ASCEND);
bartime= CacheTimeBuffer[i];
bar= formula_cachepos - i;
ibars= formula_cachesize;
pos[s]= i;
}
maxtime=MathMax(maxtime,bartime);
if (synctime>=0)
{
bartime= bartime/60/maintf*maintf*60;
if (tf>=maintf)
{ if (findtime >= bartime+tf*60+synctime) return(0); }
else if (findtime < bartime+synctime) return(0);
}
if (bar + MathAbs(FuncCacheMinSize[n]) > ibars) return(0);
}
findtime=maxtime;
if (ts>=0 && RatesPos[ts][1]>0 && symindex>=0) //UseOwnSymRates==true)
{
switch (functype)
{
case FUNC_OPEN: value= Rates[i][1]; break;
case FUNC_LOW: value= Rates[i][2]; break;
case FUNC_HIGH: value= Rates[i][3]; break;
case FUNC_CLOSE: value= Rates[i][4]; break;
case FUNC_VOLUME: value= Rates[i][5]; break;
default: Error=ERROR_FORMULA; return(0);
}
return(true);
}
int period= Param[n][3];
if (period<=0) period+=ibars-bar;
if (functype==FUNC_MACD)
{ int period2=Param[n][4]; int period3=Param[n][5]; if (period2<=0) period2+=ibars-bar; if (period3<=0) period3+=ibars-bar; }
if (symindex>=0 && symindex!=EMPTY_VALUE)
switch (functype)
{
case FUNC_ATR:
value= iATR(symbol, tf, period, Param[n][4]+bar); break;
case FUNC_BANDS:
value= iBands(symbol, tf, period, Param[n][4], Param[n][5], Param[n][6], Param[n][7], Param[n][8]+bar); break;
case FUNC_MA:
value= iMA(symbol, tf, period, Param[n][4], Param[n][5], Param[n][6], Param[n][7]+bar); break;
case FUNC_STDDEV:
value= iStdDev(symbol, tf, period, Param[n][4], Param[n][5], Param[n][6], Param[n][7]+bar); break;
case FUNC_AD:
value= iAD(symbol, tf, Param[n][3]+bar); break;
case FUNC_ADX:
value= iADX(symbol, tf, period, Param[n][4], Param[n][5], Param[n][6]+bar); break;
case FUNC_CCI:
value= iCCI(symbol, tf, period, Param[n][4], Param[n][5]+bar); break;
case FUNC_DEMARKER:
value= iDeMarker(symbol, tf, period, Param[n][4]+bar); break;
case FUNC_ENVELOPES:
value= iEnvelopes(symbol, tf, period, Param[n][4], Param[n][5], Param[n][6], Param[n][7], Param[n][8], Param[n][9]+bar); break;
case FUNC_MACD:
value= iMACD(symbol, tf, period, period2, period3, Param[n][6], Param[n][7], Param[n][8]+bar); break;
case FUNC_MOMENTUM:
value= iMomentum(symbol, tf, period, Param[n][4], Param[n][5]+bar); break;
case FUNC_RSI:
value= iRSI(symbol, tf, period, Param[n][4], Param[n][5]+bar); break;
case FUNC_STOCHASTIC:
value= iStochastic(symbol, tf, period, Param[n][4], Param[n][5], Param[n][6], Param[n][7], Param[n][8], Param[n][9]+bar); break;
case FUNC_CLOSE: case FUNC_LINECLOSE:
value= iClose(symbol, tf, bar+Param[n][3]); break;
case FUNC_OPEN: case FUNC_LINEOPEN:
value= iOpen(symbol, tf, bar+Param[n][3]); break;
case FUNC_HIGH: case FUNC_LINEHIGH:
value= iHigh(symbol, tf, bar+Param[n][3]); break;
case FUNC_LOW: case FUNC_LINELOW:
value= iLow(symbol, tf, bar+Param[n][3]); break;
case FUNC_VOLUME:
value= iVolume(symbol, tf, bar+Param[n][3]); break;
case FUNC_MAXIMUM: case FUNC_MINIMUM:
if (functype==FUNC_MAXIMUM) bar= iHighest(symbol, tf, Param[n][5], period, Param[n][4]+bar);
else bar= iLowest(symbol, tf, Param[n][5], period, Param[n][4]+bar);
if (Param[n][5]==MODE_CLOSE) { value= iClose(symbol, tf, bar); break; }
if (Param[n][5]==MODE_HIGH) { value= iHigh(symbol, tf, bar); break; }
if (Param[n][5]==MODE_LOW) { value= iLow(symbol, tf, bar); break; }
if (Param[n][5]==MODE_OPEN) { value= iOpen(symbol, tf, bar); break; }
if (Param[n][5]==MODE_VOLUME){ value= iVolume(symbol, tf, bar); break; }
default: Error=ERROR_FORMULA; ErrorString="Unsupported function: "+DefaultFuncName[functype]; return(0);
}
else // if (if (symindex<0)
switch (functype)
{
case FUNC_MYATR:
value= MyFunc_ATR(CacheValueBuffer, CacheTimeBuffer, i, i-formula_cachestartpos+1, Param[n][3], Param[n][4], Param[n][5]); break;
case FUNC_BANDS:
value=iBandsOnArray(CacheValueBuffer, i+1, period, Param[n][4], Param[n][5], Param[n][7], Param[n][7]+bar); break;
case FUNC_MA:
value= iMAOnArray(CacheValueBuffer, i+1, period, Param[n][4], Param[n][5], Param[n][7]+bar); break;
case FUNC_STDDEV:
value= iStdDevOnArray(CacheValueBuffer, i+1, period, Param[n][4], Param[n][5], Param[n][7]+bar); break;
case FUNC_CCI:
value= iCCIOnArray(CacheValueBuffer, i+1, period, Param[n][5]+bar); break;
case FUNC_ENVELOPES:
value= iEnvelopesOnArray(CacheValueBuffer,i+1,period,Param[n][4],Param[n][5],Param[n][7],Param[n][8],Param[n][9]+bar); break;
case FUNC_MOMENTUM:
value= iMomentumOnArray(CacheValueBuffer,i+1,period,Param[n][5]+bar); break;
case FUNC_RSI:
value= iRSIOnArray(CacheValueBuffer,i+1,period,Param[n][5]+bar); break;
case FUNC_CLOSE: case FUNC_LINECLOSE: case FUNC_OPEN: case FUNC_LINEOPEN: case FUNC_VOLUME:
i-=Param[n][3];
value= CacheValueBuffer[i]; break;
case FUNC_MAXIMUM:
value= CacheValueBuffer[ArrayMaximum(CacheValueBuffer, period, i-period+1-Param[n][4])]; break; //if (bartime>=Time[2]) Alert(CacheValueBuffer[0]," ",CacheValueBuffer[1]," ",CacheValueBuffer[2]," ",CacheValueBuffer[3]); break;
case FUNC_MINIMUM:
value= CacheValueBuffer[ArrayMinimum(CacheValueBuffer, period, i-period+1-Param[n][4])]; break;
case FUNC_ABS:
value= MathAbs(CacheValueBuffer[i]); break;
case FUNC_LOG:
value= MathLog(CacheValueBuffer[i]); if (Param[n][2]!=0) value/=MathLog(Param[n][2]); break;
case FUNC_EXP:
value= MathExp(CacheValueBuffer[i]); break;
case FUNC_RND:
static bool rndinit; if (!rndinit) { MathSrand(TimeLocal()); rndinit=true; }
value= MathRand(); break;
case FUNC_ROUND:
value= MathRound(CacheValueBuffer[i]); break;
case FUNC_MAX:
value= MathMax(CacheValueBuffer[pos[1]], CacheValueBuffer[pos[2]]); break;
case FUNC_MIN:
value= MathMin(CacheValueBuffer[pos[1]], CacheValueBuffer[pos[2]]); break;
default: Error=ERROR_FORMULA; ErrorString="Unsupported function: "+DefaultFuncName[functype]; return(0);
}
return(true);
}
//-------------------------------------------------------------------------
int GetFunctionMinCacheSize(double& Param[][], int n)
{
int size=0;
int functype=Param[n][0];
switch(functype)
{
case FUNC_ATR: size= Param[n][3]+Param[n][4]; if (Param[n][3]==0) Param[n][3]=-size-1; break;
case FUNC_MYATR: if (Param[n][2]==0) Param[n][2]=Period();
size= Param[n][3] * (Param[n][4]+Param[n][5]+1) / Param[n][2]; break;
case FUNC_AD: size= Param[n][3]; break;
case FUNC_ADX: size= Param[n][3]+Param[n][6]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_BANDS: size= Param[n][3]+Param[n][5]+Param[n][8]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_CCI: size= Param[n][3]+Param[n][5]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_DEMARKER: size= Param[n][3]+Param[n][4]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_ENVELOPES: size= Param[n][3]+Param[n][9]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_MA: size= Param[n][3]+Param[n][4]+Param[n][7]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_MACD: size= Param[n][8]+MathMax(MathMax(Param[n][3],Param[n][4]),Param[n][5]);
if (Param[n][3]==0) Param[n][3]=-Param[n][8];
if (Param[n][4]==0) Param[n][4]=-Param[n][8];
if (Param[n][5]==0) Param[n][5]=-Param[n][8]; break;
case FUNC_MOMENTUM: size= Param[n][3]+Param[n][5]+1; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_RSI: size= Param[n][3]+Param[n][5]+1; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_STDDEV: size= Param[n][3]+Param[n][4]+Param[n][7]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_STOCHASTIC: size= Param[n][9]+MathMax(Param[n][3],Param[n][4]); if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_OPEN:
case FUNC_CLOSE:
case FUNC_HIGH:
case FUNC_LOW:
case FUNC_VOLUME: size= Param[n][3]+1; break;
case FUNC_LINEOPEN:
case FUNC_LINECLOSE:
case FUNC_LINEHIGH:
case FUNC_LINELOW: size= Param[n][3]; break;
case FUNC_MAXIMUM:
case FUNC_MINIMUM: size= Param[n][3]+Param[n][4]; if (Param[n][3]==0) Param[n][3]=-size; break;
case FUNC_LOG:
case FUNC_EXP:
case FUNC_ROUND: size= 1; break;
case FUNC_MAX:
case FUNC_MIN: size= 1;
}
if (Param[n][3]<=0 || ((Param[n][4]<=0 || Param[n][5]<=0) && functype==FUNC_MACD))
switch (functype)
{ case FUNC_ATR: case FUNC_MA: case FUNC_ADX: case FUNC_BANDS: case FUNC_CCI: case FUNC_DEMARKER: case FUNC_ENVELOPES: case FUNC_MACD:
case FUNC_MOMENTUM: case FUNC_RSI: case FUNC_STDDEV: case FUNC_STOCHASTIC: case FUNC_MAXIMUM: case FUNC_MINIMUM:
size=-MathMax(size,1);
}
return(size);
}
/*
//--------- Âû÷èñëÿåì ìàêñèìàëüíîå âðåìÿ êîòèðîâîê Bid/Ask äëÿ äàííîé ôîðìóëû ---------
int GetBidAskMaxTime(int n)
{
int maxtime=0;
for (int f=0; f<ArrayRange(AlgoFunctions,1); f++)
{
int funcindex=AlgoFunctions[n][f];
if (funcindex<0) break;
int functype=FuncParam[funcindex][0];
if (functype!=FUNC_BID && functype!=FUNC_ASK && functype!=FUNC_LAST) continue;
int symindex=FuncParam[funcindex][1];
string symbol=Symbols[symindex];
maxtime=MathMax(maxtime, MarketInfo(GetQuoteSymbol(symbol),MODE_TIME));
}
return(maxtime);
}
*/
//--------------------------------------------------------
int GetBidAskFormula(int baseformulaindex, int& priceindex)
{
int n= baseformulaindex;
int existindex= Algo_BidAskAlgoIndex[n][-priceindex];
if (existindex>0) return(existindex); //{ int maxtime=GetBidAskMaxTime(existindex); priceindex=maxtime; }
if (!AlgoEnabled[n]) return(-1);
static bool getpowratio[100];
if (priceindex==-1 || priceindex==-2)
if (!getpowratio[n])
if (!GetAlgoAllPowAndRatio(n, AlgorithmsTotalPowRatio)) return(-1);
else getpowratio[n]=true;
double algo[ALGORANGE1][ALGORANGE2];
for (int i=0; i<ALGORANGE1; i++)
{
for (int j=0; j<ALGORANGE2; j++) algo[i][j]=Algorithms[n][i][j];
if (i>0) if (Algorithms[n][i-1][CELLNEXTCELL]<=i-1) break;
if (Algorithms[n][i][CELLTYPE]!=TYPE_FUNC) continue;
int funcindex= Algorithms[n][i][CELLVALUE];
if (FuncParam[funcindex][0]!=FUNC_CLOSE) continue;
if (FuncParam[funcindex][2]!=0) continue;
int symindex= FuncParam[funcindex][1];
if (symindex<0) continue;
double totalratio= AlgorithmsTotalPowRatio[n][i][0] * AlgorithmsTotalPowRatio[n][i][1];
int functype=FUNC_BID;
if ((totalratio>0)==(priceindex==-1)) functype=FUNC_ASK;
if (priceindex==-3) functype=FUNC_LAST;
int functotal= ArrayRange(FuncParam,0);
for (int f=0; f<functotal; f++)
if (FuncParam[f][0]==functype && FuncParam[f][1]==symindex) break;
if (f==functotal)
{
ArrayResize(FuncParam,f+1); ArrayResize(FuncCacheMinSize,f+1); //ArrayResize(FuncCopies,f+1);
FuncParam[f][0]=functype; FuncParam[f][1]=symindex;
//FuncCacheMinSize[f]= 0; // GetFunctionMinCacheSize(FuncParam,f);
}
algo[i][CELLVALUE]=f;
}
int new= SaveAlgoArray(algo, i, -1, -1);
Algo_BidAskAlgoIndex[n][-priceindex]= new;
return(new);
}
//----------------------------------------------------------------------------------------------------
bool GetAlgoAllPowAndRatio(int n, double& AlgorithmsTotalPowRatio[][][])
{
double results[2];
bool result= CountMyFormulaValue(n, -3, results);
ArrayInitialize(CachePos,-1);
if (result==false) return(0);
int nlast= Algo_BidAskAlgoIndex[n][3];
double algovalues[ALGORANGE1];
int cellscount= ArrayRange(Algorithms,1);
for (int i=0; i<cellscount; i++)
{
if (i>0) if (Algorithms[n][i-1][CELLNEXTCELL] <= i-1) break;
if (Algorithms[n][i][CELLTYPE]==TYPE_VALUE) { algovalues[i]= Algorithms[n][i][CELLVALUE]; continue; }
int funcindex=Algorithms[nlast][i][CELLVALUE];
if (FuncLastTime[funcindex] <=0) return(0);
algovalues[i]= FuncLastValue[funcindex];
}
if (ArrayRange(AlgorithmsTotalPowRatio,0) <=n) ArrayResize(AlgorithmsTotalPowRatio, n+1);
cellscount=i;
for (i=0; i<cellscount; i++)
{
GetAlgoPositionPowAndRatio(n, i, algovalues, results);
AlgorithmsTotalPowRatio[n][i][0]= results[0];
AlgorithmsTotalPowRatio[n][i][1]= results[1];
}
return(true);
}
//--------------------------------------------------------------------------------------------
bool SaveExistAlgo(int N)
{
bool foundlinks=0;
for (int n=0; n<ArrayRange(Algorithms,0); n++)
if (n!=N)
for (int i=0; ; i++)
{
if (Algorithms[n,i,CELLTYPE]==TYPE_FUNC)
{
int funcindex= Algorithms[n][i][CELLVALUE];
if (FuncParam[funcindex][1] != -N-1) continue; // íå ðàâíî èíäåêñó èñêîìîé ôîðìóëû
FuncParam[funcindex][1]= -ArrayRange(Algorithms,0)-1;
foundlinks=true;
}
if (Algorithms[n,i,CELLNEXTCELL]<=0) break;
}
if (!foundlinks) return(0); // ññûëêè íà ìàññèâ ñ ýòèì èíäåêñîì íå íàéäåíû
ArrayResize(Algorithms,n+1); ArrayCopy0(Algorithms, Algorithms, n, N, 1);
ArrayResize(AlgorithmsTotalPowRatio,n+1); ArrayCopy0(AlgorithmsTotalPowRatio, AlgorithmsTotalPowRatio, n, N, 1);
ArrayResize(SymbolsIndexes,n+1); ArrayCopy0Int(SymbolsIndexes, SymbolsIndexes, n, N, 1);
ArrayResize(SymbolsFuncPos,n+1); ArrayCopy0Int(SymbolsFuncPos, SymbolsFuncPos, n, N, 1);
ArrayResize(CacheStartPos,n+1); CacheStartPos[n]= ArraySize(CacheValueBuffer);
ArrayResize(CachePos,n+1); CachePos[n]= CacheStartPos[n]-1;
ArrayResize(CacheMinSize,n+1); CacheMinSize[n]= CacheMinSize[N];
ArrayResize(AlgoNames,n+1); AlgoNames[n]= AlgoNames[N];
return(true);
}
//------------------------------------------------------------------------------------
int AddFormulaForOwnRates(string formula)
{
MyRatesAllow=true;
double value= AddFormula(formula);
MyRatesAllow=false;
return(value);
}
//------------------------------------------------------------------------------------
bool SetFormula(string formula, int n)
{
return( AddFormula(formula,n)>=0 );
}
//-----------------------------------------------------------------------------------
int AddFormula(string formula, int N=-1, int defaulttf=0, int defaultfunc=FUNC_CLOSE)
{
ErrorString="";
if (DefaultFuncSymCount[FUNC_CLOSE]==0) { InitTime=0; init(); }
int len=StringLen(CURRENT_SYMBOL);
int findpos= StringFind(formula,CURRENT_SYMBOL);
if (findpos==0) formula= Symbol()+StringSubstr(formula,findpos+len); else
if (findpos>0) formula= StringSubstr(formula,0,findpos)+Symbol()+StringSubstr(formula,findpos+len);
double algo[ALGORANGE1][ALGORANGE2];
static int ParentN=-1;
if (N>=0) ParentN=N;
int cellscount= CreateFormulaArray(formula,algo,FuncParam,Symbols,defaulttf,defaultfunc);
if (N==ParentN) ParentN=-1; // çíà÷èò ýòî îñíîâíîé àëãîðèòì
if (cellscount<=0) return(-1);
int n= SaveAlgoArray(algo, cellscount, N, ParentN);
AlgoNames[n]=formula;
return(n);
}
//------------------------------------------------------
int SaveAlgoArray(double algo[][], int cellscount, int N, int ParentN)
{
int n=0;
if (N>=0) n=N;
for (n=n; n<ArrayRange(Algorithms,0); n++) // Èùåì òàêîé æå àëãîðèòì ñðåäè èìåþùèõñÿ àëãîðèòìîâ
{
if (n==ParentN) continue;
for (int i=0; i<=cellscount && i>=0; i++)
for (int j=0; j<ArrayRange(algo,1); j++)
if (Algorithms[n][i][j] != algo[i][j]) { i=-2; break; }
if (i>0) return(n); // ñîâïàäåíèå íàéäåíî, çíà÷èò âîçâðàùàåì èíäåêñ ñóùåñòâóþùåãî àëãîðèòìà
if (N>=0) break;
}
if (n==ParentN) n++; // äî÷åðíèé àëãîðèòì ñîâïàäàåò ñ ðîäèòåëüñêèì
if (N>=0 && !IsIndicator) // åñëè ÿâíî óêàçàí èíäåêñ ñîõðàíÿìîãî àëãîðèòìà, òî ñíà÷àëà ïðîâåðÿåì, ñóùåñòâóþò ëè ñðåäè äðóãèõ àëãîðèòìîâ ññûëêè íà àëãîðèòì ïîä òàêèì èíäåêñîì, è åñëè äà, òî ïåðåìåùàåì ñóùåñòâóþùèé àëãîðèòì â äðóãîå ìåñòî, à ññûëêè êîððåêòèðóåì
if (N<ArrayRange(Algorithms,0)) SaveExistAlgo(N);
if (N<0 && IsIndicator) n= MathMax(n, 10); // èíäåêñ ñîõðàíÿåìîãî àëãîðèòìà íàçíà÷àåì >= 10, ò.ê. ýòî íå îñíîâíîé àëãîðèòì (îñíîâíàÿ ôîðìóëà), à äî÷åðíèé àëãîðèòì
if (ArrayRange(Algorithms,0)<=n) ArrayResize(Algorithms,n+1);
if (ArrayRange(AlgorithmsTotalPowRatio,0)<=n) ArrayResize(AlgorithmsTotalPowRatio,n+1);
if (ArrayRange(AlgoFunctions,0)<=n) ArrayResize(AlgoFunctions,n+1);
if (ArrayRange(SymbolsIndexes,0)<=n) ArrayResize(SymbolsIndexes,n+1);
if (ArrayRange(SymbolsFuncPos,0)<=n) ArrayResize(SymbolsFuncPos,n+1);
if (ArraySize(CachePos)<=n) ArrayResize(CachePos,n+1);
if (ArraySize(CacheStartPos)<=n) ArrayResize(CacheStartPos,n+1);
if (ArraySize(CacheMinSize)<=n) ArrayResize(CacheMinSize,n+1);
if (ArraySize(AlgoNames)<=n) ArrayResize(AlgoNames,n+1);
AlgoRange0= MathMax(AlgoRange0, ArrayRange(Algorithms,0));
Algo_BidAskAlgoIndex[n][1]=-1; Algo_BidAskAlgoIndex[n][2]=-1; Algo_BidAskAlgoIndex[n][3]=-1;
int ss=0;
int nf=-1;
int funccount=0;
for (i=0; i<cellscount; i++)
{
for (j=0; j<ArrayRange(algo,1); j++)
Algorithms[n][i][j]=algo[i][j];
if (algo[i][CELLTYPE]==0) continue;
if (algo[i][CELLTYPE]==TYPE_VALUE) continue;
int funcindex= algo[i][CELLVALUE];
for (int f=0; f<funccount; f++)
if (AlgoFunctions[n][f]==funcindex) break;
AlgoFunctions[n][f]=funcindex;
if (f==funccount) funccount++;
FuncCacheMinSize[funcindex]= GetFunctionMinCacheSize(FuncParam, funcindex);
int functype=FuncParam[funcindex][0];
int symindexcount=DefaultFuncSymCount[functype];
for (int p=1; p<=symindexcount; p++)
{
int symindex= FuncParam[funcindex][p];
if (symindex==EMPTY_VALUE) continue;
if (symindex<0) // èíäåêñ ôîðìóëû
{
nf= -symindex-1;
if (nf>=ArraySize(CacheMinSize)) { ArrayResize(CacheMinSize,nf+1); ArrayResize(CacheStartPos,nf+1); ArrayResize(CachePos,nf+1); }
if (FuncCacheMinSize[funcindex]<0) CacheMinSize[nf]= MathMin(CacheMinSize[nf], FuncCacheMinSize[funcindex]);
else CacheMinSize[nf]= MathMax(CacheMinSize[nf], FuncCacheMinSize[funcindex]);
if (!AlgoEnabled[nf])
if (!IsIndicator) return(-1); else continue;
CacheMinSize[n]= MathMax(CacheMinSize[n], 1);
for (int s1=0; SymbolsIndexes[nf][s1][0] >=0; s1++)
{
for (int s=0; s<ss; s++)
if (SymbolsIndexes[n][s][0]==SymbolsIndexes[nf][s1][0] || s>=ArrayRange(SymbolsIndexes,1)) break;
if (s==ss) { SymbolsIndexes[n][s][0]= SymbolsIndexes[nf][s1][0]; ss++; }
}
continue;
}
else // èíäåêñ ñèìâîëà
for (s=0; s<ss; s++)
if (SymbolsIndexes[n][s][0]==symindex) break;
SymbolsIndexes[n][s][0]=symindex;
if (s==ss) { ss++; SymbolsIndexes[n][s][1]=0; }
int pos=SymbolsIndexes[n][s][1]; //Alert(n," ",s," ",pos," = ",i); //return(0);
SymbolsFuncPos[n][s][pos]=i; // Çàïèñûâàåì ïîçèöèþ äàííîé ôóíêöèè â ìàññèâå [ñèìâîë][ôóíêöèÿ]
SymbolsIndexes[n][s][1]++;
int tf= FuncParam[funcindex][symindexcount+1];
for (int ts=0; ts<ArrayRange(TimeSeries,0); ts++)
if (TimeSeries[ts][0]==symindex && TimeSeries[ts][1]==tf) break;
FuncTimeSerie[funcindex]= ts;
if (ts<ArrayRange(TimeSeries,0)) continue;
ArrayResize(TimeSeries, ts+1);
TimeSeries[ts][0]= symindex;
TimeSeries[ts][1]= tf;
}
}
SymbolsIndexes[n][ss][0]=-1; // óñòàíàâëèâàåì îêîí÷àíèå ìàññèâà èíäåêñîâ
AlgoFunctions[n][funccount]=-1;
//if (nf>=0)
{
int totalsize=0;
for (int m=0; m<ArraySize(CacheMinSize); m++)
{
totalsize+=CacheMinSize[m];
if (CacheMinSize[m]>1) totalsize+=100;
if (CacheMinSize[m]<0) totalsize+=CacheMinSize[m]+1000;
CacheStartPos[m+1]= totalsize; //CacheStartPos[a]+CacheMinSize[a]+100;
CachePos[m]=CacheStartPos[m]-1;
}
ArrayResize(CacheValueBuffer, totalsize);
ArrayResize(CacheTimeBuffer, totalsize);
}
AlgoEnabled[n]=true;
return(n);
}
//-----------------------------------------------------------------------------------
bool GetAlgoPositionPowAndRatio(int n, int i, double algovalues[], double& results[])
{
double pow=1;
double ratio=1;
double log=1;
double values[];
ArrayCopy(values,algovalues);
int mycell=i;
int maxcellscount= ArrayRange(Algorithms,1);
for (int cell=0; cell<maxcellscount; cell++)
{
int nextcell= Algorithms[n][cell][CELLNEXTCELL];
if (nextcell<=cell) break;
double cellvalue= values[cell];
double nextcellvalue= values[nextcell];
int operation= Algorithms[n][cell][CELLOPERATION];
switch (operation)
{
case '-': if (nextcell==mycell) ratio*=-1; else values[nextcell]*=-1; //if (algo[nextcell][CELLTYPE]==TYPE_FUNC) values[nextcell]*=-1;
case '+': if (cell!=mycell && nextcell!=mycell) values[nextcell]+=cellvalue;
break;
case '/': if (nextcell==mycell) pow*=-1; else values[nextcell]= 1/values[nextcell];
case '*': if (cell==mycell) ratio*=nextcellvalue; else
if (nextcell==mycell) ratio*=cellvalue; else values[nextcell]*=cellvalue;
break;
case '^': if (nextcell==mycell) log*=MathLog(cellvalue); else
if (cell==mycell) pow*=nextcellvalue; else
values[nextcell]= MathPow(cellvalue,nextcellvalue); //if (cellvalue<1 && MathMod(nextcellvalue,2)>0)
}
if (cell==mycell) mycell=nextcell;
}
results[0]= pow*log;
results[1]= ratio;
return( results[0]*results[1] );
}
//----- Ñ÷èòûâàíèå ïàðàìåòðîâ ôóíêöèè -------------------------------------------------------------
bool GetFunctionParam(string formula, int& startpos, int templateindex, string& symbols[], int last_sym, int& param[])
{
static int Periods[]={ PERIOD_M1,PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1,PERIOD_W1,PERIOD_MN1 };
static string PeriodNames[]={"M1", "M5", "M15", "M30", "H1", "H4", "D1", "W1", "MN1"};
string paramstr[PARAMCOUNT];
int paramcount=PARAMCOUNT;
int functype= TemplateFuncParam[templateindex][0];
param[0]=functype;
int p=0;
int bracket=0;
int endpos=StringLen(formula);
for (int i=startpos; i<=endpos; i++)
{
int char=StringGetChar(formula,i);
if (char=='(') bracket++;
if (char==')') bracket--;
if (bracket<0) endpos=i;
if (i<endpos)
if (bracket>0 || char!=',') continue;
p++;
if (p==paramcount) break;
int paramlenght= i-startpos;
string paramstring="";
if (paramlenght>0) paramstring= StringTrimLeft(StringTrimRight(StringSubstr(formula, startpos, paramlenght)));
paramstr[p]=paramstring;
startpos=i+1;
}
if (functype==FUNC_RND) { paramcount=0; param[1]=EMPTY_VALUE; }
int symparamcount= DefaultFuncSymCount[functype];
int tfparam=2;
switch (functype) { case FUNC_ABS: case FUNC_LOG: case FUNC_EXP: case FUNC_ROUND: case FUNC_MAX: case FUNC_MIN: tfparam=-1; }
int pp=p;
for (p=paramcount-1; p>=1; p--)
{
paramstring= paramstr[p];
if (p > pp) paramstring="";
param[p]=StrToInteger(paramstring);
if (paramstring!="" && paramstring!="0")
if (p==tfparam || (p==3 && functype==FUNC_MYATR)) // ïàðàìåòð ÿâëÿåòñÿ íàçâàíèåì ïåðèîäà
{
if (DoubleToStr(param[p],0) ==paramstring) // ïàðàìåòð ÿâëÿåòñÿ ÷èñëîì
int n= ArrayBsearch(Periods, param[p]);
else
for (n=ArraySize(PeriodNames)-1; n>=0; n--)
if (paramstring==PeriodNames[n]) { param[p]=Periods[n]; break; }
if (Periods[n]!=param[p]) return(0); // { ErrorString="Wrong timeframe: "+paramstring;
continue;
}
if (functype==FUNC_MAXIMUM || functype==FUNC_MINIMUM)
if (p==5)
if (paramstring=="OPEN") param[p]=MODE_OPEN; else
if (paramstring=="CLOSE") param[p]=MODE_CLOSE; else
if (paramstring=="HIGH") param[p]=MODE_HIGH; else
if (paramstring=="LOW") param[p]=MODE_LOW; else
if (paramstring=="VOLUME") param[p]=MODE_VOLUME;
if (paramstring=="" && p>symparamcount) // åñëè ïàðàìåòð íå çàäàí è ýòîò ïàðàìåòð íå ÿâëÿåòñÿ íàçâàíèåì ñèìâîëà
param[p]= TemplateFuncParam[templateindex][p-1];
if (p>symparamcount) continue; // ïàðàìåòð íå ÿâëÿåòñÿ íàçâàíèåì ñèìâîëà
string symbol=paramstring;
param[p]=0;
switch(functype)
{
case FUNC_ABS: case FUNC_LOG: case FUNC_EXP: case FUNC_ROUND: case FUNC_MAX: case FUNC_MIN:
param[p]=-1;
if (symbol=="") { param[p]=EMPTY_VALUE; continue; }
break;
case FUNC_BANDS: case FUNC_CCI: case FUNC_ENVELOPES: case FUNC_MA: case FUNC_MOMENTUM: case FUNC_STDDEV: case FUNC_RSI:
case FUNC_MAXIMUM: case FUNC_MINIMUM:
if (param[3]<=0) param[1]=-1; // èñïîëüçóåòñÿ ïåðåìåííûé ïåðèîä óñðåäíåíèÿ ôóíêöèé. Ñòàíäàðòíûå ôóíêöèè iMa, iStdDev è ò.ä. â ýòîì ñëó÷àå ðàñc÷èòûâàþòñÿ î÷åíü ìåäëåííî, ïîýòîìó áóäåì èñïîëüçîâàòü ôóíêöèè íà ïîëüçîâàòåëüñêèõ ìàññèâàõ: iMaOnArray, iStdDevOnArray è ò.ä.
}
string mathsign[]= { "+", "-", "*", "/", "^", "(" };
for (int m= ArraySize(mathsign)-1; m>=0; m--)
if (StringFind(symbol,mathsign[m])>=0)
break;
if (m>=0 || functype==FUNC_MYATR || MyRatesAllow) param[p]=-1;
if (param[p]>=0)
if (functype!=FUNC_OPEN && functype!=FUNC_CLOSE && functype!=FUNC_HIGH && functype!=FUNC_LOW && functype!=FUNC_VOLUME)
if (!FindSymbolInSymbolsRow(symbol)) param[p]=-1; // åñëè ñèìâîë íå íàéäåí â ôàéëå symbols.row, çíà÷èò ñòàíäàðòíûå èíäèêàòîðíûå ôóíêöèè èñïîëüçîâàòü íà í¸ì íåëüçÿ, ïîýòîìó ñîçäà¸ì íîâóþ ôîðìóëó ñ ýòèì ñèìâîëîì, ÷òîáû èñïîëüçîâàòü èíäèêàòîðû íà ìàññèâàõ (...OnArray)
if (param[p]<0) // ôîðìóëà
{
static int recurslevel=0;
string oldparamstr[PARAMCOUNT];
int oldparam[PARAMCOUNT];
ArrayCopy(oldparamstr, paramstr, recurslevel*PARAMCOUNT, 0, PARAMCOUNT);
ArrayCopy(oldparam, param, recurslevel*PARAMCOUNT, 0, PARAMCOUNT);
recurslevel++;
int defaulttf= param[2];
int defaultfunc= FUNC_CLOSE;
if (functype==FUNC_VOLUME) defaultfunc=FUNC_VOLUME;
if (functype==FUNC_MAXIMUM || functype==FUNC_MINIMUM)
if (param[5]==MODE_OPEN) defaultfunc=FUNC_OPEN; else
if (param[5]==MODE_VOLUME) defaultfunc=FUNC_VOLUME;
int newformulaindex= AddFormula(symbol, -1, defaulttf, defaultfunc);
recurslevel--;
ArrayCopy (paramstr, oldparamstr, 0, recurslevel*PARAMCOUNT, PARAMCOUNT);
ArrayCopy (param, oldparam, 0, recurslevel*PARAMCOUNT, PARAMCOUNT);
if (newformulaindex<0) { if (ErrorString=="") ErrorString="Failed to create formula "+symbol; return(0); } // "Íå óäàëîñü çàïèñàòü ôîðìóëó "
param[p]= -newformulaindex-1; // çàïèñûâàåì èíäåêñ íîâîé ôóíêöèè âìåñòî èíäåêñà ñèìâîëà
}
if (param[p]>=0 && param[p]!=EMPTY_VALUE) param[p]= SetSymbol(symbol, last_sym);
}
if (functype==FUNC_MYATR)
{
if (param[2]==0) param[2]=Period();
if (param[3]==0) param[3]=Period();
}
startpos= endpos+1;
return(true);
}
//------------------------------------------------------
bool FindSymbolInSymbolsRow(string symbol)
{
MarketInfo(symbol,MODE_TIME);
if (GetLastError()!=4106) return(true);
static string symbols[];
static int inittime;
if (InitTime!=inittime)
{
int h=FileOpenHistory("symbols.raw",FILE_BIN|FILE_READ);
if (h<0) { Print("Íå óäàëîñü îòêðûòü ôàéë symbols.raw"); return(0); }
int arraysize=FileSize(h)/1936;
ArrayResize(symbols,arraysize);
string txt="";
for (int n=0; n<arraysize; n++)
{
if (!FileSeek(h,n*1936,SEEK_SET)) { symbols[n]=""; break; }
symbols[n]=FileReadString(h,12); // òèêåð
}
Print("Ñ÷èòàíî ",n," êîíòðàêòîâ èç ôàéëà symbols.raw");
FileClose(h);
inittime=InitTime;
}
for (int i=ArraySize(symbols)-1; i>=0; i--)
if (symbols[i]==symbol) break;
if (i<0) return(0);
return(true);
}
//-----------------------------------------
int SetSymbol(string symbol, int& last_sym)
{
if (symbol=="0") symbol=Symbol();
if (symbol=="")
if (last_sym>=0) symbol=Symbols[last_sym]; else symbol=Symbol();
// Ïðîâåðÿåì, ÿâëÿåòñÿ ëè íàçâàíèå ñèìâîëà ññûëêîé íà äðóãóþ ôîðìóëó
string upcasesymbol= StringUpperCase(symbol);
int finddigitpos=10000;
if (StringFind(upcasesymbol,"FORMULA")==0) finddigitpos=7; else if (StringFind(upcasesymbol,"F")==0) finddigitpos=1;
for (int d=finddigitpos; d<StringLen(symbol); d++)
if (StringGetChar(symbol,d)<'0' || StringGetChar(symbol,d)>'9') break;
if (d==StringLen(symbol) && d>1)
{
int formulaindex= StrToInteger(StringSubstr(symbol,finddigitpos));
int index= -formulaindex-1;
IsFormulaUsing[formulaindex]= true;
return(index);
}
for (int s=0; s<ArraySize(Symbols); s++)
if (Symbols[s]==symbol) break;
if (s==ArraySize(Symbols)) ArrayResize(Symbols,s+1);
Symbols[s]=symbol;
last_sym= s; // çàïîìèíàåì èíäåêñ ïîñëåäíåãî ñèìâîëà
return(s);
}
//--------------------------------------------------------
int CreateFormulaArray(string Formula,double& Algo[][],double& AllFuncParam[][],string& AllSymbols[],int defaultTF,int defaultFunc)
{
Formula= StringTrimLeft(StringTrimRight(Formula));
if (StringSubstr(Formula,0,1)=="'") Formula=StringSubstr(Formula,1);
int strlen= StringLen(Formula);
bool symbolfound=0;
bool digitfound=0;
int last_sym= -1;
int funccount= ArrayRange(AllFuncParam,0);
if (funccount==0) ArrayResize(AllSymbols,0);
int startlevel=0;
int maxlevel=0;
int signchar=0;
int member=0;
static int recurslevel=0;
#define ARRAYRANGE1 6
double Array[20][ARRAYRANGE1]; // [member][param]
ArrayInitialize(Array,0);
#define CELLLEVEL 4
#define CELLPARENTLEVEL 5
int lastlevel=-1;
int LevelInvert[100];
int startpos=0;
int squarebracket=0;
for (int i=0; startpos <= strlen; i++)
{
int char=StringGetChar(Formula,i);
if (char=='[') { squarebracket++; symbolfound=true; }
if (char==']') squarebracket--;
if (squarebracket>0 && i<strlen) continue;
if ((char>='0' && char<='9') || char=='.')
{
if (!symbolfound) digitfound=true;
continue;
}
if (char==' ' && !symbolfound) { if (i==startpos) startpos++; continue; }
if (char=='+' || char=='-' || char=='*' || char=='/' || char=='^')
{
if (!symbolfound && !digitfound) signchar=char;
if (i==startpos) { startpos++; continue; }
}
else
if (char!='(' && char!=')' && i<strlen)
{ symbolfound=true; digitfound=false; continue; }
int operand;
string charstr=CharToStr(signchar);
if (StringFind("+-)",charstr)>=0) operand=SUMMAND; else
if (StringFind("*/",charstr)>=0) operand=MULTIPLIER; else
if (StringFind("^",charstr)>=0) operand=POW;
int level= startlevel+operand;
if (level < Array[member-1][CELLLEVEL])// lastlevel)
for (int lev=Array[member-1][CELLLEVEL]; lev>level || (lev==level && startpos==strlen); lev--) //
{
Array[member][CELLLEVEL]= lev;
Array[member][CELLTYPE]=TYPE_VALUE;
if (lev%3==SUMMAND) Array[member][CELLVALUE]=0; else Array[member][CELLVALUE]=1;
int plev= lev-1;
if (LevelInvert[plev]==true) { Array[member][CELLVALUE]=-1; LevelInvert[plev]=false; } // if (Array[member][CELLPARENTLEVEL]=plev; }Alert("inv ",member," ",Array[member][CELLLEVEL]); Array[member][CELLVALUE]=-1; LevelInvert[lev-1]=false; Array[member][CELLLEVEL]=lev; }
//if (lev%3==SUMMAND && lev>level) plev=MathMax(level,lastlevel);
Array[member][CELLPARENTLEVEL]= plev;
member++;
}
if (lastlevel>=0 && member>0) lastlevel= Array[member-1][CELLLEVEL];
else lastlevel= level;
if (level>lastlevel && lastlevel>=0)
{ Array[member-1][CELLLEVEL]= level; Array[member-1][CELLPARENTLEVEL]= level; } //Alert(member-1," ",lastlevel," ",level);
if (signchar=='-') { operand=MULTIPLIER; LevelInvert[level]=true; }
if (signchar=='/') { operand=POW; LevelInvert[level]=true; }
level= startlevel+operand;
Array[member][CELLTYPE]=TYPE_VALUE;
if (operand==SUMMAND) Array[member][CELLVALUE]=0; else Array[member][CELLVALUE]=1;
Array[member][CELLLEVEL]= level; //startlevel+operand;
Array[member][CELLPARENTLEVEL]= level; //startlevel+operand;
if (digitfound)
Array[member][CELLVALUE]= StrToDouble(StringSubstr(Formula,startpos,i-startpos));
if (symbolfound)
{
string name= StringTrimLeft(StringTrimRight(StringSubstr(Formula, startpos, i-startpos)));
if (StringGetChar(Formula, startpos)=='[')
{
name= StringSubstr(name, 1); //startpos++;
if (StringGetChar(Formula, i-1)==']') name= StringSubstr(name, 0, StringLen(name)-1);
}
int param[PARAMCOUNT]; ArrayInitialize(param,0);
if (char!='(') // ýòî íå èìÿ ôóíêöèè, çíà÷èò ýòî íàçâàíèå ñèìâîëà
{
param[0]= defaultFunc;
param[1]= SetSymbol(name, last_sym);
param[2]= defaultTF;
}
else // èìÿ ôóíêöèè
{
i++;
int tempcount= ArraySize(TemplateFuncName);
for (int t=0; t<tempcount; t++)
if (StringLen(TemplateFuncName[t])==0) t=tempcount;
else if (StringUpperCase(TemplateFuncName[t])==StringUpperCase(name)) break;
if (t>=tempcount) { ErrorString="Unknown function: "+name+"(...)"; break; } // "Íåèçâåñòíàÿ ôóíêöèÿ: "
recurslevel++;
ArrayCopy0 (Array, Array, recurslevel*100, 0, 100); // áýêàïèì èñõîäíûå ìàññèâû, ò.ê. îíè ìîãóò áûòü çàìåíåíû â õîäå ðåêóðñèè
ArrayCopy(LevelInvert, LevelInvert, recurslevel*100, 0, 100);
bool result= GetFunctionParam(StringUpperCase(Formula), i, t, AllSymbols, last_sym, param);
ArrayCopy0 (Array, Array, 0, recurslevel*100, 100); // âîññòàíàâëèâàåì èñõîäíûå ìàññèâû
ArrayCopy(LevelInvert, LevelInvert, 0, recurslevel*100, 100);
recurslevel--;
if (result==false) { ErrorString="Wrong parameter of function "+name+"()"; break; } // "Íåâåðíûé ïàðàìåòð ôóíêöèè "
}
// Èùåì òàêóþ æå ôóíêöèþ ñ òàêèìè æå ïàðàìåòðàìè â îáùåì ìàññèâå ôóíêöèé
int functotal=ArrayRange(AllFuncParam,0);
for (int f=0; f<functotal; f++)
{
for (int p=0; p<PARAMCOUNT; p++)
if (AllFuncParam[f][p]!=param[p]) break;
if (p==PARAMCOUNT) break; // âñå ïàðàìåòðû ñîâïàäàþò, çíà÷èò ïðåêðàùàåì ïîèñê
}
if (f==functotal)
{
ArrayResize(AllFuncParam, f+1);
ArrayResize(FuncCacheMinSize, f+1);
ArrayResize(FuncTimeSerie, f+1);
for (p=0; p<PARAMCOUNT; p++) AllFuncParam[f][p]=param[p]; // íå íàéäåíî ôóíêöèé ñ ñîâïàäàþùèìè ïàðàìåòðàìè, çíà÷èò äîáàâëÿåì ôóíêöèþ â ìàññèâ
}
Array[member][CELLVALUE]= f;
Array[member][CELLTYPE]= TYPE_FUNC;
}
maxlevel= MathMax(maxlevel, Array[member][CELLLEVEL]);
if (char=='(' && !symbolfound) // ïåðåä ñêîáêîé íå áûëî ñèìâîëîâ, çíà÷èò ýòî íå ôóíêöèÿ
{
startlevel+=3;
lastlevel=-1;
i++;
}
if (char==')')
{
startlevel-=3;
for (int m=member-1; m>=0; m--) if (MathFloor(Array[m][CELLLEVEL]/3)*3==startlevel) break;
lastlevel= Array[m][CELLLEVEL];
i++;
}
if (symbolfound || digitfound || char==')' || member==0)
member++;
if (startlevel<0) ErrorString="')' - Unbalanced right bracket!"; //"Ëèøíÿÿ çàêðûâàþùàÿ ñêîáêà!";
if (ErrorString!="") break;
startpos=i;
if (i<strlen) i--;
symbolfound=false;
digitfound=false;
squarebracket=0;
signchar=0;
}
if (ErrorString!="") { if (recurslevel==0) Print(Formula," : ",ErrorString); return(0); } // Alert(Symbol()+" "+WindowExpertName()+": ",ErrorString);
member--;
FormulaArrayOptimization(Array, member, maxlevel);
string sourcestring= GetSourceAlgoString(Array, member, maxlevel);
if (Debug)
Alert(Formula, "\n\n", sourcestring);
double array[][ARRAYRANGE1];
ArrayCopy(array, Array, 0, CELLPARENTLEVEL); // êîïèðóåì ìàññèâ, ñäâèãàÿ çíà÷åíèÿ ñóáèíäåêñà CELLPARENTLEVEL íà íóëåâîé ñóáèíäåêñ
int posmemb[100];
//string txt="";
for (m=0; m<=member; m++) { posmemb[m]= ArrayMaximum(array,member+1); array[posmemb[m],0]=-2; } //txt=txt+posmemb[m]+" ";}
int sign[3][2]={ '+', '-', '*', '/', '^', '?'};
int InvertedLevels[100]; ArrayInitialize(InvertedLevels, 1<<30);
//Alert(txt);
for (int pos=0; pos<=member; pos++)
{
int memb= posmemb[pos];
level= Array[memb][CELLLEVEL];
int plevel= Array[memb][CELLPARENTLEVEL];
int nextpos= -1;
for (p=pos+1; p<=member; p++)
if (posmemb[p]>memb && Array[posmemb[p]][CELLPARENTLEVEL]<=plevel)
if (posmemb[p]<posmemb[nextpos] || nextpos<0) nextpos=p;
int nextmemb= posmemb[nextpos];
if (Array[nextmemb][CELLVALUE]==-1 && Array[nextmemb][CELLTYPE]==TYPE_VALUE && Array[nextmemb][CELLLEVEL]==plevel+1)
if (plevel%3!=POW)// && Array[nextmemb-1][CELLPARENTLEVEL]==Array[nextmemb][CELLLEVEL])
{ // èíâåðòèðóåì ÿ÷åéêó (óìíîæåíèå ïîòîì áóäåò çàìåíåíî íà äåëåíèå, à ñëîæåíèå íà âû÷èòàíèå)
for (p=0; p<nextpos; p++) if (Algo[p][CELLNEXTCELL]==nextpos) break;// if (Array[posmemb[[p]][CELLPARENTLEVEL]<=; for (p=0; p<nextpos; p++) if (posmemb[p]==nextmemb-1) break;
if (Array[posmemb[p]][CELLPARENTLEVEL]==Array[nextmemb][CELLLEVEL])
{
Array[posmemb[p]][CELLPARENTLEVEL]= Array[nextmemb][CELLPARENTLEVEL];
InvertedLevels[posmemb[p]] |= 1<<plevel;
posmemb[nextpos]=posmemb[p];
ArrayCopy(posmemb, posmemb, p, p+1); //InvertedLevels[p-1]= plevel;
member--; pos=-1;
continue;
}
}
Algo[pos][CELLNEXTCELL]= nextpos;
Algo[pos][CELLVALUE]= Array[memb][CELLVALUE];
Algo[pos][CELLTYPE]= Array[memb][CELLTYPE];
bool nextmembinvert= (InvertedLevels[nextmemb] & (1<<plevel)) > 0; // && Array[nextmemb][CELLLEVEL]==plevel+1; //level+1;
Algo[pos][CELLOPERATION]= sign[plevel%3][nextmembinvert*1];
}
Algo[member][CELLNEXTCELL]= 0;
int algolen= member+1;
if (Debug)
Alert(Formula, "\n\n", sourcestring, GetResultAlgoString(Algo, algolen));
if (ErrorString!="") algolen=0;
return(algolen);
}
//-------------------------------------------------------------------
//int DblToInt(double value) { return(value); }
//--------------------------------------------------------------------------
bool FormulaArrayOptimization(double& Array[][], int& member, int& maxlevel)
{
double temparray[][ARRAYRANGE1];
bool memb0positive;
int membsize=0;
int memb0size=0;
int membcount=0;
int lastvaluememb;
for (int level=maxlevel; level>=0; level--)
{
int leveltype= level%3;
int memb0=-1;
for (int memb=0; memb<=member; memb++)
{
int lev= Array[memb][CELLLEVEL];
int plev= Array[memb][CELLPARENTLEVEL];
if (memb0==-1) { membsize=0; membcount=0; memb0=-2; }
if (lev<level) { membsize=0; continue; }
if (lev==level) membsize=1; else
if (memb>0 && Array[memb-1][CELLPARENTLEVEL]==level) membsize=1; else
if (lev>level) membsize++;
//if (plev>=level) membsize++;
if (lev>level && plev>level) continue;
if (memb==member) plev=-1;
membcount++;
int celltype= Array[memb][CELLTYPE]; //int level= Array[memb][CELLLEVEL];
double membvalue= Array[memb][CELLVALUE];
if (memb0<0)
{
memb0=memb;
memb0size=membsize;
memb0positive=false;
int funcindex=membvalue;
if (leveltype==POW && lev==level) //memb0size==1)
if ((celltype==TYPE_VALUE && membvalue>=0) || (celltype==TYPE_FUNC && FuncParam[funcindex][1]>=0))
memb0positive=true; // îñíîâàíèåì ñòåïåíè ÿâëÿåòñÿ åäèíè÷íûé ÷ëåí, ïðåäñòàâëÿþùèé ñîáîé ïîëîæèòåëüíîå ÷èñëî ëèáî èíäåêñ ñèìâîëà
bool basepositive=memb0positive;
lastvaluememb=-1;
}
//if (memb==1) Alert("memb: ",memb," value: ",membvalue," type: ",celltype," level: ",level," plev: ",plev," invert: ",Array[1][CELLINVERT]," memb0: ",memb0," count: ",membcount);
/*
if (membsize>1 && Array[memb-membsize][CELLLEVEL]==level && memb!=memb0) // åñëè òåêóùèé ÷ëåí ÿâëÿåòñÿ ñîñòàâíûì (äëèíà áîëüøå 1), à ïðîøëûé ÷ëåí áûë åäèíè÷íûì, òî ìåíÿåì èõ ìåñòàìè
if (membcount>2 || leveltype!=POW)
{
ArrayCopy0(temparray, Array, 0, memb-membsize, 1); // ñîõðàíÿåì ïðåäûäóùèé ÷ëåí
ArrayCopy0(Array, Array, memb-membsize, memb-membsize+1, membsize); // êîïèðóåì òåêóùèé ÷ëåí íà ìåñòî ïðåäûäóùåãî
ArrayCopy0(Array, temparray, memb, 0, 1); // ïîìåùàåì ïðåäûäóùèé ÷ëåí âñëåä çà òåêóùèì
//Alert("!! ",level," ",memb," ",membsize," ",membcount," ",Array[memb0][CELLPARENTLEVEL]);
level=maxlevel+1; level=-1; break;
}
*/
if (lev>level) continue;
if (celltype==TYPE_VALUE)
{
double resultvalue= Array[lastvaluememb][CELLVALUE];
if (lastvaluememb<0) { resultvalue=membvalue; lastvaluememb=memb; }//if (leveltype==SUMMAND) resultvalue=0; else resultvalue=1;
else
switch (leveltype)
{
case SUMMAND: resultvalue+=membvalue; break;
case MULTIPLIER: resultvalue*=membvalue; break; // || memb>memb0
case POW:
if (lastvaluememb==memb0)
if (basepositive || MathMod(membvalue,2)==1 || memb==memb0+1)
{
if (resultvalue==0 && membvalue<0) { ErrorString="Zero divide!"; continue; }
if (resultvalue<0 && MathMod(membvalue,1)>0) { ErrorString="Exponentiation error!"; continue; }
resultvalue= MathPow(resultvalue, membvalue);
if (MathMod(membvalue,2)==0) { basepositive=true; memb0positive=true; }
}
else lastvaluememb=-1;
else
{
if ((MathMod(resultvalue,2)==0 && MathMod(membvalue,1)==0)
|| (MathMod(resultvalue,1)>0 && MathMod(membvalue,1)>0) || (MathMod(resultvalue,2)==1 && lastvaluememb==memb-1)
|| MathMod(membvalue,2)==1 || basepositive)
resultvalue*=membvalue;
else lastvaluememb=-1;
if (MathMod(resultvalue,2)==0) basepositive=true;
}
if (lastvaluememb<0) { lastvaluememb=memb; resultvalue=membvalue; }
}
Array[lastvaluememb][CELLVALUE]=resultvalue;
bool delete= (lastvaluememb!=memb);
if (delete) if (leveltype==SUMMAND) Array[memb][CELLVALUE]=0; else Array[memb][CELLVALUE]=1;
membvalue=Array[memb][CELLVALUE];
if (membvalue==0 && leveltype==SUMMAND) delete=true;
if (membvalue==1 && leveltype!=SUMMAND) if (leveltype==MULTIPLIER || memb>memb0) delete=true;
//if (memb==member) Alert("memb: ",memb," value: ",membvalue," level: ",level," plev: ",plev," count: ",membcount);
if (delete)
if (memb>memb0 || (level==0 && member>1))// && Array[memb-1][CELLLEVEL]==level) || plev==level || (plev<level && memb==memb0) || membcount==2)
{
if (plev<level && memb>memb0) { Array[memb-1][CELLPARENTLEVEL]=plev; } // åñëè ýòî êîíå÷íàÿ ÿ÷åéêà, òî ìåíÿåì ðîäèòåëüñêèé óðîâåíü ó ïðåäûäóùåé ÿ÷åéêè
ArrayCopy0(Array, Array, memb-membsize+1, memb+1); // óäàëÿåì äàííóþ ÷èñëîâóþ ÿ÷åéêó èç ìàññèâà
member--; membcount--; membsize=0; memb--;//memb0=-1;//continue;
if (plev<level || memb<memb0) { memb=memb0-memb0size; memb0=-1; }
continue;
}
}
if (plev>=level) continue;
/*
if (leveltype==POW)
if (Array[memb0][CELLLEVEL]==level && Array[memb0][CELLTYPE]==TYPE_FUNC && Array[memb0][CELLVALUE]==1)
{ memb=memb0-memb0size-1; ArrayCopy0(Array, Array, memb, memb+1);
*/
//if (plev<level)
if (membcount>2 && memb0positive && leveltype==POW)// && Array[memb][CELLLEVEL]==level) // åñëè îñíîâàíèå ñòåïåíè ïîëîæèòåëüíîå, òî ïðåîáðàçóåì ïîêàçàòåëè â ìíîæèòåëè (ïîìåùàÿ èõ â ñêîáêè)
{
int startmemb=memb;
if (membvalue==-1 && celltype==TYPE_VALUE && lev==level) if (membcount>3) startmemb--; else startmemb=0;
for (int i=startmemb; i>=memb0+1; i--)
{
if (Array[i][CELLLEVEL]==level) Array[i][CELLLEVEL]+=2; else Array[i][CELLLEVEL]+=3;
if (Array[i][CELLPARENTLEVEL]>=level && i<startmemb)
if (Array[i][CELLPARENTLEVEL]==level) Array[i][CELLPARENTLEVEL]+=2; else Array[i][CELLPARENTLEVEL]+=3;
maxlevel= MathMax(Array[i][CELLLEVEL], maxlevel);
}
if (i<startmemb) { memb=memb0-memb0size; memb0=-1; continue; }
}
if (true)
if (membcount==1 && membsize==1 && plev>=0) // åñëè èìååòñÿ âñåãî îäèí ÷ëåí íà ýòîì óðîâíå, òî ïåðåìåùàåì åãî íà ðîäèòåëüñêèé óðîâåíü
{
Array[memb][CELLLEVEL]= plev;
Array[memb][CELLPARENTLEVEL]= plev;
}
memb0=-1;
}
}
return(true);
}
//--------------------------------------------------------------------
string GetSourceAlgoString(double Array[][], int member, int maxlevel)
{
string txt="";
for (int y=0; y<=maxlevel; y++)
{
txt= txt+y+"\t";
for (int x=0; x<=member; x++)
if (Array[x,CELLLEVEL]==y)
{
string valuestr=StringConcatenate(Array[x,CELLVALUE],"");
if (Array[x,CELLTYPE]==TYPE_FUNC) valuestr="f"+valuestr;
//if (Array[x,CELLINVERTLEVEL]==true) if (y%3==SUMMAND) valuestr="-"+valuestr; else valuestr="/"+valuestr;
txt=StringConcatenate(txt, StrFmt(valuestr,3.5)," ", StrFmt(StringConcatenate(Array[x,CELLPARENTLEVEL],""),3.5), "\t"); //," ",Array[x,y,CELLMAINCELL],"\t");
}
else txt=txt+"---- "+"---- "+"\t";
txt=txt+"\n";
}
txt=txt+"\n";
return(txt);
}
//-------------------------------------
string StrFmt(string str, double len)
{
string spaces=" ";
str= str+ StringSubstr( spaces, StringLen(spaces)-MathRound((len-StringLen(str))*2), 0);
return(str);
}
//----------------------------------------- ------------
string GetResultAlgoString(double Algo[][], int algolen)
{
string CellParamNames[4];
CellParamNames[CELLVALUE]="Value";
CellParamNames[CELLTYPE]="Type";
CellParamNames[CELLOPERATION]="Action";
CellParamNames[CELLNEXTCELL]="ToCell";
bool symbolsrow=false;
string txt="";
for (int y=-1; y<ArraySize(CellParamNames); y++)
{
if (y==-1) txt= txt+ "Cell\t";
else if (symbolsrow) txt= txt+ "\t";
else txt= txt+ CellParamNames[y]+ "\t";
for (int x=0; x<algolen; x++)
{
if (y==-1) { txt= txt+ x+ "\t"; continue; }
string valstr= StringConcatenate(Algo[x][y], "");
if (symbolsrow) valstr="";
if (Algo[x][CELLTYPE]==TYPE_FUNC)
{
int valueindex= Algo[x][CELLVALUE];
int symindex= FuncParam[valueindex][1];
if (y==CELLTYPE) valstr= StringConcatenate("Func ", FuncParam[valueindex][0]);
else if (y==CELLVALUE) valstr= "f" +valueindex;
if (symbolsrow) if (symindex>=0) valstr= "."+Symbols[symindex]; else valstr= "(F"+ (-symindex-1)+ ")";
}
else if (y==CELLTYPE) valstr="Value";
if (y==CELLOPERATION) valstr= CharToStr(Algo[x][y]);
txt= StringConcatenate(txt, valstr, "\t");
}
txt= txt+ "\n";
if (symbolsrow) { symbolsrow=false; continue; }
if (y==CELLVALUE) { symbolsrow=true; y--; }
}
return(txt);
}
//------------------------------------------------------------
string StringUpperCase(string text)
{
for (int i=0; i<StringLen(text); i++)
{
int char=StringGetChar(text,i);
if (char>='a' && char<='z') { text= StringSetChar(text, i, char+'A'-'a'); }
}
return(text);
}
//-----------------------------------------------------------------------------------
int ArrayCopy0(double& array1[], double& array2[], int start1=0, int start2=0, int count=0)
{
int range=1;
for (int i=ArrayDimension(array1)-1; i>0; i--) range*=ArrayRange(array1,i);
return( ArrayCopy(array1, array2, start1*range, start2*range, count*range) / range);
}
//--------------------------------------------------------------------------------------
int ArrayCopy0Int(int& array1[], int& array2[], int start1=0, int start2=0, int count=0)
{
int range=1;
for (int i=ArrayDimension(array1)-1; i>0; i--) range*=ArrayRange(array1,i);
return( ArrayCopy(array1, array2, start1*range, start2*range, count*range) / range);
}
//--------------------------------------------------------------------------------------
string GetQuoteSymbol(string symbol)
{
//if (StringFind(AccountCompany(),"BroCo")>=0)
{
int marginmode=MarketInfo(symbol,MODE_MARGINCALCMODE);
if (marginmode==1 || marginmode==2) // CFD ëèáî ôüþ÷åðñ
if (StringFind(symbol,"_CONT")<0 && StringFind(symbol,"#I")!=StringLen(symbol)-2)
{
string quotesymbol=symbol+"#I";
MarketInfo(quotesymbol,MODE_TIME);
if (GetLastError()!=4106) symbol=quotesymbol;
}
}
return(symbol);
}
//----------------------------------------------
string GetPeriodName(int period)
{
int periods[]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1 };
string names[]= { "M1", "M5", "M15", "M30", "H1", "H4", "D1", "W1", "MN" };
int findindex= ArrayBsearch(periods,period);
if (periods[findindex]==period) return(names[findindex]);
return("M"+period);
}
//--------------------------------------------------------------------------
void DrawLine(int window, string object, double price, string text, int clr)
{
if (window<0) return;
int foundwindow=ObjectFind(object);
if (foundwindow==-1)
{
if (!ObjectCreate(object,OBJ_HLINE,window,TimeCurrent(),price))
if (GetLastError()==4051) { WrongWindow=true; return; }
ObjectSet(object,OBJPROP_STYLE,STYLE_DOT);
ObjectSet(object,OBJPROP_COLOR,clr);
ObjectSetText(object,text);
return;
}
else if (foundwindow!=window) return;
ObjectMove(object,0,TimeCurrent(),price);
}
//--------------------------------------
bool DrawLabel(string name, int x, int y, int corner, string text, int fontsize, string font, int clr)
{
int wnd=ObjectFind(name);
if (wnd!=Window || ObjectType(name)!=OBJ_LABEL)
{ ObjectDelete(name); wnd=-1; }
if (wnd<0) if (!ObjectCreate(name,OBJ_LABEL,Window,0,0)) return(0);
ObjectSet(name,OBJPROP_XDISTANCE,x);
ObjectSet(name,OBJPROP_YDISTANCE,y);
ObjectSetText(name,text,fontsize,font,clr);
ObjectSet(name,OBJPROP_CORNER,corner);
return(true);
}
//----------------------------------------------------------------------
void DrawStatusLabel(string text, int clr=White)
{
int corner=0;
int y=56;
if (LabelsOnTheRight) { corner=1; y=40; }
if (!DrawLabel(StatusLabel, 5, y, corner, text, 7, "Arial", clr))
if (GetLastError()==4051) { WrongWindow=true; Print("Wrong window"); }
}
//---------------------------------------------------------
bool BoolChartLabels[8];
void DrawChartLabel(int n, string text)
{
if (Window<0) return(0);
int corner=0;
int x1=5;
int y=16;
if (LabelsOnTheRight) { corner=1; y=2; }
for (int i=0; i<n; i++) if (BoolChartLabels[i]==true) y+=14;
if (n==8)
{ DrawLabel(SignalLabel, x1, y, corner, text, 8, "Courier", Red); return; }
BoolChartLabels[n]=true;
int len=StringLen(text);
if (len>63)
{
int x2= x1+63*8;
if (LabelsOnTheRight) { x2=x1; x1+= (len-63)*8; }
DrawLabel(ChartLabels_[n], x2, y, corner, StringSubstr(text,63), 8, "Courier", Colors[n]);
}
if (!DrawLabel(ChartLabels[n], x1, y, corner, text, 8, "Courier", Colors[n]))
if (GetLastError()==4051) { WrongWindow=true; Print("Wrong window"); }
}
//---------------------------------------------------------------
void DrawErrorChartLabel(int n, string text)
{
if (Window<0) return;
string object=ChartErrorLabels[n];
if (text=="") { ObjectDelete(object); return; }
int corner=0;
int x= 5 + (StringLen(Formulas[n])+2) * 8;
int y= 16;
if (LabelsOnTheRight) { corner=1; y=2; }
for (int i=0; i<n; i++) if (BoolChartLabels[i]==true) y+=14;
BoolChartLabels[n]=true;
if (!DrawLabel(object, x, y, corner, text, 8, "Arial", Red))
if (GetLastError()==4051) { WrongWindow=true; Print("Wrong window"); }
}
//---------------------------------------------
bool FindWordInString(string text, string word)
{
int textlen=StringLen(text);
int wordlen=StringLen(word);
for (int pos=0; ; pos++)
{
pos=StringFind(text,word,pos);
if (pos<0) break;
int prevchar=StringGetChar(text,pos-1);
int postchar=StringGetChar(text,pos+wordlen);
if (pos>0) if (prevchar!=' ' && prevchar!=',') continue;
if (pos<textlen-wordlen) if (postchar!=' ' && postchar!=',') continue;
return(true);
}
return(0);
}
//---------------------------------------------------------------------------
bool CheckSignalLevels(int chart, double bid, double ask)
{
static int AlertTime[MAXCHARTS][4];
string SignalLines[4]={"",""};
double SignalValue[4];
int SignalType[4]= {-1,-1,-1,-1};
if (Signal_HighValue!="") { SignalValue[0]= StrToDouble(Signal_HighValue); SignalType[0]=MODE_HIGH; }
if (Signal_LowValue!="") { SignalValue[1]= StrToDouble(Signal_LowValue); SignalType[1]=MODE_LOW; }
if (Signal_HighLine!="") { SignalLines[2]= Signal_HighLine; SignalType[2]=MODE_HIGH; }
if (Signal_LowLine!="") { SignalLines[3]= Signal_LowLine; SignalType[3]=MODE_LOW; }
int digits=IndDigits;
bid= NormalizeDouble(bid,digits);
ask= NormalizeDouble(ask,digits);
bool signal=false;
for (int i=0; i<4; i++)
{
if (SignalType[i]<0) continue;
if (TimeLocal()-AlertTime[chart][i] < 5) continue;
double signalvalue= NormalizeDouble(SignalValue[i],digits);
string object=SignalLines[i];
if (object!="")
{
if (ObjectFind(object)!=Window) continue;
string modetext="High"; if (SignalType[i]==MODE_LOW) modetext="Low";
ObjectSetText(object, "Signal Line "+modetext);
if (ObjectType(object)==OBJ_HLINE)
signalvalue= ObjectGet(object,OBJPROP_PRICE1);
else signalvalue= ObjectGetValueByShift(object,0);
if (GetLastError()==4205) continue; // îøèáêà êîîðäèíàò îáúåêòà
}
string txt="";
string BidStr="Bid ", AskStr="Ask ";
if (!ShowBidAsk) { BidStr=""; AskStr=""; }
if (SignalType[i]==MODE_HIGH)
if (bid!=EMPTY_VALUE && bid>=signalvalue)
txt= StringConcatenate(Formulas[chart],": ",BidStr,DoubleToStr(bid,digits)," >= ",DoubleToStr(signalvalue,digits));
if (SignalType[i]==MODE_LOW)
if (ask!=EMPTY_VALUE && ask<=signalvalue)
txt= StringConcatenate(Formulas[chart],": ",AskStr,DoubleToStr(ask,digits)," <= ",DoubleToStr(signalvalue,digits));
if (txt=="") continue;
if (object!="") txt= txt+" ("+object+")";
static int lastinittime=0;
if (InitTime!=lastinittime) { ArrayInitialize(AlertTime,0); lastinittime=InitTime; }
if (AlertTime[chart][i]==0) Alert(txt); else Print(txt);
AlertTime[chart][i]= TimeLocal();
signal=true;
}
if (signal) PlaySound("alert2.wav");
return(signal);
}
//----------------------------------------------------------------------------------
int GetFormulaSymbols(int n, string& symbols[])
{
for(int s=0; s<ArrayRange(SymbolsIndexes,1); s++)
{
int symindex= SymbolsIndexes[n][s][0];
if (symindex<0) break;
symbols[s]= Symbols[symindex];
}
return(s);
}
//-------------------------------------------------
int GetFormulaSymIndexes(int n, int& indexes[])
{
for(int s=0; s<ArrayRange(SymbolsIndexes,1); s++)
{
int symindex= SymbolsIndexes[n][s][0];
if (symindex<0) break;
indexes[s]= symindex;
}
return(s);
}
//------------------------------------------------
int GetAllFormulasSymbols(string& symbols[])
{
ArrayCopy(symbols, Symbols);
return( ArraySize(Symbols) );
}
//--------------------------------------------------------------
int GetFormulaSymFuncNames(int n, int s, string& funcnames[])
{
if (SymbolsIndexes[n][s][0]<0) return(0);
int pp= SymbolsIndexes[n][s][1]; // îáùåå êîëè÷åñòâî ïîÿâëåíèé äåííîãî ñèìâîëà â ôîðìóëå
ArrayResize(funcnames, MathMax(ArrayRange(funcnames,0),pp));
for (int p=0; p<pp; p++)
{
int pos= SymbolsFuncPos[n][s][p];
int funcindex= Algorithms[n][pos][CELLVALUE];
int functype= FuncParam[funcindex][0]; //if (functype!=FUNC_CLOSE && functype!=FUNC_OPEN && functype!=FUNC_HIGH && functype!=FUNC_LOW) continue;
funcnames[p]= DefaultFuncName[functype];
}
return(pp);
}
//-----------------------------------------------------------------------------------------------------
int GetFormulaSymPowRatio(int n, int s, double& totalpowratio[][2])
{
if (!GetAlgoAllPowAndRatio(n, AlgorithmsTotalPowRatio)) return(0);
if (SymbolsIndexes[n][s][0]<0) return(0);
int pp= SymbolsIndexes[n][s][1]; // îáùåå êîëè÷åñòâî ïîÿâëåíèé äåííîãî ñèìâîëà â ôîðìóëå
ArrayResize(totalpowratio, MathMax(ArrayRange(totalpowratio,0),pp));
ArrayInitialize(totalpowratio,0);
for (int p=0; p<pp; p++)
{
int pos= SymbolsFuncPos[n][s][p];
totalpowratio[p][0]= AlgorithmsTotalPowRatio[n][pos][0];
totalpowratio[p][1]= AlgorithmsTotalPowRatio[n][pos][1];
}
return(pp);
}
//------------------------------------------------------------
int FindIndicatorWindow()
{
static int LastSubChartIndex=0;
static int LastWindow=0;
int SubChartIndex=1;
int window= WindowFind(IndicatorName);
if (window>0)
{
ObjectCreate(DropWindowIdObject,OBJ_VLINE,window,0,0); // ñîçäà¸ì èäåíòèôèöèðóþùèé îáúåêò
ObjectSet(DropWindowIdObject,OBJPROP_COLOR,CLR_NONE);
ObjectSetText(DropWindowIdObject,window+"-"+MainChartIndex+"-0");
SubChartIndex=0;
}
else
{
if (ObjectFind(DropWindowIdObject)<0) return(-1);
string txt= ObjectDescription(DropWindowIdObject);
window= StrToInteger(txt);
int findpos= StringFind(txt, "-");
MainChartIndex= StrToInteger(StringSubstr(txt, findpos+1));
findpos= StringFind(txt, "-", findpos+2);
if (findpos>=0)
SubChartIndex= StrToInteger(StringSubstr(txt, findpos+1))+1;
ObjectSetText(DropWindowIdObject, window+"-"+MainChartIndex+"-"+SubChartIndex);
}
if (SubChartIndex!=LastSubChartIndex || window!=LastWindow)
{
DeleteObjects();
InitObjects(MainChartIndex, SubChartIndex);
IndicatorName= "ChartBuilder ("+MainChartIndex;
if (SubChartIndex>0) IndicatorName= IndicatorName+"-"+SubChartIndex;
IndicatorName= IndicatorName+")";
IndicatorShortName(IndicatorName);
LastSubChartIndex= SubChartIndex;
LastWindow=window;
}
return(window);
}
//-----------------------------------------------------------------------------------
void DeleteObjects()
{
if (StringLen(StatusLabel)>0) ObjectDelete(StatusLabel);
if (StringLen(SignalLabel)>0) ObjectDelete(SignalLabel);
for (int i=0; i<8; i++)
{
if (StringLen(LineAsk[i])>0) ObjectDelete(LineAsk[i]);
if (StringLen(LineBid[i])>0) ObjectDelete(LineBid[i]);
if (StringLen(ChartLabels[i])>0) ObjectDelete(ChartLabels[i]);
if (StringLen(ChartLabels_[i])>0) ObjectDelete(ChartLabels_[i]);
if (StringLen(ChartErrorLabels[i])>0) ObjectDelete(ChartErrorLabels[i]);
}
}
//-----------------------------------------------------------------------------------------------------------------
double MyFunc_ATR(double arrayprice[], int arraytime[], int currentpos, int maxcount, int period, int periodscount, int shift)
{
if (period==0 || periodscount==0) return(EMPTY_VALUE);
double sumvalue=0;
int periods=0;
int startperiodtime=0;
int lastpos;
for (int i=0; i<maxcount; i++)
{
int pos= currentpos-i;
int time= arraytime[pos];
if (startperiodtime==0)
{
startperiodtime= time/(period*60)*period*60;
lastpos=pos;
}
if (time>=startperiodtime) continue;
startperiodtime=0;
periods++;
if (periods < shift+1) { i--; continue; }
if (shift>0) { shift=0; periods=1; }
double maxvalue= arrayprice[ ArrayMaximum(arrayprice,lastpos-pos+1,pos) ];
double minvalue= arrayprice[ ArrayMinimum(arrayprice,lastpos-pos+1,pos) ];
sumvalue += maxvalue-minvalue;
i--;
if (periods==periodscount) break;
}
if (periods < periodscount + shift) return(EMPTY_VALUE);
return( sumvalue/periods );
}
//---------------------------------------------------------------
bool SaveToFile(string filename, int chartnumber, int savingbars)
{
int delimiter= StringGetChar(SaveToFile_Delimiter, 0);
if (delimiter==0) delimiter='\t';
int h= FileOpen(filename, FILE_WRITE|FILE_CSV, delimiter);
if (h<0) { Print("Error opening file ",filename); return(0); }
int buf= (chartnumber-1)*BuffersPerChart;
if (!OnlyClosePrice) buf++;
for (int i=0; i<Bars; i++)
{
double value= GetBuffer(buf,i);
if (value!=EMPTY_VALUE) FileWrite(h, TimeToStr(Time[i]+Period()*60-1), value);
}
FileClose(h);
return(true);
}
//---------------------------------------------------------
int ReadSymbolHistory(string symbol, int tf, double& rates[][6], int ratespos)
{
string file= symbol+tf+".hst";
int handle=FileOpenHistory(file, FILE_BIN|FILE_READ);
if (handle<0) { Print("Íå óäàëîñü íàéòè ôàéë ",file); return(-1); }
if (FileSeek(handle,148,SEEK_SET)==false)
{ Print("Íå óäàëîñü íàéòè ñòàðòîâóþ ïîçèöèþ èñòîðèè â ôàéëå ",file); return(0); }
int historysize= (FileSize(handle)-148)/44;
//Alert(symbol," history size: ",historysize);
int minarraysize= ratespos+historysize;
ArrayResize (rates, MathMax(ArrayRange(rates,0),minarraysize));
int i=ratespos;
int n=0;
while(true)
{
datetime readtime= FileReadInteger(handle, LONG_VALUE);
if (FileIsEnding(handle)) { Print("Ôàéë ",file," çàêîí÷åí äëÿ ÷òåíèÿ"); break; }
rates[i][0]=readtime;
FileReadArray(handle, rates, i*6+1, 5); // ñ÷èòûâàåì çíà÷åíèÿ öåí è îáú¸ìà
i++;
}
FileClose(handle);
return (i-ratespos);
}
//---------------------------------------------------------------
void SetParameters(int& arr[][], int i, int p0, int p1=0, int p2=0, int p3=0, int p4=0, int p5=0, int p6=0, int p7=0, int p8=0)
{ arr[i][0]=p0; arr[i][1]=p1; arr[i][2]=p2; arr[i][3]=p3; arr[i][4]=p4; arr[i][5]=p5; arr[i][6]=p6; arr[i][7]=p7; arr[i][8]=p8; }
void SetFuncParameters(string name, int funcindex, int p1=0, int p2=0, int p3=0, int p4=0, int p5=0, int p6=0, int p7=0, int p8=0)
{
static int i;
TemplateFuncName[i]= name;
SetParameters(TemplateFuncParam, i, funcindex, p1, p2, p3, p4, p5, p6, p7, p8);
if (StringLen(DefaultFuncName[funcindex])==0) DefaultFuncName[funcindex]=name;
i++;
}//---------------------------------------
void SetBuffer(int index, int bar, double value)
{
switch(index)
{
case 0: buffer0[bar]=value; break;
case 1: buffer1[bar]=value; break;
case 2: buffer2[bar]=value; break;
case 3: buffer3[bar]=value; break;
case 4: buffer4[bar]=value; break;
case 5: buffer5[bar]=value; break;
case 6: buffer6[bar]=value; break;
case 7: buffer7[bar]=value; break;
}
}
//-------------------------------------
double GetBuffer(int index, int bar)
{
switch(index)
{
case 0: return(buffer0[bar]);
case 1: return(buffer1[bar]);
case 2: return(buffer2[bar]);
case 3: return(buffer3[bar]);
case 4: return(buffer4[bar]);
case 5: return(buffer5[bar]);
case 6: return(buffer6[bar]);
case 7: return(buffer7[bar]);
}
}
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---