This is a simple request.
I have to create a column in query editor, or in table view. Whichever is easy.
Column looks like this -->
A,B,C,D,D,E,D
B,C,D,B,D,A
C,C,D,F,E,G
D,D,E,E,E,F,B
Result should be based on count of characters present, with 'A' character always taking the priority.
For instance result of the above column next to it will be
A ( A will take priority even if D has most count)
A (Even though B has most count, A will take Priority)
C ( as C has most count)
E ( as E has most count)
Result =
VAR String = COALESCE ( 'Table'[Column], "XX" )
VAR Items = SUBSTITUTE ( String, ",", "|" )
VAR Length = PATHLENGTH ( Items )
VAR T1 = GENERATESERIES ( 1, Length, 1 )
VAR T2 = ADDCOLUMNS ( T1, "#Item", PATHITEM ( Items, [Value] ) )
VAR T3 = GROUPBY ( T2, [#Item], "#Count", COUNTX ( CURRENTGROUP(), 1 ) )
VAR T4 = TOPN ( 1, T3, [#Count] )
VAR Result = MAXX ( T4, [#Item] )
RETURN
IF ( PATHCONTAINS ( Items, "A" ), "A", Result )
Blockquote
I'm trying to optimize a measure, and after analyzing it I found that the problem comes from the fact that part of it is calculated on every row when it only needs to be calculated once when a certain filter is applied.
Here's the measure :
Effectif :=
VAR LastPeriod =
MAX ( 'Time'[Period] )
RETURN
CALCULATE (
DISTINCTCOUNT ( 'Sales'[ClientID] ),
FILTER (
Sales,
OR (
LastPeriod - Sales[ClientLastOrder] < 4,
LastPeriod - Sales[ClientEntry] < 4
)
)
)
In this case, LastPeriod will be calculated over and over, whereas we only need it to be calculated once when a filter is applied on Time.
Is there any way to store this information somewhere so that it doesn't have to make superfluous calculations ?
Try this 2 Codes, and let me know If one or both of them are any faster. Instead of iterating (or scanning ) a full table, you only iterate the columns you need in a filter argument. Like this:
Version-1
Effectif :=
VAR LastPeriod =
MAX ( 'Time'[Period] )
RETURN
CALCULATE (
DISTINCTCOUNT ( 'Sales'[ClientID] ),
FILTER (
ALL ( Sales[ClientLastOrder], Sales[ClientEntry] ),
OR (
LastPeriod - Sales[ClientLastOrder] < 4,
LastPeriod - Sales[ClientEntry] < 4
)
)
)
Version-2
Effectif :=
VAR LastPeriod =
MAX ( 'Time'[Period] )
RETURN
CALCULATE (
DISTINCTCOUNT ( 'Sales'[ClientID] ),
CALCULATETABLE (
SUMMARIZE ( Sales, Sales[ClientLastOrder], Sales[ClientEntry] ),
OR (
LastPeriod - Sales[ClientLastOrder] < 4,
LastPeriod - Sales[ClientEntry] < 4
)
)
)
It is hard to be confident without any data sample, but I guess that this formula of LastPeriod calculating may help you:
VAR LastPeriod =
CALCULATE(
MAX ( 'Time'[Period] ),
ALL('Sales')
)
Also you may check such function as ALLSELECTED(). It may fit you more.
I'm using the calculation below to calculate the sum of the amount for accounts >= 200
And the problem I have is when I visualize Account with Account total with excel, it gives me the total amount in all accounts.
How can I solve this?`
Account total:= CALCULATE(SUM('Table'[amount]),'Table'[Type]= "ABC",'Table'[account] >=200)
#Jos is mostly correct but there are some small inaccuracies.
This code
CALCULATE (
SUM ( 'Table'[amount] ),
'Table'[Type] = "ABC",
'Table'[account] >= 200
)
is equivalent to
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( ALL ( 'Table'[Type] ), 'Table'[Type] = "ABC" ),
FILTER ( ALL ( 'Table'[account] ), 'Table'[account] >= 200 )
)
not
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( ALL ( 'Table' ), 'Table'[Type] = "ABC" && 'Table'[account] >= 200 )
)
In particular, if you had a filter on, say, 'Table'[Category], this would be preserved in the former but not in the latter since ALL ( 'Table' ) removes filters on all of the columns, not just [Type] and [account].
I propose the following two nearly equivalent solutions, which are slightly more computationally efficient than filtering an entire table:
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( VALUES ( 'Table'[Type] ), 'Table'[Type] = "ABC" ),
FILTER ( VALUES ( 'Table'[account] ), 'Table'[account] >= 200 )
)
or
CALCULATE (
SUM ( 'Table'[amount] ),
KEEPFILTERS ( 'Table'[Type] = "ABC" ),
KEEPFILTERS ( 'Table'[account] >= 200 )
)
More on KEEPFILTERS: https://www.sqlbi.com/articles/using-keepfilters-in-dax/
You should be using:
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( 'Table', 'Table'[Type] = "ABC" && 'Table'[account] >= 200 )
)
The difference is that your current formula is equivalent to:
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( ALL ( 'Table' ), 'Table'[Type] = "ABC" && 'Table'[account] >= 200 )
)
i.e. identical to that which I give apart from the crucial difference that it applies an (in your case implicit) ALL to the table prior to filtering. This implicit ALL will override any filters you may be applying externally.
I moved a report from Power BI to Power Pivot, but the formula of SELECTEDVALUE does not exist in Power Pivot.
Can you help correct to a function that works in Power Pivot?
las_val =
VAR y =
SELECTEDVALUE ( DateTime[Gasday] )
RETURN
CALCULATE (
HEML_TTF_PRICE_V[TTF_DA_WE],
TOPN (
1,
FILTER (
ALLSELECTED ( DateTime[Gasday] ),
DateTime[Gasday] <= y
&& NOT ( ISBLANK ( HEML_TTF_PRICE_V[TTF_DA_WE] ) )
),
DateTime[Gasday], DESC
)
)
SELECTEDVALUE is a newer function that's a shortcut for
IF ( HASONEVALUE ( DateTime[GasDay] ), VALUES ( DateTime[GasDay] ) )
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.