//------------------------------------------------------------------------
// 简称: EMA_Trend_Strategy
// 名称: EMA浮盈减仓版
//------------------------------------------------------------------------
Params
Numeric EMA_Long_Length(34);
Numeric EMA_Short1_Length(21);
Numeric EMA_Short2_Length(13);
Numeric EMA_Exit_Length(21);
Numeric FixedPosition(2);
Numeric StopLossPoints(200);
Numeric MinOrderInterval(2);
Numeric MaxDailyOrders(10);
Numeric ProfitReduceRatio(0.012);
Bool UseProfitReduce(True);
Numeric BreakevenThreshold(0.002);
Numeric FlatBarsCount(10);
Numeric VolumeRatio(1.5);
Bool UseVolumeFilter(True);
Numeric AvgAmplitudeThreshold(0.01);
Numeric Price_EMA2_Threshold(0.0085);
Numeric GapPercent(0.01);
Bool UseCandleFilter(True);
Numeric MinBodyRatio(0.65);
Numeric MaxUpperShadowRatio(0.3);
Numeric MaxLowerShadowRatio(0.3);
Vars
Series<Numeric> EMA1;
Series<Numeric> EMA2;
Series<Numeric> EMA3;
Series<Numeric> EMA4;
Series<Numeric> SelfPosition;
Series<Bool> PositionLock;
Series<Numeric> EntryPrice;
Series<Numeric> EntryBar;
Bool CanOpenLong;
Bool CanOpenShort;
Bool ForceClose;
Bool ForceClose_SL;
Bool ForceClose_EMA;
Bool ForceClose_Signal;
Bool ForceClose_Breakeven;
Numeric CurrentProfitRate;
Numeric CurrentLossPoints;
Numeric MaxFavorablePoints;
Series<Bool> ReducedPosition;
Series<Numeric> OriginalPosition;
Series<Bool> BreakevenSet;
Series<Numeric> HighestPrice;
Series<Numeric> LowestPrice;
Bool MarketFlat;
Numeric i;
Numeric AvgAmplitude;
Series<Numeric> AvgVolume;
Bool VolumeOK;
Series<Numeric> LastOrderBar;
Series<Numeric> TodayOrderCount;
Series<Numeric> CurrentTradeDate;
Numeric BarsSinceLastOrder;
Bool AllowNewOrder;
Series<Bool> JustClosedFlag;
Series<Numeric> ClosedBar;
Bool LongSignal;
Bool ShortSignal;
Bool AboveEMA1;
Bool BelowEMA1;
Numeric BodySize;
Numeric Amplitude;
Numeric BodyRatio;
Numeric UpperShadow;
Numeric LowerShadow;
Numeric UpperShadowRatio;
Numeric LowerShadowRatio;
Bool CandleFilterOK;
Events
OnBar(ArrayRef<Integer> indexs)
{
ForceClose = False;
ForceClose_SL = False;
ForceClose_EMA = False;
ForceClose_Signal = False;
ForceClose_Breakeven = False;
CurrentProfitRate = 0;
CurrentLossPoints = 0;
MaxFavorablePoints = 0;
If(CurrentBar == 0)
{
CurrentTradeDate = Date;
TodayOrderCount = 0;
JustClosedFlag = False;
EntryPrice = 0;
EntryBar = 0;
ReducedPosition = False;
OriginalPosition = 0;
BreakevenSet = False;
HighestPrice = 0;
LowestPrice = 999999;
LastOrderBar = -100;
ClosedBar = -100;
SelfPosition = 0;
PositionLock = False;
}
If(MarketPosition == 0 && PositionLock == True)
{
SelfPosition = 0;
PositionLock = False;
EntryPrice = 0;
EntryBar = 0;
ReducedPosition = False;
OriginalPosition = 0;
BreakevenSet = False;
HighestPrice = 0;
LowestPrice = 999999;
MaxFavorablePoints = 0;
CurrentProfitRate = 0;
CurrentLossPoints = 0;
}
If(SelfPosition == 0)
{
EntryPrice = 0;
EntryBar = 0;
ReducedPosition = False;
OriginalPosition = 0;
BreakevenSet = False;
HighestPrice = 0;
LowestPrice = 999999;
MaxFavorablePoints = 0;
CurrentProfitRate = 0;
CurrentLossPoints = 0;
}
If(Date != CurrentTradeDate)
{
CurrentTradeDate = Date;
TodayOrderCount = 0;
JustClosedFlag = False;
}
If(JustClosedFlag && CurrentBar > ClosedBar + MinOrderInterval)
{
JustClosedFlag = False;
}
BarsSinceLastOrder = CurrentBar - LastOrderBar;
AllowNewOrder = (TodayOrderCount < MaxDailyOrders) &&
(BarsSinceLastOrder >= MinOrderInterval || TodayOrderCount == 0) &&
!JustClosedFlag &&
!PositionLock;
EMA1 = XAverage(Close, EMA_Long_Length);
EMA2 = XAverage(Close, EMA_Short1_Length);
EMA3 = XAverage(Close, EMA_Short2_Length);
EMA4 = XAverage(Close, EMA_Exit_Length);
If(UseCandleFilter)
{
BodySize = Abs(Close - Open);
Amplitude = High - Low;
If(Amplitude > 0)
{
BodyRatio = BodySize / Amplitude;
UpperShadow = High - Max(Close, Open);
LowerShadow = Min(Close, Open) - Low;
UpperShadowRatio = UpperShadow / Amplitude;
LowerShadowRatio = LowerShadow / Amplitude;
CandleFilterOK = (BodyRatio >= MinBodyRatio) &&
(UpperShadowRatio <= MaxUpperShadowRatio) &&
(LowerShadowRatio <= MaxLowerShadowRatio);
}
Else
{
CandleFilterOK = True;
}
}
Else
{
CandleFilterOK = True;
}
MarketFlat = False;
AvgAmplitude = 0;
If(CurrentBar >= FlatBarsCount)
{
For i = 1 To FlatBarsCount
{
AvgAmplitude = AvgAmplitude + (High[i] - Low[i]) / Close[i];
}
AvgAmplitude = AvgAmplitude / FlatBarsCount;
If(AvgAmplitude < AvgAmplitudeThreshold &&
Abs(Close - EMA2)/Close < Price_EMA2_Threshold)
{
MarketFlat = True;
}
}
If(UseVolumeFilter && CurrentBar > 10)
{
AvgVolume = Average(Vol[1], 10);
VolumeOK = Vol[1] > AvgVolume * VolumeRatio;
}
Else If(!UseVolumeFilter)
{
VolumeOK = True;
}
Else
{
VolumeOK = False;
}
AboveEMA1 = Close[1] > EMA1[1];
BelowEMA1 = Close[1] < EMA1[1];
LongSignal = (EMA3[1] > EMA3[2] && EMA2[1] > EMA2[2]) &&
Close[1] > EMA2[1];
ShortSignal = (EMA3[1] < EMA3[2] && EMA2[1] < EMA2[2]) &&
Close[1] < EMA2[1];
CanOpenLong = !MarketFlat &&
VolumeOK &&
AboveEMA1 &&
LongSignal &&
Open > EMA2[1] &&
(Open-Close[1]) / Close[1] < GapPercent &&
MarketPosition == 0 &&
SelfPosition == 0 &&
!PositionLock &&
CandleFilterOK;
CanOpenShort = !MarketFlat &&
VolumeOK &&
BelowEMA1 &&
ShortSignal &&
Open < EMA2[1] &&
(Close[1]-Open) / Close[1] < GapPercent &&
MarketPosition == 0 &&
SelfPosition == 0 &&
!PositionLock &&
CandleFilterOK;
If(SelfPosition == 1 && EntryPrice > 0)
{
If(High > HighestPrice || HighestPrice == 0)
{
HighestPrice = High;
}
If(Low < LowestPrice || LowestPrice == 0)
{
LowestPrice = Low;
}
CurrentProfitRate = (Close - EntryPrice) / EntryPrice;
CurrentLossPoints = EntryPrice - LowestPrice;
MaxFavorablePoints = HighestPrice - EntryPrice;
}
Else If(SelfPosition == -1 && EntryPrice > 0)
{
If(High > HighestPrice || HighestPrice == 0)
{
HighestPrice = High;
}
If(Low < LowestPrice || LowestPrice == 0)
{
LowestPrice = Low;
}
CurrentProfitRate = (EntryPrice - Close) / EntryPrice;
CurrentLossPoints = HighestPrice - EntryPrice;
MaxFavorablePoints = EntryPrice - LowestPrice;
}
If(SelfPosition == 1)
{
If(CurrentLossPoints >= StopLossPoints)
{
ForceClose_SL = True;
}
Else If(Close[1] < EMA4[1])
{
ForceClose_EMA = True;
}
Else If(BelowEMA1 && ShortSignal)
{
ForceClose_Signal = True;
}
Else If(!ForceClose && UseProfitReduce && !ReducedPosition &&
MaxFavorablePoints >= EntryPrice * ProfitReduceRatio)
{
If(OriginalPosition == 0)
{
OriginalPosition = FixedPosition;
}
Numeric ReduceQty = IntPart(FixedPosition / 2);
If(ReduceQty > 0)
{
Sell(ReduceQty, 0);
ReducedPosition = True;
BreakevenSet = True;
LastOrderBar = CurrentBar;
}
}
Else If(ReducedPosition && BreakevenSet &&
CurrentProfitRate <= BreakevenThreshold)
{
ForceClose_Breakeven = True;
}
}
Else If(SelfPosition == -1)
{
If(CurrentLossPoints >= StopLossPoints)
{
ForceClose_SL = True;
}
Else If(Close[1] > EMA4[1])
{
ForceClose_EMA = True;
}
Else If(AboveEMA1 && LongSignal)
{
ForceClose_Signal = True;
}
Else If(!ForceClose && UseProfitReduce && !ReducedPosition &&
MaxFavorablePoints >= EntryPrice * ProfitReduceRatio)
{
If(OriginalPosition == 0)
{
OriginalPosition = FixedPosition;
}
Numeric ReduceQty = IntPart(FixedPosition / 2);
If(ReduceQty > 0)
{
BuyToCover(ReduceQty, 0);
ReducedPosition = True;
BreakevenSet = True;
LastOrderBar = CurrentBar;
}
}
Else If(ReducedPosition && BreakevenSet &&
CurrentProfitRate <= BreakevenThreshold)
{
ForceClose_Breakeven = True;
}
}
ForceClose = ForceClose_SL || ForceClose_EMA || ForceClose_Signal || ForceClose_Breakeven;
If((MarketPosition == 1 || SelfPosition == 1) && ForceClose)
{
Sell(0, 0);
SelfPosition = 0;
PositionLock = False;
LastOrderBar = CurrentBar;
JustClosedFlag = True;
ClosedBar = CurrentBar;
EntryPrice = 0;
EntryBar = 0;
ReducedPosition = False;
OriginalPosition = 0;
BreakevenSet = False;
HighestPrice = 0;
LowestPrice = 999999;
MaxFavorablePoints = 0;
CurrentProfitRate = 0;
CurrentLossPoints = 0;
}
Else If((MarketPosition == -1 || SelfPosition == -1) && ForceClose)
{
BuyToCover(0, 0);
SelfPosition = 0;
PositionLock = False;
LastOrderBar = CurrentBar;
JustClosedFlag = True;
ClosedBar = CurrentBar;
EntryPrice = 0;
EntryBar = 0;
ReducedPosition = False;
OriginalPosition = 0;
BreakevenSet = False;
HighestPrice = 0;
LowestPrice = 999999;
MaxFavorablePoints = 0;
CurrentProfitRate = 0;
CurrentLossPoints = 0;
}
If(MarketPosition == 0 && SelfPosition == 0 && !PositionLock && AllowNewOrder && !JustClosedFlag)
{
If(CanOpenLong)
{
Buy(FixedPosition, Open);
SelfPosition = 1;
PositionLock = True;
EntryPrice = Open;
EntryBar = CurrentBar;
ReducedPosition = False;
OriginalPosition = FixedPosition;
BreakevenSet = False;
HighestPrice = Open;
LowestPrice = Open;
LastOrderBar = CurrentBar;
TodayOrderCount = TodayOrderCount + 1;
}
Else If(CanOpenShort)
{
SellShort(FixedPosition, Open);
SelfPosition = -1;
PositionLock = True;
EntryPrice = Open;
EntryBar = CurrentBar;
ReducedPosition = False;
OriginalPosition = FixedPosition;
BreakevenSet = False;
HighestPrice = Open;
LowestPrice = Open;
LastOrderBar = CurrentBar;
TodayOrderCount = TodayOrderCount + 1;
}
}
}