i have made a spell checker code using Ternary search tree. Can anybody tell me how to find the next possible word in TST.
for example if i want to search if i search a word "Manly" in spell checker and the word is not present in TST, so the output it gives like
DO YOU MEAN:
"Man"
"Mango"
.
.means possible near words
I have implemented my own spell checker but instead of a simple ternary trie I am using a ternary dag as Peter Kankowski suggests here. You can look at my blog for some details and how I did it. Its in Greek, but you can get an idea.
Edit:
Ok, you are right.
The basic idea is to use a pre-created list of candidates for a given edit distance ( a value of 2 for me is ok ). To reduce the size of the list one can use wildcard characters.
Such a list, of course, can be constructed in different ways. I prefer for / while loops like this ( e.g. for candidates of two substitutions )
void Substitute2( vector<wchar_t*>& v, const wstring& w )
{
size_t len = w.size();
if ( len < 2 )
return;
size_t p1 = 0, p2 = 1;
while ( p1 < len ) {
p2 = p1 + 1;
while ( p2 < len ) {
wchar_t* chars = new wchar_t[ len + 1 ];
for ( size_t i = 0; i < len; ++i ) {
if ( i != p1 && i != p2 ) {
chars[ i ] = w[ i ];
}
}
chars[ p1 ] = '?';
chars[ p2 ] = '?';
chars[ len ] = '\0';
v.push_back( chars );
p2++;
}
p1++;
}
}
After having prepared the candidates list, a simple search in a ternary dag for each item in the list will give us the suggestions for that misspelled word.
void Search( FileNode* pDict, FileNode* pNode, const wchar_t* Word, wstring Sug, set<wstring>& List )
{
if ( IsNullLink( pNode, pDict ) )
return;
if ( *Word == '?' ) {
Search( pDict, GetLo( pNode, pDict ), Word, Sug, List );
Search( pDict, GetEq( pNode, pDict ), Word + 1, Sug + pNode->Char, List );
Search( pDict, GetHi( pNode, pDict ), Word, Sug, List );
} else {
if ( *Word < pNode->Char ) {
Search( pDict, GetLo( pNode, pDict ), Word, Sug, List );
} else if ( *Word > pNode->Char ) {
Search( pDict, GetHi( pNode, pDict ), Word, Sug, List );
} else {
if ( pNode->Char == '\0' )
{
List.insert( Sug );
}
if ( *Word != '\0' ) {
Search( pDict, GetEq( pNode, pDict ), Word + 1, Sug + pNode->Char, List );
}
}
}
}
Note: The dictionary is a compiled (file based) ternary dag
The search for the word in your TST will terminate at a specific location in the tree. From this point, you can simply go up one level in the tree until you hit a level where there is more than just the child you came from.
On that level, you can simply choose the other possible paths and return those words.
Related
I'm trying to develop an Expert Advisor, so far I can understand and write this which will place orders when a new bar opens.
int BarsCount = 0;
int start()
{ if ( Bars > BarsCount )
{ OrderSend( Symbol(), OP_BUY, 0.01, Ask, 2, NULL, NULL );
BarsCount = Bars;
}
return( 0 );
}
how to get the highest value of standard deviation for last 2 hours to a variable?
E.g.: lets say the EA runs in a 30 mins chart and the bar1 has the standard deviation value 0.003, and bar2 has 0.001, bar3 has 0.004 and bar4 has 0.001.
So, the highest value for past 4 hours is bar3 which has the value of 0.004, so how to get that value to a variable?
I'm trying to make the EA place orders when this formula is true:
( ( current_value_of_standard_deviation
/ highest_value_of_standard_deviation_for_last_2_hours
)
* 100
) > 10
Use built-in tools:
input int MA_period = 27;
int BarsCount = 0;
int nCells2CMP= ( PERIOD_H1 * 2 / PERIOD_CURRENT ) - 1;
double Sig2H[100];
void OnInit(){
...
}
void OnTick(){
if ( Bars > BarsCount ){
if ( BarsCount == 0 ){
for ( int i = MA_period; i > 0; i-- ){
Sig2H[i] = iStdDev( _Symbol,
PERIOD_CURRENT,
0,
MODE_SMA,
PRICE_CLOSE,
i
);
}
}
for ( int i = MA_period; i > 1; i-- ) Sig2H[i] = Sig2H[i-1];
Sig2H[1] = iStdDev( _Symbol, // symbol
PERIOD_CURRENT, // timeframe
MA_period, // MA averaging period
0, // MA shift
MODE_SMA, // MA averaging method
PRICE_CLOSE, // applied price
1 // shift
);
}
Sig2H[0] = iStdDev( _Symbol, // symbol
PERIOD_CURRENT, // timeframe
MA_period, // MA averaging period
0, // MA shift
MODE_SMA, // MA averaging method
PRICE_CLOSE, // applied price
0 // shift
);
if ( 0.1 < ( Sig2H[0]
/ Sig2H[ArrayMaximum( Sig2H,
nCells2CMP,
1
)
]
)
){...}
}
I have tried many things but can't get it to work with the code below.
I've tried variations of the logic of the code below but have failed and am not sure where to implement it:
if ( OrderSelect( OrdersHistoryTotal() - 1, SELECT_BY_POS, MODE_HISTORY ) )
{
if ( OrderType() == OP_BUY )
{
if ( OrderClosePrice() > OrderStopLoss() ) Print( "Hit TP" );
else Print( "Hit SL" );
}
else if ( OrderType() == OP_SELL )
{
if ( OrderClosePrice() < OrderStopLoss() ) Print( "Hit TP" );
else Print( "Hit SL" );
}
}
or
Orderselect...
if ( MathAbs( OrderClosePrice()
- OrderTakeProfit()
) > MathAbs( OrderClosePrice()
- OrderStopLoss()
)
) Print( "StopLoss" );
if ( MathAbs( OrderClosePrice()
- OrderTakeProfit()
) < MathAbs( OrderClosePrice()
- OrderStopLoss()
)
) Print( "TakeProfit" );
The OrderSelect() has been an issue for me, so any help will be greatly appreciated.
Below is the EA I'm trying to add it to, but just knowing how and where to put it will help.
extern int MagicNumber = 10001;
extern double Lots = 0.01;
extern double StopLoss = 1;
extern double TakeProfit = 1;
extern int TrailingStop = 0;
extern int Slippage = 3;
//+------------------------------------------------------------------+
// expert start function
//+------------------------------------------------------------------+
int start() // New-MQL4.56789 #strict uses another constructor: int OnTick(){...}
{
double MyPoint = Point;
if ( Digits == 3
|| Digits == 5
) MyPoint = Point*10;
double TheStopLoss = 0;
double TheTakeProfit = 0;
if ( TotalOrdersCount() == 0 )
{
int result = 0;
if ( ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1 ) < iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 1 ) )
&& ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 0 ) > iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 0 ) )
) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here is your open BUY rule
{
result = OrderSend( Symbol(),
OP_BUY,
Lots,
Ask,
Slippage,
0,
0,
"Buy",
MagicNumber,
0,
Blue
);
if ( result > 0 )
{
TheStopLoss = 0;
TheTakeProfit = 0;
if ( TakeProfit > 0 ) TheTakeProfit = Ask + TakeProfit * MyPoint;
if ( StopLoss > 0 ) TheStopLoss = Ask - StopLoss * MyPoint;
OrderSelect( result, SELECT_BY_TICKET );
OrderModify( OrderTicket(),
OrderOpenPrice(),
NormalizeDouble( TheStopLoss, Digits ),
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
}
return(0);
}
if ( ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1 ) > iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 1 ) )
&& ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 0 ) < iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 0 ) )
) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here is your open SELL rule
{
result = OrderSend( Symbol(),
OP_SELL,
Lots,
Bid,
Slippage,
0,
0,
"Sell",
MagicNumber,
0,
Red
);
if ( result > 0 )
{
TheStopLoss = 0;
TheTakeProfit = 0;
if ( TakeProfit > 0 ) TheTakeProfit = Bid - TakeProfit * MyPoint;
if ( StopLoss > 0 ) TheStopLoss = Bid + StopLoss * MyPoint;
OrderSelect( result, SELECT_BY_TICKET );
OrderModify( OrderTicket(),
OrderOpenPrice(),
NormalizeDouble( TheStopLoss, Digits ),
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
}
return(0);
}
}
for ( int cnt = 0; cnt < OrdersTotal(); cnt++ )
{
OrderSelect( cnt, SELECT_BY_POS, MODE_TRADES );
if ( OrderType() <= OP_SELL
&& OrderSymbol() == Symbol()
&& OrderMagicNumber() == MagicNumber
)
{
if ( OrderType() == OP_BUY )
{
if ( TrailingStop > 0 )
{
if ( Bid - OrderOpenPrice() > MyPoint * TrailingStop )
{
if ( OrderStopLoss() < Bid - MyPoint * TrailingStop )
{
OrderModify( OrderTicket(),
OrderOpenPrice(),
Bid - TrailingStop * MyPoint,
OrderTakeProfit(),
0,
Green
);
return(0);
}
}
}
}
else
{
if ( TrailingStop > 0 )
{
if ( ( OrderOpenPrice() - Ask ) > ( MyPoint * TrailingStop ) )
{
if ( ( OrderStopLoss() > ( Ask + MyPoint * TrailingStop ) )
|| ( OrderStopLoss() == 0 )
)
{
OrderModify( OrderTicket(),
OrderOpenPrice(),
Ask + MyPoint * TrailingStop,
OrderTakeProfit(),
0,
Red
);
return(0);
}
}
}
}
}
}
return(0);
}
int TotalOrdersCount()
{
int result = 0;
for ( int i = 0; i < OrdersTotal(); i++ )
{
OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
if ( OrderMagicNumber() == MagicNumber ) result++;
}
return( result );
}
... open WHEN ... is the key part of the goal
OrderSelect() is not of much help for you to solve the "Open WHEN" puzzle. It just crawls accross a db.POOL of records, that MetaTrader Terminal 4 localhost internal DBMS takes care of, which is slow and very, very inefficient way to handle event the order-management tasks, so try to avoid any arbitrary scans thereof in a production-grade system. Here, you even will not get any cardinal piece of information you need for your task from such devastating db.POOL scans, so let's focus on the goal first.
... WHAT ... is the idea behind the goal?
The EA is a scholastically trivial variation on a slow-200 / fast-30 simple moving average cross.
There I guess you would like to add your additional idea of opening additional trades on condition the underlying SMA-cross-originated trade has reached it's { SL | TP }-termination respectively, right?
For such case, Brokers with a MetaTrader Server 4 typically allow you to place a so called pending order, which instructs a Broker, to maintain a record about your will to enter market, supposing a price reaches a pre-defined level -- ( guess what, these would be the { SL | TP } as you requested in the title -- and such record is waiting ( with some more configurable options ), until a such price movement happens or not, during which such position is waiting in an inactive state, called a pending order ...
For Terms & Conditions, kindly check your Broker's contract and/or ask their Customer Care representative. Some special limitations may apply ( better to know a-priori ).
... WHERE ... to put the code?
Without re-designing the provided code ( some minor errors/inefficiencies there ) the code shall go here:
result = OrderSend( Symbol(),
OP_SELL, // PRIMARY SELL <<<AT-MARKET>>>
Lots,
Bid,
Slippage,
0,
0,
"Sell",
MagicNumber,
0,
Red
);
if ( result > 0 )
{
TheStopLoss = 0;
TheTakeProfit = 0;
if ( TakeProfit > 0 ) TheTakeProfit = Bid - TakeProfit * MyPoint;
if ( StopLoss > 0 ) TheStopLoss = Bid + StopLoss * MyPoint;
OrderSelect( result, SELECT_BY_TICKET );
OrderModify( OrderTicket(),
OrderOpenPrice(),
NormalizeDouble( TheStopLoss, Digits ),
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
// ---------------------------------------------------- HERE ADD
OrderSend( Symbol(),
OP_SELLSTOP, // SELL-STOP PENDING ORDER ON SELL.TP
Lots,
NormalizeDouble( TheTakeProfit
- MarketInfo( _Symbol, MODE_SPREAD ),
Digits
),
Slippage,
0, // SL: T.B.D.
0, // TP: T.B.D.
"Sell on Sell.TP",
sTpMagicNumber, // avoid collisions with other logic
0, // never expires
Red
);
OrderSend( Symbol(),
OP_BUYSTOP, // BUY-STOP PENDING ORDER ON SELL.SL
Lots,
NormalizeDouble( TheStopLoss
- MarketInfo( _Symbol, MODE_SPREAD ),
Digits
),
Slippage,
0, // SL: T.B.D.
0, // TP: T.B.D.
"Buy on Sell.SL",
bSlMagicNumber, // avoid collisions with other logic
0, // never expires
Red
);
}
The spread-adjustment is not absolute, as during instable periods of time, the market is exposed to spurious spread volatilities. Again, Brokers' Terms & Conditions apply here, so be carefull.
I think there is something I am not understanding with an algorithm I'm working with. I have a binary tree where "*" is the root, "C" is on the left, "+" is on the right and + has "a" to the left and "b" to the right.
This is the algorithm:
Module Find_Value ( List, Root, Value ) {
If ( Root is NULL ){
Return NULL;
}Else{
If ( List [ Root ] .data equals Value )
Return Root;
Temp = Find_Value ( List, List[ Root ].left, Value )
If ( Temp is NULL )
Return Find_Value ( List, List[ Root ].right, Value );
Else
Return Temp;
}
}
And I'm supposed to carry out Find_Value(List, 0, b)
I could be just reading it wrong, but I do not see any instruction to go back up the tree. I get find_value(List,1,C) the first run-through and then I see temp as looking to the left of C (which is null) and the the right of C (also null). Can anyone tell me I am just interpreting the instructions incorrectly?
This is what is happening here:
(I have replaced * with 0,C with 2 for better understanding and also used them as identifiers for each temp at each step)
1) Temp(*) = Find_Value ( List, *.left, b );
2) Temp(C) = Find_value ( List,C.left,b); //returns null ,
therefore Temp(C) = NULL;
3) If ( Temp(C) is NULL )
Return Find_Value ( List, C.right, Value ); //returns null;
4) therefore the 1st step returns null;
Temp(*) = null;
5) If ( Temp(*) is NULL )
Return Find_Value ( List, *.right, Value );
6) Temp(+) = Find_Value ( List, +.left, Value );
7) Temp(a) = Find_Value ( List, a.left, Value ); // returns null
8) If ( Temp(a) is NULL )
Return Find_Value ( List, a.right, Value ); //returns null
therefore Temp(+) = NULL;
9) If ( Temp(+) is NULL )
Return Find_Value ( List, +.right, Value );
10) If ( List [ Root ].data equals Value )
Return Root;
where List[Root].data = b;
Step 9 returns b,followed by Step 5 returning b;
and overall the function return b;
I am failing over and over trying to get this indicator to run quantised with 2 buffers in mql4. After a long time reading I have put 2 extra buffers in to squish it :/ because:
the indicator is sitting between 0.1430-0.1427 at present but doesn't have a fixed top and bottom.
I can't seem to suss it; cool indicator but won't play fair!
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Lime
#property indicator_color2 Red
#property indicator_color3 CLR_NONE
#property indicator_color4 CLR_NONE
//#property indicator_minimum 0
//#property indicator_maximum 100
extern int P = 13;
extern int T = 3000;
extern double P2 = 0.001;
//int MIN = 0;
//int MAX = 100;
double G[];
double R[];
double B3[];
double B4[];
int init(){
IndicatorBuffers(4);
SetIndexBuffer( 0, G );SetIndexStyle( 0, DRAW_LINE, STYLE_SOLID, 1, Lime );
SetIndexBuffer( 1, R );SetIndexStyle( 1, DRAW_LINE, STYLE_SOLID, 1, Red );
SetIndexBuffer( 2, B3 );SetIndexStyle( 2, DRAW_NONE );
SetIndexBuffer( 3, B4 );SetIndexStyle( 3, DRAW_NONE );
return(0);
}
int start(){
if ( T >= Bars ) T = Bars;
SetIndexDrawBegin( 0, Bars - T + P + 1 );
SetIndexDrawBegin( 1, Bars - T + P + 1 );
SetIndexDrawBegin( 2, Bars - T + P + 1 );
SetIndexDrawBegin( 3, Bars - T + P + 1 );
int Z, C, Opt = IndicatorCounted();
if ( Bars <= 38 ) return(0);
if ( Opt < P ){
for ( Z = 1; Z <= 0; Z++ ) G[T-Z] = 0.0;
for ( Z = 1; Z <= 0; Z++ ) R[T-Z] = 0.0;
}
Z = T - P - 1;
while( Z >= 0 ){
double A, S1, S2;
S1 = 0.0; for ( C = 0; C <= P - 1; C++ ){ S1 = S1 + ( High[Z+C] + Low[Z+C] ) / 2;}
S2 = 0.0; for ( C = 0; C <= P - 1; C++ ){ S2 = S2 + ( ( High[Z+C] + Low[Z+C] ) * ( C+1 ) / 2 );}
A = S1 / S2;
// if ( A < MIN ){ MIN = A;}
// if ( A > MAX ){ MAX = A;}
// A = ( MIN / MAX ) * 100;
G[Z] = A;
if ( Z > 0 ){ R[Z-1] = A;}
Z--;
}
for ( int N = T-P-2; N >= 0; N-- ){
if ( N > 0 ){
if ( G[N-1] > G[N] ){ R[N] = EMPTY_VALUE; continue;}
if ( G[N-1] < G[N] ){ G[N] = R[N]; continue;}
}
B3[0] = G[0] + P2;
B4[0] = G[0] - P2; //forced quantise using 2 extra buffers
}
return(0);
}
Let´s split the task first
0) indicator logic
1) indicator quantisation step
2) indicator performance
MQL4 Custom Indicator programming relies on deeper understanding of underlying MetaTrader4 Terminal platform. Each external Market Event, changing a traded instrument price, is signalled to a lcoalhost by a network delivery of a QUOTE ... message from MetaTrader4 Server. This is aka Tick and it triggers a call to a function originally called start(), in newer New-MQL4.56789 renamed to OnTick().
The below modified MQL4 listing contains remarks for core-logic disambiguation, which must precede all the below listed steps.
1) indicator quantisation step
While the code is still very inefficient ( as per [2] below ) the logic does not include any straight hurdle form having the output quantised to any form thereof { binary | ternary | arbitrary-number-of-states }-quantised system. Whence the indicator core-logic is cleared, the quantisation step is just a trivial conversion from R(1) to I(1).
2) indicator performance
Any Tick arrival may, but need not modify either High[0] or Low[0], which are the only variable parts of the proposed Custom Indicator calculus.
This is the core idea on how to reduce the scope of re-calculations, that the MQL4 code has to realise per tick. In recent versions of MT4, all Custom Indicators share a single thread, the more stress has been put on efficient algorithmisation of Custom Indicators, at these may block the platform's trading decisions on poor, inefficient code-loops and convolution/recursion re-executions.
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Lime
#property indicator_color2 Red
#property indicator_color3 CLR_NONE
#property indicator_color4 CLR_NONE
extern int P = 13;
extern int T = 3000;
extern double P2 = 0.001;
double G[]; // 0: LINE
double R[]; // 1: LINE
double B3[]; // 2: BUT NEVER PAINTED, NEVER CONSUMED _?_
double B4[]; // 3: BUT NEVER PAINTED, NEVER CONSUMED _?_
int init(){
IndicatorBuffers(4);
SetIndexBuffer( 0, G );SetIndexStyle( 0, DRAW_LINE, STYLE_SOLID, 1, Lime );
SetIndexBuffer( 1, R );SetIndexStyle( 1, DRAW_LINE, STYLE_SOLID, 1, Red );
SetIndexBuffer( 2, B3 );SetIndexStyle( 2, DRAW_NONE );
SetIndexBuffer( 3, B4 );SetIndexStyle( 3, DRAW_NONE );
return(0);
}
int start(){
if ( Bars <= 38 ) return(0); // JIT/RET in case Bars < 39 --^ --^ --^ --^
if ( T >= Bars ) T = Bars; // (TRIM´d) T < Bars .OR. = Bars
int aDrawBegins = Bars - T + P + 1; // ( extern P = 13 ) + 1 + ( Bars - ( extern T = 3000 if T < Bars else Bars ) )
//tIndexDrawBegin( 0, Bars - T + P + 1 ); // PREF: ( reused 4x )
SetIndexDrawBegin( 0, aDrawBegins ); // Draw 14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
SetIndexDrawBegin( 1, aDrawBegins ); // Draw 14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
SetIndexDrawBegin( 2, aDrawBegins ); // Draw 14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
SetIndexDrawBegin( 3, aDrawBegins ); // Draw 14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
double A, S1, S2; // auxiliary var for bar-mid-price calculi
int Z; // auxiliary stepper
int Opt = IndicatorCounted(); // Opt ( NEVER RE-USED )
if ( Opt < P ){ // if ( ( extern P = 13 ) > IndicatorCounted() )
// ----------------------- ??? ----------------------------------------------------- NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
for ( Z = 1; Z <= 0; Z++ ) G[T-Z] = 0.0; // .STO G[T-Z], 0., BUT NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
for ( Z = 1; Z <= 0; Z++ ) R[T-Z] = 0.0; // .STO R[T-Z], 0., BUT NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
// ----------------------- ??? ----------------------------------------------------- NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
}
Z = T - P - 1; // .STO Z, ( T = Bars (TRIM´d) ) - ( extern P = 13 ) - 1
while( Z >= 0 ){ // .DEC Z
// !!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PERF: very inefficient to RE-calc STATIC ( ( extern P = 13 ) - 1 )-DEEP CONVOLUTIONS per tick !!
S1 = 0.0; for ( int C = 0; C <= P - 1; C++ ){ S1 = S1 + ( High[Z+C] + Low[Z+C] ) / 2; }
S2 = 0.0; for ( int C = 0; C <= P - 1; C++ ){ S2 = S2 + ( ( High[Z+C] + Low[Z+C] ) * ( C+1 ) / 2 );}
// !!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PERF: very inefficient to RE-calc STATIC ( ( extern P = 13 ) - 1 )-DEEP CONVOLUTIONS per tick !!
A = S1 / S2;
G[Z] = A; // .STO G[Z], A if Z >= 0
if ( Z > 0 ){ R[Z-1] = A;} // .STO R[Z-1], A if Z > 0
Z--;
}
for ( int N = T - P - 2; N >= 0; N-- ){ // .STO N, ( T = Bars (TRIM´d) ) - ( extern P = 13 ) - 2
if ( N > 0 ){ // N > 0:
if ( G[N-1] > G[N] ){ R[N] = EMPTY_VALUE; continue;} // .BLNK R[N], EMPTY if G[N-1] > G[N]
if ( G[N-1] < G[N] ){ G[N] = R[N]; continue;} // .SET G[N], R[N] if G[N-1] < G[N]
}
// ?? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // WHY MANY-TIMES RE-ASSIGNED A CONST. VALUE HERE, INSIDE A FOR(){...}-loop body? -------------- ??
B3[0] = G[0] + P2; // .STO B3[0], G[0] + ( extern P2 = 0.001 )
B4[0] = G[0] - P2; // .STO B4[0], G[0] - ( extern P2 = 0.001 )
// forced quantise using 2 extra buffers
// ?? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // WHY MANY-TIMES RE-ASSIGNED A CONST. VALUE HERE, INSIDE A FOR(){...}-loop body? -------------- ??
}
return(0);
}
New-MQL4.56789 syntax
The OnCalculate() function is called only in custom indicators when it's necessary to calculate the indicator values by the Calculate event. This usually happens when a new tick is received for the symbol, for which the indicator is calculated. This indicator is not required to be attached to any price chart of this symbol.
The first rates_total parameter contains the number of bars, available to the indicator for calculation, and corresponds to the number of bars available in the chart.
We should note the connection between the return value of OnCalculate() and the second input parameter prev_calculated. During the OnCalculate() function call, the prev_calculated parameter contains a value returned by OnCalculate() during previous call. This allows for economical algorithms for calculating the custom indicator in order to avoid repeated calculations for those bars that haven't changed since the previous run of this function.
For this, it is usually enough to return the value of the rates_total parameter, which contains the number of bars in the current function call. If since the last call of OnCalculate() the price data has changed (a deeper history downloaded or history blanks filled), the value of the input parameter prev_calculated will be set to zero by the terminal.
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate( const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]
)
{
// Get the number of bars available now for the current Symbol and chart period
int barsNow = Bars( _Symbol, PERIOD_CURRENT );
// .RET value of prev_calculated for a next call
return( rates_total );
}
PostScript/PDF string literals are surrounded by parentheses, and are allowed to contain unescaped parentheses as long as the parentheses are fully balanced. So for instance
( () ) % valid string constant
( ( ) % invalid string constant, the inner ( should be escaped
I know an algorithm to tell me if there are any unbalanced parentheses in a string; what I'm looking for is an algorithm that will locate a minimal set of parentheses that are unbalanced, so that I can then stick backslashes in front of them to make the whole a valid string literal. More examples:
( ⟶ \(
() ⟶ ()
(() ⟶ \(() or (\()
()) ⟶ ()\) or (\))
()( ⟶ ()\(
A modification of the standard stack based algorithm to detect imbalanced parenthesis should work for you. Here's some pseudo code:
void find_unbalaned_indices(string input)
{
// initialize 'stack' containing of ints representing index at
// which a lparen ( was seen
stack<int index> = NIL
for (i=0 to input.size())
{
// Lparen. push into the stack
if (input[i] == '(')
{
// saw ( at index=i
stack.push(i);
}
else if (input[i] == ')')
{
out = stack.pop();
if (out == NIL)
{
// stack was empty. Imbalanced RParen.
// index=i needs to be escaped
...
}
// otherwise, this rparen has a balanced lparen.
// nothing to do.
}
}
// check if we have any imbalanced lparens
while (stack.size() != 0)
{
out = stack.pop();
// out is imbalanced
// index = out.index needs to be escaped.
}
}
Hope this helps.
def escape(s):
return ''.join(r(')(', r('()', s)))
def r(parens, chars):
return reversed(list(escape_oneway(parens, chars)))
def escape_oneway(parens, chars):
"""Given a sequence of characters (possibly already escaped),
escape those close-parens without a matching open-paren."""
depth = 0
for x in chars:
if x == parens[0]:
depth += 1
if x == parens[1]:
if depth == 0:
yield '\\' + x
continue
else:
depth -= 1
yield x