Berechnet die ungünstigste kombinierte Maximum Adverse Excursion, wenn mehrere Positionen gleichzeitig geöffnet sind, und hilft Ihnen so, Drawdowns bei Basket-Einstiegsstrategien zu quantifizieren.
Größte MAE – nützlich für die Analyse von Strategien mit einzelnen oder mehreren Orders.
Mehrere Orders im Vergleich zu einer einzelnen Order
Es ist effizienter, das Risiko auf einen Korb von Orders zu verteilen, anstatt auf eine einzelne Order. Mehrere Einstiegspositionen bieten mehr Flexibilität, ohne dass ein präzises Timing für einen einzelnen Einstieg erforderlich ist.
Wenn mehrere Orders gleichzeitig in derselben Richtung eröffnet werden, berechnen Sie die Gesamt-MAE aller offenen Positionen. Wenn Positionen in entgegengesetzter Richtung liegen (Hedging), ziehen Sie die MFE der entgegengesetzten Positionen von der größeren MAE ab, um die globale MAE zu erhalten.
Vier Snippets
BiggestMAEallTrade – Größte MAE für einen Kontrakt, pro Kontrakt normalisiert für genaue Ergebnisse, selbst wenn die Strategie die Kontraktgröße während des Backtestings erhöht.
package SQ.Columns.Databanks;
import com.strategyquant.lib.L;
import com.strategyquant.lib.SQUtils;
import com.strategyquant.lib.SettingsMap;
import com.strategyquant.tradinglib.*;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
import java.lang.*;
// Mode in France by Emmanuel Evrard for the StrategyQuantX Community :)
public class BiggestMAEallTrade extends DatabankColumn
{
public BiggestMAEallTrade()
{
super(L.tsq("Biggest Multiple MAE"), DatabankColumn.Decimal2PL, ValueTypes.Minimize, 0, 0, 100);
setWidth(140);
setTooltip(L.tsq("Biggest Multiple MAE - is the worst Maximum Adverse Excursion of all trades open at once"));
}
//------------------------------------------------------------------------
@Override
public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort) throws Exception
{
double worstMAE = -Double.MAX_VALUE;
Date date = new Date();
Date dateTemp = new Date();
double Total1 = 0;
double Size1 = 0;
for(int i = 0; i<ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
Size1 = order.Size;
if (Size1 == 0) { Size1 = 0.01; }
if (dateTemp.equals(date))
{
Total1 += order.MAE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MAE;
}
if((Total1 / Size1) > worstMAE)
{
worstMAE = (Total1/order.Size);
}
}
return -1*worstMAE;
}
}
BiggestMAEallTradePct – Größte MAE als Prozentsatz des Kontostands. Zeigt an, ob die Strategie ein angemessenes Risiko im Verhältnis zum Konto verwendet (z. B. im Vergleich zu maximal 5 % Tagesverlust).
package SQ.Columns.Databanks;
import com.strategyquant.lib.L;
import com.strategyquant.lib.SQUtils;
import com.strategyquant.lib.SettingsMap;
import com.strategyquant.tradinglib.*;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
import java.lang.*;
// Mode in France by Emmanuel Evrard for the StrategyQuantX Community :)
public class BiggestMAEallTradePct extends DatabankColumn
{
public BiggestMAEallTradePct()
{
super(L.tsq("Biggest Multiple MAE %"), DatabankColumn.Decimal2Pct, ValueTypes.Minimize, 0, 0, 100);
setWidth(70);
setTooltip(L.tsq("Biggest Multiple MAE % - is the worst Maximum Adverse Excursion of all trades open at once compared to AccountBalance"));
}
@Override
public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort) throws Exception
{
double worstMAE = -Double.MAX_VALUE;
Date date = new Date();
Date dateTemp = new Date();
double Total1 = 0;
double Total2 = 0;
for(int i = 0; i<ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
if (dateTemp.equals(date))
{
Total1 += order.MAE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MAE;
}
Total2 = SQUtils.safeDivide(Total1, order.AccountBalance - order.PL) * 100.0;
if(Total2 > worstMAE)
{
worstMAE = Total2;
}
}
return -1*worstMAE;
}
}
BiggestMAEallHedgingTrade & BiggestMAEallHedgingTradePct – Für abgesicherte Positionen in entgegengesetzten Richtungen. Nimmt die größere MAE und zieht die MFE der Gegenrichtung ab. Funktioniert, wenn während der größeren MAE entgegengesetzte Trades offen sind.
package SQ.Columns.Databanks;
import com.strategyquant.lib.L;
import com.strategyquant.lib.SQUtils;
import com.strategyquant.lib.SettingsMap;
import com.strategyquant.tradinglib.*;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
import java.lang.*;
// Mode in France by Emmanuel Evrard for the StrategyQuantX Community :)
public class BiggestMAEallHedgingTrade extends DatabankColumn
{
public BiggestMAEallHedgingTrade()
{
super(L.tsq("Biggest Multiple Hedging MAE"), DatabankColumn.Decimal2PL, ValueTypes.Minimize, 0, 0, 100);
setWidth(140);
setTooltip(L.tsq("Biggest Multiple Hedging MAE - is the worst Maximum Adverse Excursion of all trades open at once"));
}
//------------------------------------------------------------------------
@Override
public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort) throws Exception
{
double worstMAE1= -Double.MAX_VALUE;
double worstMAE2 = -Double.MAX_VALUE;
double BesttMFE1= -Double.MAX_VALUE;
Date date = new Date();
Date dateTemp = new Date();
double Total1 = 0;
double Size1 = 0;
int direction = 0;
for(int i = 0; i < ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
Size1 = order.Size;
direction=order.getDirection();
if (direction == 1) // Bullish positions
{
if (Size1 == 0) { Size1 = 0.01; }
if (dateTemp.equals(date))
{
Total1 += order.MAE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MAE;
}
if((Total1 / Size1) > worstMAE1)
{
worstMAE1 = (Total1/order.Size);
}
}
}
Total1 = 0;
for(int i = 0; i < ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
Size1 = order.Size;
direction=order.getDirection();
if (direction == -1) // Bearish positions
{
if (Size1 == 0) { Size1 = 0.01; }
if (dateTemp.equals(date))
{
Total1 += order.MAE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MAE;
}
if((Total1 / Size1) > worstMAE2)
{
worstMAE2 = (Total1/order.Size);
}
}
}
if (worstMAE1 >= worstMAE2)
{
Total1 = 0;
for(int i = 0; i < ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
Size1 = order.Size;
direction=order.getDirection();
if (direction == -1) // Bearish positions
{
if (Size1 == 0) { Size1 = 0.01; }
if (dateTemp.equals(date))
{
Total1 += order.MFE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MFE;
}
if((Total1 / Size1) > BesttMFE1)
{
BesttMFE1 = (Total1/order.Size);
}
}
}
return -1*(worstMAE1 - BesttMFE1);
}
else if (worstMAE2 > worstMAE1)
{
Total1 = 0;
for(int i = 0; i < ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
Size1 = order.Size;
direction=order.getDirection();
if (direction == 1) // Bullish positions
{
if (Size1 == 0) { Size1 = 0.01; }
if (dateTemp.equals(date))
{
Total1 += order.MFE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MFE;
}
if((Total1 / Size1) > BesttMFE1)
{
BesttMFE1 = (Total1/order.Size);
}
}
}
return -1*(worstMAE2 - BesttMFE1);
}
return 0;
}
}
package SQ.Columns.Databanks;
import com.strategyquant.lib.L;
import com.strategyquant.lib.SQUtils;
import com.strategyquant.lib.SettingsMap;
import com.strategyquant.tradinglib.*;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
import java.lang.*;
// Mode in France by Emmanuel Evrard for the StrategyQuantX Community :)
public class BiggestMAEallHedgingTradePct extends DatabankColumn
{
public BiggestMAEallHedgingTradePct()
{
super(L.tsq("Biggest Multiple Hedging MAE %"), DatabankColumn.Decimal2Pct, ValueTypes.Minimize, 0, 0, 100);
setWidth(100);
setTooltip(L.tsq("Biggest Multiple Hedging MAE % - is the worst Maximum Adverse Excursion of all trades open at once compared to AccountBalance"));
}
@Override
public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort) throws Exception
{
double worstMAE1= -Double.MAX_VALUE;
double worstMAE2 = -Double.MAX_VALUE;
double BesttMFE1= -Double.MAX_VALUE;
Date date = new Date();
Date dateTemp = new Date();
double Total1 = 0;
double Total2 = 0;
int direction = 0;
for(int i = 0; i<ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
direction=order.getDirection();
if (direction == 1) // Bullish position
{
if (dateTemp.equals(date))
{
Total1 += order.MAE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MAE;
}
Total2 = SQUtils.safeDivide(Total1, order.AccountBalance - order.PL) * 100.0;
if(Total2 > worstMAE1)
{
worstMAE1 = Total2;
}
}
}
Total1 = 0;
for(int i = 0; i<ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
direction=order.getDirection();
if (direction == -1) // Bearish position
{
if (dateTemp.equals(date))
{
Total1 += order.MAE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MAE;
}
Total2 = SQUtils.safeDivide(Total1, order.AccountBalance - order.PL) * 100.0;
if(Total2 > worstMAE2)
{
worstMAE2 = Total2;
}
}
}
if (worstMAE1 >= worstMAE2)
{
Total1 = 0;
for(int i = 0; i<ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
direction=order.getDirection();
if (direction == -1) // Bearish position
{
if (dateTemp.equals(date))
{
Total1 += order.MFE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MFE;
}
Total2 = SQUtils.safeDivide(Total1, order.AccountBalance - order.PL) * 100.0;
if(Total2 > BesttMFE1)
{
BesttMFE1 = Total2;
}
}
}
return -1*(worstMAE1 - BesttMFE1);
}
else if (worstMAE2 > worstMAE1)
{
Total1 = 0;
for(int i = 0; i<ordersList.size(); i++)
{
Order order = ordersList.get(i);
dateTemp = new Date(order.CloseTime);
direction=order.getDirection();
if (direction == 1) // Bullish position
{
if (dateTemp.equals(date))
{
Total1 += order.MFE;
}
else
{
date = new Date(order.CloseTime);
Total1 = order.MFE;
}
Total2 = SQUtils.safeDivide(Total1, order.AccountBalance - order.PL) * 100.0;
if(Total2 > BesttMFE1)
{
BesttMFE1 = Total2;
}
}
}
return -1*(worstMAE2 - BesttMFE1);
}
return 0;
}
}