Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #property copyright "2024, (c)hyrolean"
- #property link "https://pastebin.com/ADhjs5D1"
- #property version "1.12"
- #property strict
- #include <stdlib.mqh>
- // 3EMA https://youtu.be/GsAAMgKXzic
- #define ENTRY_NAME "3MAPyramid"
- enum ENUM_POSI {
- POSI_STOP, // Stop
- POSI_ONLY_LONG, // Only Long
- POSI_ONLY_SHORT, // Only Short
- POSI_HALF_LONG_AND_SHORT, // Long & Short (Half duplex)
- POSI_FULL_LONG_AND_SHORT // Long & Short (Full duplex)
- };
- enum ENUM_TIMEBASE {
- TIMEBASE_GMT, // Greenwich Mean Time (GMT)
- TIMEBASE_LOCAL, // Local Time
- TIMEBASE_SERVER // Server Time
- };
- enum ENUM_TIMEACT {
- TIMEACT_NONE, // None ( EA closes positions automatically )
- TIMEACT_FORCE_CLOSE_ALL, // Force Close All positions
- TIMEACT_FORCE_CLOSE_LONG, // Force Close Long positions
- TIMEACT_FORCE_CLOSE_SHORT, // Force Close Short positions
- TIMEACT_SOFT_CLOSE_ALL, // Close All positions if profits are Positive
- TIMEACT_SOFT_CLOSE_LONG, // Close Long positions if profits are Positive
- TIMEACT_SOFT_CLOSE_SHORT // Close Short positions if profits are Positive
- };
- input ENUM_POSI ActivePositions = POSI_HALF_LONG_AND_SHORT; // Active Entry Positions
- input ENUM_TIMEFRAMES MainTimeFrame = PERIOD_M5; // Main Time Frame
- input int MAGICMA = 35835; // Magic Number
- input bool TimeControl = false; // Time Control
- input ENUM_TIMEBASE TimeBase = TIMEBASE_LOCAL; // Time Base
- input string TimeStart = "09:00"; // Time Start
- input string TimeEnd = "15:00"; // Time End
- input ENUM_TIMEACT TimeAction = TIMEACT_NONE; // Time Action when time end reached
- input int Slippage = 10; // Max slippage
- input int Spread = 50; // Max spread in points
- input double BaseLots = 0.02; // Base lots
- input double MinLots = 0.01; // Minimum lots
- input double MaxLots = 100.0; // Maximum lots
- input double ProfitTotalLots = 1.00; // Profit Taking total lots
- input double ProfitRatePer = 33.3; // Profit Rate in percentage
- input int ProfitKeepTL = 3; // Profit keeping TL(TimeLimited) period
- input bool EntryTLPos = true; // Entry TL(TimeLimited) positions
- input bool EntryFastMAPos = true; // Entry Fast MA positions
- input bool EntryMediumMAPos= true; // Entry Medium MA positions
- input ENUM_MA_METHOD MAMode= MODE_EMA;// MA mode
- input ENUM_APPLIED_PRICE MAPriceType = PRICE_CLOSE; // MA price type
- input int FastMAPeriod = 10; // Fast MA period
- input int MediumMAPeriod = 20; // Medium MA period
- input int SlowMAPeriod = 50; // Slow MA period
- input bool ReferSlowMA = false; // Refer Slow MA
- input double Takeprofit = 540; // Take profit in points
- input double Stoploss = 360; // Stop loss in points
- input double PyramidingStride= 80.0; // Pyramiding price Stride in points
- input double PyramidingScale = 1.0; // Pyramiding lots Multiplier
- input int PyramidingTimes = 30; // Pyramiding max Positions (0=infinite)
- input int PyramidingInterval=0; // Pyramiding Interval in sec (0=continuous)
- input bool Averaging = false; // Averaging enabled (averaging down and martingale)
- input int AveragingTimes = 20; // Averaging max Positions (0=infinite)
- input double AveragingScale = 1.0; // Averaging lots Multiplier
- input bool Offsetting = true; // Offsetting Enabled (divergence entriable)
- input int OffsettingExpireMinutes=0; // Offsetting Order Expire minutes (0=unlimited)
- input double OffsettingDvgnScale=0.1; // Offsetting Divergence lots Multiplier
- input bool Trailing = false; // Trailing Enabled
- input double TrailingStart = 100; // Trailing Start in points
- input double TrailingPadding = 50; // Trailing Padding in points
- input bool Scalping = false; // Scalping Enabled
- input double ScalpingProfit = 500; // Scalping Border of Gross Profit (0.0=n/a)
- input double ScalpingLoss = -1000; // Scalping Border of Gross Loss (0.0=n/a)
- input int ScalpingInterval= 5; // Scalping Interval in sec (0=continuous)
- input bool ScalpingIgnoreTL= false; // Scalping also after TL(TimeLimited) reached
- input group "Appearance Settings"
- input bool ShowUserEntry = true; // Show user entry SELL/BUY buttons
- input bool ShowCloseAll = true; // Show a CLOSE ALL button
- input bool ShowCloseLong = false; // Show a CLOSE LONG button
- input bool ShowCloseShort = false; // Show a CLOSE SHORT button
- input bool ShowAmount = true; // Show Current Amount
- input int AmountDig = 0; // Amount Number of decimal places
- input group "Color Settings"
- input color ClrAmountPosi = clrLightGoldenrod; // Amount Positive color
- input color ClrAmountNega = clrLightPink; // Amount Negative color
- input color ClrTimeControl = clrYellow; // Time Control Status color
- input color ClrLongBorder = clrDeepSkyBlue; // Long Border color
- input color ClrShortBorder = clrViolet; // Short Border color
- input color ClrTrailBorder = clrLime; // Trailing Border color
- input color ClrLongArrow = clrBlue; // Long Arrow color
- input color ClrShortArrow = clrRed; // Short Arrow color
- input group "DEBUG Setting"
- input bool DBGMODE = true; // DEBUG MODE
- double Lots, PrevBid, PrevAsk;
- #define MAShift 0
- bool PmdTiming=false;
- double PmdPrevBid, PmdPrevAsk;
- datetime CurTime, CurPmdInt, CurSclpInt, TimeTick, StartTime, CancelTime, UserTime;
- int BuyKeepTimer=0, SellKeepTimer=0, BuyLosscutTimer=0, SellLosscutTimer=0;
- bool BuyTLEntried=false, BuyFastMAEntried=false, BuyMediumMAEntried=false;
- bool SellTLEntried=false, SellFastMAEntried=false, SellMediumMAEntried=false;
- #define ORDER_RETRY 10
- #define FLAG_BUY 1
- #define FLAG_SELL 2
- #define FLAG_DUPLEX 4
- int PositionFlag = FLAG_BUY | FLAG_SELL | FLAG_DUPLEX ;
- int UserEntry = 0 ;
- #define SELLBTN_NAME "EntrySell"
- #define BUYBTN_NAME "EntryBuy"
- #define CLOSEALLBTN_NAME "CloseAll"
- #define CLOSELONGBTN_NAME "CloseLong"
- #define CLOSESHORTBTN_NAME "CloseShort"
- #define BUYBORDER_NAME "LONG BORDER"
- #define SELLBORDER_NAME "SHORT BORDER"
- bool BuyBorderLined = false, SellBorderLined = false ;
- #define BUYTRAIL_NAME "LONG SL"
- #define SELLTRAIL_NAME "SHORT SL"
- bool BuyTrailLined = false, SellTrailLined = false ;
- #define OFFTIME_NAME "OFF TIME"
- bool OffTimeVisible = false ;
- #define AMOUNT_NAME "AMOUNT"
- #define AMOUNT_CLR_NEGA ClrAmountNega
- #define AMOUNT_CLR_POSI ClrAmountPosi
- // BuyMaxPrice/SellMinPrice
- #define BUYMAXPRICE_NAME (ENTRY_NAME "_BuyMaxPrice_" +Symbol())
- #define SELLMINPRICE_NAME (ENTRY_NAME "_SellMinPrice_" +Symbol())
- double BuyMaxPrice, SellMinPrice ;
- // LossPrices
- #define LOSSPRICES_NAME (ENTRY_NAME "_LossPrices_" + Symbol())
- double LossPrices=0.0;
- #define DBGINFO_NAME "DEBUG INFO"
- //---------------------------------------------------------------------------
- //エラーログ出力
- void PrintLastError()
- {
- int lastError = GetLastError() ;
- printf(ENTRY_NAME"(%s): error(%d): %s",
- Symbol(),lastError,ErrorDescription(lastError));
- }
- //---------------------------------------------------------------------------
- //オブジェクトのソート
- // ( https://youtu.be/ZRPiwUNLjiA )
- #include <Arrays/ArrayObj.mqh>
- #define ARRAY_SORT_ASCEND 1
- #define ARRAY_SORT_DESCEND 2
- template <typename T>
- class CSortable : public CObject {
- public:
- T key;
- int Compare(const CObject *node, const int mode=0) const {
- if(mode<=0) return 0;
- CSortable *comp= (CSortable*)node ;
- bool f = key<comp.key ;
- if(!f&&!(comp.key<key)) return 0;
- int result = f ? -1:+1 ;
- switch(mode) {
- case ARRAY_SORT_ASCEND: return +result;
- case ARRAY_SORT_DESCEND: return -result;
- }
- return 0;
- }
- };
- template <typename T>
- void AddToArray(CArrayObj &array, const T& key) {
- CSortable<T> *node = new CSortable<T>();
- node.key=key;
- array.Add(node);
- }
- //---------------------------------------------------------------------------
- int OnInit()
- {
- //テスターで表示されるインジケータを非表示にする
- HideTestIndicators(true);
- CurTime = MainTime();
- CurPmdInt = CurSclpInt = TimeTick = CancelTime = StartTime = UserTime = BaseTime();
- Lots = BaseLots ; PrevBid = PmdPrevBid = Bid ; PrevAsk = PmdPrevAsk = Ask ;
- if(Lots<MinLots) Lots = MinLots ;
- if(Lots>MaxLots) Lots = MaxLots ;
- DeleteBorderLines() ;
- DrawBorderLine(OP_BUY);
- DrawBorderLine(OP_SELL);
- BuyTrailLined = ObjectFind(BUYTRAIL_NAME)>=0 ;
- SellTrailLined = ObjectFind(SELLTRAIL_NAME)>=0 ;
- BuyTLEntried=SellTLEntried=EntryTLPos;
- BuyFastMAEntried=SellFastMAEntried=EntryFastMAPos;
- BuyMediumMAEntried=SellMediumMAEntried=EntryMediumMAPos;
- // LossPrices 値読込
- if(!GlobalVariableGet(LOSSPRICES_NAME,LossPrices))
- LossPrices = 0.0;
- STATUS buyStatus, sellStatus ;
- CheckStatus(OP_BUY,MAGICMA,buyStatus);
- CheckStatus(OP_SELL,MAGICMA,sellStatus);
- // done : borderPrice を medianPrice に置換する
- if(buyStatus.Positions>0) {
- double totalLots = buyStatus.TotalLots ;
- double totalPrice = buyStatus.TotalPrices ;
- double borderPrice = buyStatus.BorderPrice ;
- double offsetPrice = Offsetting?-sellStatus.CurrentPrices:0;
- bool offs = Offsetting && offsetPrice>0 ;
- if(offs) {
- double medianPrice = buyStatus.MedianBorderPrice(sellStatus,LossPrices) ;
- if(medianPrice!=0.0) borderPrice = medianPrice;
- else borderPrice = (totalPrice+offsetPrice)/totalLots ;
- }
- //double profitPrice = buyStatus.ProfitPrice(borderPrice) ;
- BuyKeepTimer = CheckOverPriceTime(OP_BUY,borderPrice,buyStatus.MinOpenTime) ;
- if(ProfitKeepTL!=0&&BuyKeepTimer>=ProfitKeepTL) BuyTLEntried = false ;
- BuyMaxPrice = buyStatus.MaxPrice ;
- double price;
- if(GlobalVariableGet(BUYMAXPRICE_NAME,price)) {
- if(price>BuyMaxPrice) {
- BuyMaxPrice = price ;
- }
- GlobalVariableDel(BUYMAXPRICE_NAME);
- }
- }
- if(sellStatus.Positions>0) {
- double totalLots = sellStatus.TotalLots ;
- double totalPrice = sellStatus.TotalPrices ;
- double borderPrice = sellStatus.BorderPrice; ;
- double offsetPrice = Offsetting?-buyStatus.CurrentPrices:0;
- bool offs = Offsetting && offsetPrice>0 ;
- if(offs) {
- double medianPrice = sellStatus.MedianBorderPrice(buyStatus,LossPrices) ;
- if(medianPrice!=0.0) borderPrice = medianPrice;
- else borderPrice = (totalPrice-offsetPrice)/totalLots ;
- }
- //double profitPrice = sellStatus.ProfitPrice(borderPrice) ;
- SellKeepTimer = CheckOverPriceTime(OP_SELL,borderPrice,sellStatus.MinOpenTime) ;
- if(ProfitKeepTL!=0&&SellKeepTimer>=ProfitKeepTL) SellTLEntried = false ;
- SellMinPrice = sellStatus.MinPrice ;
- double price;
- if(GlobalVariableGet(SELLMINPRICE_NAME,price)) {
- if(price<SellMinPrice) {
- SellMinPrice = price ;
- }
- GlobalVariableDel(SELLMINPRICE_NAME);
- }
- }
- // エントリできるポジションの確認
- switch(ActivePositions) {
- case POSI_STOP: // Stop
- PositionFlag = 0 ;
- break;
- case POSI_ONLY_LONG: // Only Long
- PositionFlag = FLAG_BUY ;
- break;
- case POSI_ONLY_SHORT: // Only Short
- PositionFlag = FLAG_SELL ;
- break;
- case POSI_HALF_LONG_AND_SHORT: // Long & Short (Half Duplex)
- PositionFlag = FLAG_BUY | FLAG_SELL ;
- break;
- case POSI_FULL_LONG_AND_SHORT: // Long & Short (Full Duplex)
- PositionFlag = FLAG_BUY | FLAG_SELL | FLAG_DUPLEX ;
- break;
- }
- //DEBUG INFO
- if(DBGMODE) {
- ObjectCreate(DBGINFO_NAME, OBJ_LABEL, 0, 0, 0);
- ObjectSet(DBGINFO_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSet(DBGINFO_NAME, OBJPROP_YDISTANCE, 15);
- ObjectSet(DBGINFO_NAME, OBJPROP_CORNER, 3);
- ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, "DEBUG INFO");
- ObjectSetString(0, DBGINFO_NAME, OBJPROP_FONT, "Verdana");
- ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_FONTSIZE, 8);
- ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_COLOR, clrAquamarine);
- }
- //金額表示
- if(ShowAmount) {
- ObjectCreate(AMOUNT_NAME, OBJ_LABEL, 0, 0, 0);
- ObjectSet(AMOUNT_NAME, OBJPROP_XDISTANCE, 20);
- ObjectSet(AMOUNT_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSet(AMOUNT_NAME, OBJPROP_CORNER, 3);
- ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, "0-");
- ObjectSetString(0, AMOUNT_NAME, OBJPROP_FONT, "Verdana");
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_FONTSIZE, 15);
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
- }
- //ユーザーエントリ用ボタン
- if(ShowUserEntry) {
- //SELLボタン
- ObjectCreate(SELLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSet(SELLBTN_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSet(SELLBTN_NAME, OBJPROP_YDISTANCE, 20);
- ObjectSet(SELLBTN_NAME, OBJPROP_XSIZE, 58);
- ObjectSet(SELLBTN_NAME, OBJPROP_YSIZE, 32);
- ObjectSet(SELLBTN_NAME, OBJPROP_CORNER, 0);
- ObjectSet(SELLBTN_NAME, OBJPROP_FONTSIZE, 12);
- ObjectSet(SELLBTN_NAME, OBJPROP_COLOR, White);
- ObjectSet(SELLBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
- ObjectSetString(0, SELLBTN_NAME, OBJPROP_TEXT, "SELL");
- ObjectSetString(0, SELLBTN_NAME, OBJPROP_FONT, "Verdana");
- //BUYボタン
- ObjectCreate(BUYBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSet(BUYBTN_NAME, OBJPROP_XDISTANCE, 70);
- ObjectSet(BUYBTN_NAME, OBJPROP_YDISTANCE, 20);
- ObjectSet(BUYBTN_NAME, OBJPROP_XSIZE, 58);
- ObjectSet(BUYBTN_NAME, OBJPROP_YSIZE, 32);
- ObjectSet(BUYBTN_NAME, OBJPROP_CORNER, 0);
- ObjectSet(BUYBTN_NAME, OBJPROP_FONTSIZE, 12);
- ObjectSet(BUYBTN_NAME, OBJPROP_COLOR, White);
- ObjectSet(BUYBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
- ObjectSetString(0, BUYBTN_NAME, OBJPROP_TEXT, "BUY");
- ObjectSetString(0, BUYBTN_NAME, OBJPROP_FONT, "Verdana");
- }
- int btn_ofs_x = 0 ;
- const int btn_distance = 102 ;
- //全決済ボタン
- if(ShowCloseAll) {
- ObjectCreate(CLOSEALLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_CORNER, 2);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_COLOR, White);
- ObjectSet(CLOSEALLBTN_NAME, OBJPROP_BGCOLOR, /*clrDarkGreen*/clrDarkSlateGray);
- ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_TEXT, "CLOSE ALL");
- ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_FONT, "Verdana");
- btn_ofs_x += btn_distance ;
- }
- //LONG決済ボタン
- if(ShowCloseLong) {
- ObjectCreate(CLOSELONGBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_CORNER, 2);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_COLOR, White);
- ObjectSet(CLOSELONGBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
- ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_TEXT, "CLOSE LONG");
- ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_FONT, "Verdana");
- btn_ofs_x += btn_distance ;
- }
- //SHORT決済ボタン
- if(ShowCloseShort) {
- ObjectCreate(CLOSESHORTBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_CORNER, 2);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_COLOR, White);
- ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
- ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_TEXT, "CLOSE SHORT");
- ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_FONT, "Verdana");
- btn_ofs_x += btn_distance ;
- }
- //ユーザーエントリをリセット
- UserEntry=0;
- return(INIT_SUCCEEDED);
- }
- //---------------------------------------------------------------------------
- void OnDeinit(const int reason)
- {
- int flag = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA);
- if(flag!=0) {
- if((flag&FLAG_BUY)!=0) GlobalVariableSet(BUYMAXPRICE_NAME,BuyMaxPrice);
- if((flag&FLAG_SELL)!=0) GlobalVariableSet(SELLMINPRICE_NAME,SellMinPrice);
- }
- if(ShowCloseShort) ObjectDelete(CLOSESHORTBTN_NAME) ;
- if(ShowCloseLong) ObjectDelete(CLOSELONGBTN_NAME) ;
- if(ShowCloseAll) ObjectDelete(CLOSEALLBTN_NAME) ;
- if(ShowUserEntry) {
- ObjectDelete(BUYBTN_NAME) ;
- ObjectDelete(SELLBTN_NAME) ;
- }
- if(OffTimeVisible) {
- ObjectDelete(OFFTIME_NAME) ;
- OffTimeVisible=false ;
- }
- if(ShowAmount) {
- ObjectDelete(AMOUNT_NAME) ;
- }
- if(DBGMODE) {
- ObjectDelete(DBGINFO_NAME) ;
- }
- DeleteBorderLines() ;
- }
- //---------------------------------------------------------------------------
- void OnTick()
- {
- datetime nextTime = MainTime() ;
- bool nextTimed = nextTime != CurTime ;
- CurTime = nextTime ;
- datetime nextTick = BaseTime() ;
- bool nextTicked = nextTick != TimeTick ;
- TimeTick = nextTick;
- // タイムコントロールチェック
- CheckTimeControl(nextTicked);
- // 動作チェック
- CheckBehavior(nextTimed);
- double atr14 = iATR(NULL,0,14,0) ;
- double spread = Ask-Bid ;
- // デバッグ欄表示のサンプル
- if(DBGMODE) {
- DBGOUT(
- // ATR in points
- StringFormat("ATR(14): %.3f",atr14/Point) + " | " +
- // SPREAD in points
- StringFormat("SPREAD: %g",spread/Point) + " | " +
- // 現在の値幅の変動倍率(ATR/SPREAD)
- StringFormat("ATR(14)/SPREAD: %.3f",atr14/(spread<=0?1:spread))
- );
- }
- // エントリー処理
- if(IsExpertEnabled()&&IsTradeAllowed()) {
- int busy = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA) ;
- if(ReferSlowMA) { // Slow MA の位置によりビジー状態を設定する
- double SlowMA0 = iMA(NULL, MainTimeFrame, SlowMAPeriod, MAShift, MAMode, MAPriceType, 0);
- double HalfSpread = (Ask-Bid)/2.0;
- SlowMA0+=HalfSpread ;
- if(Ask<SlowMA0) busy |= FLAG_BUY ;
- if(Bid>SlowMA0) busy |= FLAG_SELL ;
- }
- /*
- if(RSIPredict) { // RSI による売買制限
- if(RSIUpBuyLimit<RSI0||RSIDownBuyLimit>RSI0) busy |= FLAG_BUY ;
- if(RSIUpSellLimit<RSI0||RSIDownSellLimit>RSI0) busy |= FLAG_SELL ;
- }
- */
- // ユーザーの注文
- if(UserEntry) {
- // ユーザーのエントリを確認
- if(TimeTick-UserTime<60) { // 発行されてから60秒以内の注文
- int user = UserEntry ;
- // 注文
- if(user&&!AlreadyOrdered(user,MAGICMA)) {
- int entry = user == FLAG_BUY ? OP_BUY : OP_SELL ;
- EntryPosition("USER", entry, Lots);
- busy |= user ;
- }
- }
- UserEntry=0;
- }
- // MARK: 自動注文
- do {
- // 自動注文 開始時間調整
- if(StartTime>TimeTick||CancelTime>TimeTick)
- break ;
- // 自動注文 MA RSI Cross Detector
- if(MARSIXDetector)
- EAEntryPosition("MARSIX", CheckDetectorMARSIX(), busy);
- // 自動注文 2MM Detector
- if(MMX2Detector && nextTimed)
- EAEntryPosition("2MM", CheckDetectorMMX2(1),busy) ;
- // 自動注文 COBRA Detector
- if(COBRADetector && nextTimed)
- EAEntryPosition("COBRA", CheckDetectorCOBRA(1),busy) ;
- // 自動注文 GXRSI Detector
- if(GXRSIDetector && nextTimed)
- EAEntryPosition("GXRSI", CheckDetectorGXRSI(1),busy) ;
- }while(0);
- }else {
- if(StartTime-TimeTick<10)
- StartTime = TimeTick+10 ;
- }
- if(PmdTiming) {
- PmdPrevBid = (PmdPrevBid+Bid)/2.0 ; PmdPrevAsk = (PmdPrevAsk+Ask)/2.0 ;
- }
- PrevBid = Bid ; PrevAsk = Ask ;
- }
- //---------------------------------------------------------------------------
- void OnChartEvent(
- const int id,
- const long &lparam,
- const double &dparam,
- const string &sparam
- )
- {
- if( ( sparam == CLOSEALLBTN_NAME ||
- sparam == CLOSELONGBTN_NAME ||
- sparam == CLOSESHORTBTN_NAME ) && id==CHARTEVENT_OBJECT_CLICK) {
- int orderFlag = 0 ;
- if(sparam == CLOSEALLBTN_NAME) orderFlag = FLAG_SELL | FLAG_BUY ;
- else if(sparam == CLOSELONGBTN_NAME) orderFlag = FLAG_BUY ;
- else if(sparam == CLOSESHORTBTN_NAME) orderFlag = FLAG_SELL ;
- CheckoutOrderAll(orderFlag);
- Sleep(100);
- ObjectSet(sparam, OBJPROP_STATE, False);
- // 60秒エントリーを停止する
- CancelTime = TimeTick + 60 ;
- }
- if(sparam == SELLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
- { UserEntry = FLAG_SELL ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
- Sleep(100);
- ObjectSet(SELLBTN_NAME, OBJPROP_STATE, False);
- }
- if(sparam == BUYBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
- { UserEntry = FLAG_BUY ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
- Sleep(100);
- ObjectSet(BUYBTN_NAME, OBJPROP_STATE, False);
- }
- }
- //---------------------------------------------------------------------------
- //DBGOUT
- void DBGOUT(string text)
- {
- if(DBGMODE) {
- ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, text);
- }
- }
- //---------------------------------------------------------------------------
- //タイムコントロールチェック
- void CheckTimeControl(bool nextTicked)
- {
- if(!TimeControl) {
- if(OffTimeVisible) {
- ObjectDelete(OFFTIME_NAME);
- OffTimeVisible = false ;
- }
- return ;
- }
- if(!nextTicked) return ;
- datetime timStart = StringToTime(TimeStart);
- datetime timEnd = StringToTime(TimeEnd);
- MqlDateTime mqlTick, mqlStart, mqlEnd ;
- TimeToStruct(TimeTick, mqlTick);
- TimeToStruct(timStart, mqlStart);
- TimeToStruct(timEnd, mqlEnd);
- // 活動時間帯のチェック
- int ct = mqlTick.hour*60 + mqlTick.min ;
- int st = mqlStart.hour*60 + mqlStart.min ;
- int et = mqlEnd.hour*60 + mqlEnd.min ;
- if(et<=st) {
- if(st<=ct) et=24*60;
- if(ct<=et) st=0;
- }
- bool activeTime = st <= ct && ct <= et ;
- bool isActivated = StartTime<TimeTick ;
- // 現在活動時間帯
- if(activeTime) {
- if(!isActivated)
- StartTime = TimeTick ; // 現在時間を開始時間切り上げて完了
- if(OffTimeVisible) {
- ObjectDelete(OFFTIME_NAME);
- OffTimeVisible = false ;
- }
- return ;
- }
- // 活動時間を次の時間にセットする
- MqlDateTime mqlNextStart = mqlTick ;
- mqlNextStart.hour = mqlStart.hour ;
- mqlNextStart.min = mqlStart.min ;
- mqlNextStart.sec = 0 ;
- datetime timNextStart = StructToTime(mqlNextStart) ;
- while(timNextStart<TimeTick) timNextStart += 24*60*60 ;
- StartTime = timNextStart ;
- // 次の開始までの秒数
- datetime timOff = StartTime - TimeTick ;
- if(!OffTimeVisible) {
- // OFF TIME テキストを表示
- ObjectCreate(OFFTIME_NAME, OBJ_LABEL, 0, 0, 0);
- ObjectSet(OFFTIME_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSet(OFFTIME_NAME, OBJPROP_YDISTANCE, 25);
- ObjectSet(OFFTIME_NAME, OBJPROP_CORNER, 1);
- ObjectSetString(0, OFFTIME_NAME, OBJPROP_TEXT, "OFF TIME");
- ObjectSetString(0, OFFTIME_NAME, OBJPROP_FONT, "Verdana");
- ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_FONTSIZE, 8);
- ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_COLOR, ClrTimeControl);
- OffTimeVisible = true ;
- }
- int orderFlag = AlreadyOrdered(FLAG_SELL|FLAG_BUY,MAGICMA);
- switch(TimeAction) {
- case TIMEACT_NONE:
- // None
- break;
- case TIMEACT_FORCE_CLOSE_ALL:
- // Force Close All positions
- if(orderFlag!=0)
- CheckoutOrderAll(orderFlag);
- break;
- case TIMEACT_FORCE_CLOSE_LONG:
- // Force Close Long positions
- if((orderFlag&FLAG_BUY)!=0)
- CheckoutOrderAll(FLAG_BUY);
- break;
- case TIMEACT_FORCE_CLOSE_SHORT:
- // Force Close Short positions
- if((orderFlag&FLAG_SELL)!=0)
- CheckoutOrderAll(FLAG_SELL);
- break;
- case TIMEACT_SOFT_CLOSE_ALL:
- // Close All positions if profits are Positive
- if(orderFlag!=0) {
- STATUS status_long, status_short;
- CheckStatus(OP_BUY,MAGICMA,status_long);
- CheckStatus(OP_SELL,MAGICMA,status_short);
- double total = status_long.GrossProfit+status_short.GrossProfit ;
- if(total>0) {
- CheckoutOrderAll(orderFlag);
- }
- }
- break;
- case TIMEACT_SOFT_CLOSE_LONG:
- // Close Long positions if profits are Positive
- if((orderFlag&FLAG_BUY)!=0) {
- STATUS status_long;
- CheckStatus(OP_BUY,MAGICMA,status_long);
- double total=status_long.GrossProfit;
- if(total>0) {
- CheckoutOrderAll(FLAG_BUY);
- }
- }
- break;
- case TIMEACT_SOFT_CLOSE_SHORT:
- // Close Short positions if profits are Positive
- if((orderFlag&FLAG_SELL)!=0) {
- STATUS status_short;
- CheckStatus(OP_SELL,MAGICMA,status_short);
- double total=status_short.GrossProfit;
- if(total>0) {
- CheckoutOrderAll(FLAG_SELL);
- }
- }
- break;
- }
- }
- //---------------------------------------------------------------------------
- //メインタイムを返す
- datetime MainTime(int shift=0)
- {
- return iTime(Symbol(), MainTimeFrame, shift);
- }
- //---------------------------------------------------------------------------
- //タイムコントロールの基軸時間を返す
- datetime BaseTime()
- {
- switch(TimeBase) {
- case TIMEBASE_GMT: // Greenwich Mean Time (GMT)
- return TimeGMT();
- case TIMEBASE_LOCAL: // Local Time
- return TimeLocal();
- case TIMEBASE_SERVER: // Server Time
- return TimeCurrent();
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- //price超えの時間経過を調べる
- int CheckOverPriceTime(int type, double border, datetime minTime)
- {
- double spread = Ask-Bid ;
- bool buy = false ;
- switch(type) {
- case OP_BUY: buy=true; break;
- case OP_SELL: buy=false; break;
- default: return 0 ;
- }
- int numBars = iBars(Symbol(),MainTimeFrame);
- int times=0;
- for(int i=0;i<numBars;i++) {
- if(MainTime(i)<=minTime) break;
- if(buy?
- border>=iOpen(Symbol(),MainTimeFrame,i):
- border+spread<=iOpen(Symbol(),MainTimeFrame,i)) break;
- times++;
- }
- return times;
- }
- //---------------------------------------------------------------------------
- //金額表示の更新
- void UpdateAmount(double amount, int positions)
- {
- if(ShowAmount) {
- if(positions>0) {
- string s = DoubleToAmount(amount,AmountDig) ;
- if(amount>0) s = "+" + s ;
- ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s);
- if(amount<0)
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_NEGA);
- else
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
- }else {
- string s = ObjectGetString(0, AMOUNT_NAME, OBJPROP_TEXT);
- int ln=StringLen(s);
- if(ln>0) {
- if(s[ln-1]!='-')
- ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s+"-");
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- //状態チェック
- //-----
- struct ORDER_STATUS {
- int Ticket;
- double Price;
- double Stoploss;
- double Takeprofit;
- double Lots;
- double Profit;
- datetime OpenTime;
- string Comment;
- //-----
- ORDER_STATUS() {
- Ticket = -1 ;
- Price = Stoploss = Takeprofit = Lots = Profit = 0.0 ;
- OpenTime = 0 ;
- Comment = "" ;
- }
- ORDER_STATUS(
- int Ticket_,
- double Price_,
- double Stoploss_,
- double Takeprofit_,
- double Lots_,
- double Profit_,
- datetime OpenTime_,
- string Comment_ ) {
- Ticket = Ticket_;
- Price = Price_;
- Stoploss = Stoploss_;
- Takeprofit = Takeprofit_;
- Lots = Lots_;
- Profit = Profit_;
- OpenTime = OpenTime_;
- Comment = Comment_;
- }
- bool operator <(const ORDER_STATUS &rhs) const {
- return Price<rhs.Price;
- }
- };
- //-----
- struct STATUS {
- int Type, Magic;
- int Positions, PyramidPositions, AveragePositions;
- double MinPrice, MaxPrice, BorderPrice;
- double MinPriceLots, MaxPriceLots;
- double MinPriceProfit, MaxPriceProfit;
- double MinPriceStoploss, MaxPriceStoploss;
- int MinPriceTicket, MaxPriceTicket;
- double MinStoploss, MaxStoploss;
- double MinTakeprofit, MaxTakeprofit;
- double MinLots, MaxLots;
- datetime MinOpenTime, MaxOpenTime;
- double PyramidMinLots, PyramidMaxLots;
- double AverageMinLots, AverageMaxLots;
- double TotalPrices, TotalLots;
- double CurrentPrices, MedianPrices;
- double GrossProfit;
- double PositiveProfit;
- CArrayObj *Orders;
- STATUS() {
- Orders = new CArrayObj();
- }
- ~STATUS() {
- delete Orders;
- }
- void Check(int type, int magic) {
- Type=type;
- Magic=magic;
- Positions = 0 ;
- PyramidPositions = 0 ;
- AveragePositions = 0 ;
- MinPrice = DBL_MAX ;
- MaxPrice = 0.0 ;
- MinPriceLots = 0.0 ;
- MaxPriceLots = 0.0 ;
- MinPriceProfit = 0.0 ;
- MaxPriceProfit = 0.0 ;
- MinPriceStoploss = 0.0 ;
- MaxPriceStoploss = 0.0 ;
- MinPriceTicket = 0 ;
- MaxPriceTicket = 0 ;
- MinStoploss = DBL_MAX ;
- MaxStoploss = 0.0 ;
- MinTakeprofit = DBL_MAX ;
- MaxTakeprofit = 0.0 ;
- MinLots = DBL_MAX ;
- MaxLots = 0.0 ;
- MinOpenTime = TimeCurrent() ;
- MaxOpenTime = 0 ;
- PyramidMinLots = DBL_MAX ;
- PyramidMaxLots = 0.0 ;
- AverageMinLots = DBL_MAX ;
- AverageMaxLots = 0.0 ;
- BorderPrice = 0.0 ;
- GrossProfit = 0.0 ;
- PositiveProfit = 0.0 ;
- CurrentPrices = 0.0 ;
- MedianPrices = 0.0 ;
- Orders.Clear();
- double halfSpread = (Ask-Bid)/2.0;
- double totalPrice=0, totalLots=0 ;
- for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
- if( OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() ) {
- if(magic==OrderMagicNumber()) {
- if(type==OrderType()) {
- int orderTicket = OrderTicket() ;
- double orderPrice = OrderOpenPrice();
- double orderStoploss = OrderStopLoss();
- double orderTakeprofit = OrderTakeProfit();
- double orderLots = OrderLots();
- double orderProfit = OrderProfit() ;
- datetime orderOpenTime = OrderOpenTime() ;
- string orderComment = OrderComment();
- AddToArray(Orders, ORDER_STATUS(
- orderTicket,
- orderPrice,
- orderStoploss,
- orderTakeprofit,
- orderLots,
- orderProfit,
- orderOpenTime,
- orderComment )
- );
- GrossProfit += orderProfit;
- if(orderProfit>0.0)
- PositiveProfit += orderProfit;
- if(orderPrice<MinPrice) {
- MinPrice = orderPrice ;
- MinPriceLots = orderLots ;
- MinPriceProfit = orderProfit ;
- MinPriceStoploss = orderStoploss ;
- MinPriceTicket = orderTicket ;
- }
- if(orderPrice>MaxPrice) {
- MaxPrice = orderPrice ;
- MaxPriceLots = orderLots ;
- MaxPriceProfit = orderProfit ;
- MaxPriceStoploss = orderStoploss ;
- MaxPriceTicket = orderTicket ;
- }
- if(orderStoploss<MinStoploss) MinStoploss = orderStoploss;
- if(orderStoploss>MaxStoploss) MaxStoploss = orderStoploss;
- if(orderTakeprofit<MinTakeprofit) MinTakeprofit = orderTakeprofit;
- if(orderTakeprofit>MaxTakeprofit) MaxTakeprofit = orderTakeprofit;
- if(orderLots<MinLots) MinLots = orderLots;
- if(orderLots>MaxLots) MaxLots = orderLots;
- totalPrice += orderPrice*orderLots ;
- totalLots += orderLots;
- if(type==OP_BUY) {
- CurrentPrices += (Bid - orderPrice) * orderLots ;
- MedianPrices += (orderPrice + halfSpread) * orderLots ;
- }
- else if(type==OP_SELL) {
- CurrentPrices += (orderPrice - Ask) * orderLots ;
- MedianPrices += (orderPrice - halfSpread) * orderLots ;
- }
- if(MaxOpenTime<orderOpenTime) MaxOpenTime=orderOpenTime;
- if(MinOpenTime>orderOpenTime) MinOpenTime=orderOpenTime;
- if(StringFind(orderComment,"PRMD")>=0) {
- if(orderLots>PyramidMaxLots)
- PyramidMaxLots = orderLots ;
- if(orderLots<PyramidMinLots)
- PyramidMinLots = orderLots ;
- PyramidPositions++;
- }
- if(StringFind(orderComment,"AVRG")>=0) {
- if(orderLots>AverageMaxLots)
- AverageMaxLots = orderLots ;
- if(orderLots<AverageMinLots)
- AverageMinLots = orderLots ;
- AveragePositions++;
- }
- Positions++;
- }
- }
- }
- }
- Orders.Sort(ARRAY_SORT_ASCEND);
- if(!PyramidPositions) {
- PyramidMinLots = Lots ;
- PyramidMaxLots = Lots ;
- }
- if(!AveragePositions) {
- AverageMinLots = Lots ;
- AverageMaxLots = Lots ;
- }
- if(totalLots>0) {
- BorderPrice = totalPrice / totalLots ;
- }
- TotalPrices = totalPrice ;
- TotalLots = totalLots ;
- }
- double ProfitPrice(double borderPrice=0.0) const {
- if(borderPrice==0.0) borderPrice = BorderPrice;
- if(borderPrice>0.0) {
- //double stride = PyramidingStride * Point ;
- switch(Type) {
- case OP_BUY: {
- double bar = MathMax(MaxPrice,BuyMaxPrice)-borderPrice ;
- if(bar>0.0) {
- return bar * (ProfitRatePer / 100.0) + borderPrice ;
- }
- break;
- }
- case OP_SELL: {
- double bar = MathMin(MinPrice,SellMinPrice)-borderPrice ;
- if(bar<0.0) {
- return bar * (ProfitRatePer / 100.0) + borderPrice ;
- }
- break;
- }
- }
- }
- return borderPrice ;
- }
- double MedianBorderPrice(const STATUS &revStatus, double lossPrices=0.0) const
- {
- double medianLots = Type==OP_BUY ? TotalLots : -TotalLots ;
- medianLots += revStatus.Type==OP_BUY ? revStatus.TotalLots: -revStatus.TotalLots ;
- if(Type==OP_BUY?medianLots>0.0:medianLots<0.0) {
- double medianPrices = Type==OP_BUY ? MedianPrices-lossPrices : -MedianPrices+lossPrices ;
- medianPrices += revStatus.Type==OP_BUY ? revStatus.MedianPrices: -revStatus.MedianPrices ;
- double medianBorder = medianPrices/medianLots ;
- switch(Type) {
- case OP_BUY:
- medianBorder -= (Ask-Bid)/2.0;
- break;
- case OP_SELL:
- medianBorder += (Ask-Bid)/2.0;
- break;
- }
- return medianBorder ;
- }
- return 0.0;
- }
- };
- //-----
- int CheckStatus(int type, int magic, STATUS &status)
- {
- status.Check(type,magic);
- return status.Positions;
- }
- //---------------------------------------------------------------------------
- //動作チェック
- void CheckBehavior(bool nextTimed)
- {
- //最高価格/最低価格の更新
- bool lineUpdTiming = nextTimed ;
- if(Bid>BuyMaxPrice) {
- BuyMaxPrice = Bid ;
- BuyLosscutTimer = 0 ;
- lineUpdTiming = true ;
- }else if(nextTimed) {
- double o = iOpen(Symbol(),MainTimeFrame,1);
- double c = iClose(Symbol(),MainTimeFrame,1);
- if(o>c) BuyLosscutTimer++;
- }
- if(Ask<SellMinPrice) {
- SellMinPrice = Ask ;
- SellLosscutTimer = 0 ;
- lineUpdTiming = true ;
- }else if(nextTimed) {
- double o = iOpen(Symbol(),MainTimeFrame,1);
- double c = iClose(Symbol(),MainTimeFrame,1);
- if(o<c) SellLosscutTimer++;
- }
- // 全体のステータスを取得
- STATUS BuyWholeStatus, SellWholeStatus ;
- CheckStatus(OP_BUY, MAGICMA, BuyWholeStatus);
- CheckStatus(OP_SELL, MAGICMA, SellWholeStatus);
- // 損益の初期化
- if(!BuyWholeStatus.Positions&&!SellWholeStatus.Positions) {
- if(LossPrices!=0.0) {
- GlobalVariableDel(LOSSPRICES_NAME);
- LossPrices = 0.0 ;
- }
- }
- // 金額を更新
- double CurAmount = BuyWholeStatus.GrossProfit+SellWholeStatus.GrossProfit ;
- int CurPositions = BuyWholeStatus.Positions+SellWholeStatus.Positions ;
- UpdateAmount(CurAmount,CurPositions);
- if(Scalping) {
- // Sclp タイマー更新
- bool SclpTiming = false ;
- if(ScalpingInterval<=0) SclpTiming = true ;
- else {
- while(TimeTick-CurSclpInt>=ScalpingInterval) {
- CurSclpInt+=ScalpingInterval ;
- SclpTiming = true ;
- }
- }
- // スキャルピング
- if(SclpTiming&&CurPositions>0) {
- int flag = 0 ;
- if(Offsetting) {
- bool profitSatisfied = ProfitKeepTL>0 &&
- ( TL(OP_BUY)>=ProfitKeepTL || TL(OP_SELL)>=ProfitKeepTL ) ;
- if(ScalpingIgnoreTL || !profitSatisfied) {
- if( (ScalpingProfit!=0.0 && CurAmount>=ScalpingProfit) ||
- (ScalpingLoss!=0.0 && CurAmount<=ScalpingLoss) ) {
- flag |= FLAG_BUY|FLAG_SELL ;
- }
- }
- }else {
- if(BuyWholeStatus.Positions>0) {
- bool profitSatisfied = ProfitKeepTL>0 && TL(OP_BUY)>=ProfitKeepTL ;
- if(ScalpingIgnoreTL || !profitSatisfied) {
- if( (ScalpingProfit!=0.0 && BuyWholeStatus.GrossProfit>=ScalpingProfit) ||
- (ScalpingLoss!=0.0 && BuyWholeStatus.GrossProfit<=ScalpingLoss) ) {
- flag |= FLAG_BUY ;
- }
- }
- }
- if(SellWholeStatus.Positions>0) {
- bool profitSatisfied = ProfitKeepTL>0 && TL(OP_SELL)>=ProfitKeepTL ;
- if(ScalpingIgnoreTL || !profitSatisfied) {
- if( (ScalpingProfit!=0.0 && SellWholeStatus.GrossProfit>=ScalpingProfit) ||
- (ScalpingLoss!=0.0 && SellWholeStatus.GrossProfit<=ScalpingLoss) ) {
- flag |= FLAG_SELL ;
- }
- }
- }
- }
- if(flag!=0) {
- CheckoutOrderAll(flag);
- return; // 一旦、戻す
- }
- }
- }
- // Pmd タイマー更新
- PmdTiming = false ;
- if(PyramidingInterval<=0) PmdTiming = true ;
- else {
- while(TimeTick-CurPmdInt>=PyramidingInterval) {
- CurPmdInt+=PyramidingInterval ;
- PmdTiming = true ;
- }
- }
- // ボーダーライン更新
- if(!BuyWholeStatus.Positions) {
- if(BuyBorderLined) {
- ObjectDelete(BUYBORDER_NAME);
- BuyBorderLined=false;
- }
- }else if(lineUpdTiming||(Offsetting&&SellWholeStatus.Positions>0)) {
- DrawBorderLine(OP_BUY);
- }
- if(!SellWholeStatus.Positions) {
- if(SellBorderLined) {
- ObjectDelete(SELLBORDER_NAME);
- SellBorderLined=false;
- }
- }else if(lineUpdTiming||(Offsetting&&BuyWholeStatus.Positions>0)) {
- DrawBorderLine(OP_SELL);
- }
- // 不要なトレールラインを削除
- if(!BuyWholeStatus.Positions) TrailLine(OP_BUY);
- if(!SellWholeStatus.Positions) TrailLine(OP_SELL);
- // オーダーの処理
- ProcessOrders(nextTimed, OP_BUY, BuyWholeStatus, SellWholeStatus);
- ProcessOrders(nextTimed, OP_SELL, SellWholeStatus, BuyWholeStatus);
- // 損益の更新
- {
- double newLossPrices = 0.0 ;
- if(GlobalVariableGet(LOSSPRICES_NAME,newLossPrices)) {
- LossPrices = newLossPrices ;
- }
- }
- }
- //---------------------------------------------------------------------------
- //ボーダーラインを引く
- void DrawBorderLine(int orderType)
- {
- STATUS status;
- int pos = CheckStatus(orderType, MAGICMA, status);
- double borderPrice=status.BorderPrice;
- if(Offsetting) {
- // done : borderPrice を medianPrice に置換する
- STATUS revStatus;
- CheckStatus(orderType==OP_BUY?OP_SELL:OP_BUY, MAGICMA, revStatus);
- double medianPrice = status.MedianBorderPrice(revStatus,LossPrices);
- double offsetPrice = Offsetting?-revStatus.CurrentPrices:0;
- if(offsetPrice>0) {
- if(medianPrice!=0.0) borderPrice = medianPrice ;
- else if(pos>0) {
- double totalLots = status.TotalLots ;
- double totalPrice = status.TotalPrices ;
- if(orderType==OP_BUY) borderPrice = (totalPrice+offsetPrice)/totalLots ;
- else if(orderType==OP_SELL) borderPrice = (totalPrice-offsetPrice)/totalLots ;
- }
- }
- }
- double profitPrice = status.ProfitPrice(borderPrice) ;
- switch(orderType) {
- case OP_BUY:
- if(pos) {
- if(!BuyBorderLined) {
- ObjectCreate(BUYBORDER_NAME,OBJ_HLINE,0,0,profitPrice);
- BuyBorderLined = true ;
- }
- ObjectSet(BUYBORDER_NAME, OBJPROP_STYLE, STYLE_DOT);
- ObjectSet(BUYBORDER_NAME, OBJPROP_COLOR, ClrLongBorder);
- ObjectSet(BUYBORDER_NAME, OBJPROP_PRICE1, profitPrice);
- }else if(BuyBorderLined) {
- ObjectDelete(BUYBORDER_NAME);
- BuyBorderLined = false ;
- }
- break;
- case OP_SELL:
- if(pos) {
- if(!SellBorderLined) {
- ObjectCreate(SELLBORDER_NAME,OBJ_HLINE,0,0, profitPrice);
- SellBorderLined = true ;
- }
- ObjectSet(SELLBORDER_NAME, OBJPROP_STYLE, STYLE_DOT);
- ObjectSet(SELLBORDER_NAME, OBJPROP_COLOR, ClrShortBorder);
- ObjectSet(SELLBORDER_NAME, OBJPROP_PRICE1, profitPrice);
- }else if(SellBorderLined) {
- ObjectDelete(SELLBORDER_NAME);
- SellBorderLined = false ;
- }
- break;
- }
- }
- //---------------------------------------------------------------------------
- //ボーダーラインを消去
- void DeleteBorderLines()
- {
- if(BuyBorderLined) {
- ObjectDelete(BUYBORDER_NAME);
- BuyBorderLined = false ;
- }
- if(SellBorderLined) {
- ObjectDelete(SELLBORDER_NAME);
- SellBorderLined = false ;
- }
- }
- //---------------------------------------------------------------------------
- //トレールラインを引く
- void TrailLine(int orderType, double price=0.0)
- {
- switch(orderType) {
- case OP_BUY:
- if(price>0.0) {
- if(!BuyTrailLined) {
- ObjectCreate(BUYTRAIL_NAME,OBJ_HLINE,0,0, price);
- BuyTrailLined = true ;
- }
- ObjectSet(BUYTRAIL_NAME, OBJPROP_STYLE, STYLE_SOLID);
- ObjectSet(BUYTRAIL_NAME, OBJPROP_COLOR, ClrTrailBorder);
- ObjectSet(BUYTRAIL_NAME, OBJPROP_PRICE1, price);
- }else if(BuyTrailLined) {
- ObjectDelete(BUYTRAIL_NAME);
- BuyTrailLined = false ;
- }
- break;
- case OP_SELL:
- if(price>0.0) {
- if(!SellTrailLined) {
- ObjectCreate(SELLTRAIL_NAME,OBJ_HLINE,0,0, price);
- SellTrailLined = true ;
- }
- ObjectSet(SELLTRAIL_NAME, OBJPROP_STYLE, STYLE_SOLID);
- ObjectSet(SELLTRAIL_NAME, OBJPROP_COLOR, ClrTrailBorder);
- ObjectSet(SELLTRAIL_NAME, OBJPROP_PRICE1, price);
- }else if(SellTrailLined) {
- ObjectDelete(SELLTRAIL_NAME);
- SellTrailLined = false ;
- }
- break;
- }
- }
- //---------------------------------------------------------------------------
- //トレールの価格を取得
- double TrailPrice(int orderType)
- {
- switch(orderType) {
- case OP_BUY:
- if(BuyTrailLined) {
- return ObjectGet(BUYTRAIL_NAME, OBJPROP_PRICE1);
- }
- break;
- case OP_SELL:
- if(SellTrailLined) {
- return ObjectGet(SELLTRAIL_NAME, OBJPROP_PRICE1);
- }
- break;
- }
- return 0.0;
- }
- //---------------------------------------------------------------------------
- //MARK:オーダーの処理
- void ProcessOrders(bool nextTimed, int orderType, const STATUS &status, const STATUS &revStatus)
- {
- if(status.Positions<=0) return ;
- // done : borderPrice を medianPrice に置換する
- double totalLots = status.TotalLots ;
- double totalPrice = status.TotalPrices ;
- double borderPrice = status.BorderPrice ;
- double medianPrice = status.MedianBorderPrice(revStatus,LossPrices) ;
- double offsetPrice = Offsetting?-revStatus.CurrentPrices-LossPrices:0;
- bool offs = Offsetting && offsetPrice>0 ;
- if(offs) {
- if(medianPrice!=0.0) borderPrice = medianPrice;
- else if(orderType==OP_BUY) borderPrice = (totalPrice+offsetPrice)/totalLots ;
- else if(orderType==OP_SELL) borderPrice = (totalPrice-offsetPrice)/totalLots ;
- }
- double profitPrice = status.ProfitPrice(borderPrice) ;
- bool underPrice = false ;
- // Profit Time Limited タイマー更新
- bool profitSatisfied = orderType==OP_SELL?(profitPrice>Ask):(Bid>profitPrice) ;
- if(nextTimed) {
- if(ProfitKeepTL>0) {
- if(profitSatisfied)
- TL(orderType,1);
- else if(TL(orderType)<ProfitKeepTL)
- TLInit(orderType) ;
- }
- }
- /*
- if(offsetPrice>0&&profitSatisfied) {
- if(ProfitKeepTL>0)
- TL(orderType,ProfitKeepTL-TL(orderType));
- }
- */
- bool timeLimited =
- (ProfitKeepTL>0 && TL(orderType)>=ProfitKeepTL);
- int orderFlag=0, revOrderFlag=0, revOrderType=0;
- switch(orderType) {
- case OP_BUY:
- if(status.BorderPrice>Bid) underPrice = true;
- orderFlag = FLAG_BUY ;
- revOrderFlag = FLAG_SELL ;
- revOrderType = OP_SELL ;
- break;
- case OP_SELL:
- if(status.BorderPrice<Ask) underPrice = true;
- orderFlag = FLAG_SELL ;
- revOrderFlag = FLAG_BUY ;
- revOrderType = OP_BUY ;
- break;
- }
- if(underPrice) {
- bool losscut = false ;
- /*
- if(Offsetting&&OffsettingExpireMinutes>0) {
- if(revStatus.Positions>0) {
- losscut = TimeCurrent() - MathMax(status.MaxOpenTime,revStatus.MaxOpenTime) >= OffsettingExpireMinutes*60 ;
- }
- }
- */
- if(!losscut) {
- double deltaSl = Stoploss * Point ;
- if(deltaSl>0.0) {
- switch(orderType) {
- case OP_BUY:
- if(!Offsetting) {
- if(status.MinPrice-Bid>=deltaSl)
- losscut = true ;
- }
- break;
- case OP_SELL:
- if(!Offsetting) {
- if(Ask-status.MaxPrice>=deltaSl)
- losscut = true ;
- }
- break;
- }
- }
- }
- if(losscut) {
- //損切
- CheckoutOrderAll(orderFlag);
- if(Offsetting) {
- double oldLossPrices=LossPrices, newLossPrices = 0.0 ;
- if(GlobalVariableGet(LOSSPRICES_NAME,oldLossPrices)) {
- newLossPrices = oldLossPrices ;
- }
- newLossPrices += status.CurrentPrices ;
- GlobalVariableSet(LOSSPRICES_NAME,newLossPrices);
- }
- /*
- if(offs) {
- CheckoutOrderAll(revOrderFlag);
- }*/
- }else if(PmdTiming) {
- double stride = PyramidingStride * Point ;
- bool canAverage = Averaging&&(!AveragingTimes||status.AveragePositions<AveragingTimes);
- if(canAverage) {
- if(Offsetting) {
- // DONE : ナンピンするかダイバージェンスするかはMAを見て決めるようにする
- double FastMA = ShortTermMA(0) ;
- double SlowMA = LongTermMA(0) ;
- canAverage = (orderType==OP_BUY && FastMA>SlowMA) || (orderType==OP_SELL && FastMA<SlowMA);
- if(canAverage) {
- if(revStatus.Positions>0) { // ダイバージェンスポジションが既に存在する
- //ナンピンできる動きをしたかプライスアクションを調べる
- switch(orderType) {
- case OP_BUY: {
- double border = status.MinPrice-stride ;
- //プライスがボーダーラインを上から下に割り込んだかどうか
- canAverage = PmdPrevAsk>=border && Ask<=border ;
- break;
- }
- case OP_SELL: {
- double border = status.MaxPrice+stride ;
- //プライスがボーダーラインを下から上に突き抜けたかどうか
- canAverage = PmdPrevBid<=border && Bid>=border ;
- break;
- }
- }
- }
- }
- }
- }
- if(canAverage) {
- //ナンピン
- double sl=0.0, tp=0.0;
- canAverage = (orderType==OP_BUY && Ask<=status.MinPrice-stride) ||
- (orderType==OP_SELL && Bid>=status.MaxPrice+stride);
- /*switch(orderType) {
- case OP_BUY:
- sl = Bid - (Stoploss * Point);
- if(Takeprofit!=0.0) {
- tp = Ask + (Takeprofit * Point);
- if(status.MaxTakeprofit>tp)
- tp = status.MaxTakeprofit ;
- }
- break;
- case OP_SELL:
- sl = Ask + (Stoploss * Point);
- if(Takeprofit!=0.0) {
- tp = Bid - (Takeprofit * Point);
- if(status.MinTakeprofit<tp)
- tp = status.MinTakeprofit ;
- }
- break;
- }*/
- if(canAverage) {
- double lots = 0.0 ;
- switch(orderType) {
- case OP_BUY:
- if(BuyTLEntried) lots += Lots ;
- if(BuyFastMAEntried) lots += Lots ;
- if(BuyMediumMAEntried) lots += Lots ;
- break;
- case OP_SELL:
- if(SellTLEntried) lots += Lots ;
- if(SellFastMAEntried) lots += Lots ;
- if(SellMediumMAEntried) lots += Lots ;
- break;
- }
- if(Offsetting) {
- lots += revStatus.TotalLots * OffsettingDvgnScale ;
- }
- for(int i=0;i<=status.AveragePositions;i++) {
- lots *= AveragingScale ;
- }
- bool done = MakeOrder(orderType,-lots,sl,tp,"AVRG",MAGICMA) ;
- if(done) {
- // sl 値をすべて更新する
- /*if(orderType==OP_BUY?sl<status.MinStoploss:sl>status.MaxStoploss) {
- for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
- if( OrderSelect(i, SELECT_BY_POS) ) {
- if( OrderSymbol() != Symbol() ) continue ;
- if( magic != OrderMagicNumber() ) continue ;
- if( orderType != OrderType() ) continue ;
- OrderModify(OrderTicket(), OrderOpenPrice(), sl,
- OrderTakeProfit(), OrderExpiration(),
- orderType==OP_BUY?clrBlue:clrRed);
- }
- }
- }*/
- //ボーダーライン更新
- DrawBorderLine(orderType);
- }
- }
- }else if(Offsetting&&!revStatus.Positions) {
- // ダイバージェンス
- bool canOffset = false ;
- switch(orderType) {
- case OP_BUY:
- if(Bid<=status.MinPrice-stride) {
- BuyMaxPrice = status.MaxPrice ; // 最高値をリセットしておく
- canOffset = true ;
- }
- break;
- case OP_SELL:
- if(Ask>=status.MaxPrice+stride) {
- SellMinPrice = status.MinPrice ; // 最低値をリセットしておく
- canOffset = true ;
- }
- break;
- }
- if(canOffset) {
- EntryPosition("DVGN", revOrderType, Lots);
- }
- }
- }
- }else /*if(!underPrice)*/ do {
- //Entried値を取得
- bool TLEntried = orderType==OP_BUY?BuyTLEntried:SellTLEntried;
- bool FastMAEntried = orderType==OP_BUY?BuyFastMAEntried:SellFastMAEntried;
- bool MediumMAEntried = orderType==OP_BUY?BuyMediumMAEntried:SellMediumMAEntried;
- double orderDenom=0.0;
- if(TLEntried) orderDenom+=1.0;
- if(FastMAEntried) orderDenom+=1.0;
- if(MediumMAEntried) orderDenom+=1.0;
- //ピラミッティング
- if(PmdTiming) {
- double stride = orderType==OP_BUY ? Ask-status.MaxPrice : status.MinPrice-Bid ;
- bool canPyramid = stride >= PyramidingStride*Point ;
- if(canPyramid) {
- if(!timeLimited) {
- //利確ロット調整
- double curTotalLots = totalLots ;
- if(Offsetting) curTotalLots -= revStatus.TotalLots ;
- if(curTotalLots>=ProfitTotalLots) canPyramid = false ;
- }
- }
- if(canPyramid) {
- if(!PyramidingTimes||status.PyramidPositions<PyramidingTimes) {
- double lots = 0.0 ;
- switch(orderType) {
- case OP_BUY:
- if(BuyTLEntried) lots += Lots ;
- if(BuyFastMAEntried) lots += Lots ;
- if(BuyMediumMAEntried) lots += Lots ;
- break;
- case OP_SELL:
- if(SellTLEntried) lots += Lots ;
- if(SellFastMAEntried) lots += Lots ;
- if(SellMediumMAEntried) lots += Lots ;
- break;
- }
- if(Offsetting) {
- lots += revStatus.TotalLots * OffsettingDvgnScale ;
- }
- int si=0;
- double scale = PyramidingScale;
- for(int i=si;i<=status.PyramidPositions;i++) {
- lots *= scale ;
- if(lots<MinLots) break;
- if(lots>MaxLots) break;
- }
- if(lots<MinLots) lots = MinLots ;
- if(lots>MaxLots) lots = MaxLots ;
- double sl = 0.0, tp =0.0 ;
- double mulLots = lots*orderDenom;
- if(MakeOrder(orderType,-lots,sl,tp,"PRMD",MAGICMA)) {
- //tp値更新
- //UpdateSlTp(orderType,0,tp);
- //ボーダーライン更新
- DrawBorderLine(orderType);
- break;
- }
- }
- }
- }
- //Sl値自動更新
- /*
- if(MoveStoploss) {
- UpdateSlTp(orderType);
- }
- */
- if(profitSatisfied) {
- //利確処理
- double deltaTp = Takeprofit * Point ;
- if(deltaTp>0.0) {
- bool orderMustClose = false ;
- if(orderType==OP_BUY) {
- if(Bid-borderPrice/*status.MaxPrice*/>=deltaTp)
- orderMustClose = true ;
- }else if(orderType==OP_SELL) {
- if(/*status.MinPrice*/borderPrice-Ask>=deltaTp)
- orderMustClose = true ;
- }
- if(orderMustClose) {
- CheckoutOrderAll(orderFlag);
- if(offs) {
- CheckoutOrderAll(revOrderFlag);
- }
- break;
- }
- }
- }else if(offs&&revStatus.TotalLots<=status.TotalLots) {
- //損切処理
- double deltaSl = Stoploss * Point ;
- if(deltaSl>0.0) {
- bool orderMustClose = false ;
- if(orderType==OP_BUY) {
- if(Bid-status.BorderPrice/*status.MaxPrice*/>=deltaSl)
- orderMustClose = true ;
- }else if(orderType==OP_SELL) {
- if(/*status.MinPrice*/status.BorderPrice-Ask>=deltaSl)
- orderMustClose = true ;
- }
- if(orderMustClose) {
- CheckoutOrderAll(orderFlag);
- if(offs) {
- CheckoutOrderAll(revOrderFlag);
- }
- break;
- }
- }
- }
- if(timeLimited) {
- // 時間が経過した
- double Mid = (Ask+Bid)/2.0 ;
- double FastMA0 = iMA(NULL, MainTimeFrame, FastMAPeriod, MAShift, MAMode, MAPriceType, 0);
- double MediumMA0 = iMA(NULL, MainTimeFrame, MediumMAPeriod, MAShift, MAMode, MAPriceType, 0);
- if( (orderType==OP_BUY && Bid>borderPrice) ||
- (orderType==OP_SELL && Ask<borderPrice) ) { // 利確決済可能
- double trailLine = borderPrice ;
- if( (orderType==OP_BUY && Bid>profitPrice) ||
- (orderType==OP_SELL && Ask<profitPrice) ) { // profit決済可能
- trailLine = profitPrice ;
- }
- double trailPrice = TrailPrice(orderType);
- if(trailPrice==0.0) {
- TrailLine(orderType,trailLine);
- }else {
- if(orderType==OP_BUY) {
- if(trailLine>trailPrice)
- TrailLine(orderType,trailLine);
- }else if(orderType==OP_SELL) {
- if(trailLine<trailPrice)
- TrailLine(orderType,trailLine);
- }
- }
- if(TLEntried) { // Time Limited Position
- CheckoutOrderAll(orderFlag,orderDenom);
- TLEntried = false ;
- if(offs) {
- CheckoutOrderAll(revOrderFlag,orderDenom);
- }
- orderDenom-=1.0;
- }
- if(FastMAEntried) { // Fast MA Position
- bool orderMustClose = false ;
- if( (orderType==OP_BUY && Mid<=FastMA0) ||
- (orderType==OP_SELL && Mid>=FastMA0) ) { // 利益が Fast MA 以下になっている
- orderMustClose = true ;
- }
- if(orderMustClose) {
- CheckoutOrderAll(orderFlag,orderDenom);
- FastMAEntried = false ;
- if(offs) {
- CheckoutOrderAll(revOrderFlag,orderDenom);
- }
- orderDenom-=1.0;
- }
- }
- if(MediumMAEntried) { // Medium MA Position
- bool orderMustClose = false ;
- if( (orderType==OP_BUY && Mid<=MediumMA0) ||
- (orderType==OP_SELL && Mid>=MediumMA0) ) { // 利益が Medium MA 以下になっている
- orderMustClose = true ;
- }
- if(orderMustClose) {
- CheckoutOrderAll(orderFlag);
- MediumMAEntried = false ;
- if(offs) {
- CheckoutOrderAll(revOrderFlag);
- }
- orderDenom=0.0;
- }
- }
- }
- /*
- if(orderDenom>=1.0)
- UpdateSlTp(orderType,borderPrice);
- */
- }
- bool expired = !profitSatisfied &&
- offs && OffsettingExpireMinutes>0 &&
- TimeCurrent() - MathMin(status.MinOpenTime,revStatus.MinOpenTime) >= OffsettingExpireMinutes*60 ;
- if(expired) {
- if(revStatus.TotalLots<status.TotalLots) {
- // 損切逆トレーリング
- double trailLine = ( borderPrice + status.BorderPrice ) / 2.0 ;
- double trailPrice = TrailPrice(revOrderType);
- if(trailLine!=0.0) {
- if(trailPrice==0.0) { // 初回トレール
- TrailLine(revOrderType, trailLine);
- }else {
- switch(orderType) { // TP Trailing
- case OP_BUY:
- if(trailLine>trailPrice) {
- TrailLine(revOrderType, trailLine);
- }
- break;
- case OP_SELL:
- if(trailLine<trailPrice) {
- TrailLine(revOrderType, trailLine);
- }
- break;
- }
- }
- }
- }else {
- // 逆トレーリング解除
- if(TrailPrice(revOrderType)!=0.0)
- TrailLine(revOrderType);
- }
- }
- if(Trailing||expired) {
- //トレーリング
- double medianBorder = offs ? medianPrice : borderPrice ;
- if(expired) medianBorder = ( borderPrice + status.BorderPrice ) / 2.0 ;
- if(medianBorder!=0.0) {
- double trailLine = 0.0;
- double trailStart = TrailingStart*Point ;
- double trailPadding = TrailingPadding*Point ;
- double trailPrice = TrailPrice(orderType);
- switch(orderType) {
- case OP_BUY:
- if(trailPrice>0.0) {
- trailLine = MathMax(Bid-trailPadding, MathMax(trailPrice,medianBorder) );
- }
- else if(Bid-medianBorder>=trailStart) {
- trailLine = MathMax(Bid-trailPadding, medianBorder);
- }
- break;
- case OP_SELL:
- if(trailPrice>0.0) {
- trailLine = MathMin(Ask+trailPadding, MathMin(trailPrice,medianBorder) );
- }
- else if(medianBorder-Ask>=trailStart) {
- trailLine = MathMin(Ask+trailPadding, medianBorder);
- }
- break;
- }
- if(trailLine!=0.0) {
- if(trailPrice==0.0) { // 初回トレール
- TrailLine(orderType, trailLine);
- }else {
- switch(orderType) {
- case OP_BUY:
- if(trailLine>trailPrice) {
- TrailLine(orderType, trailLine);
- }
- break;
- case OP_SELL:
- if(trailLine<trailPrice) {
- TrailLine(orderType, trailLine);
- }
- break;
- }
- }
- }
- }
- }
- //損切未然防止処理
- /*else if(losscut) {
- UpdateSlTp(orderType,borderPrice);
- }*/
- //損切未然防止処理(ボーダー越えの手前阻止)
- /*else if(losscutBorder) {
- double spread = Ask-Bid ;
- if( (orderType==OP_BUY && BuyMaxPrice>borderPrice+spread && borderPrice+spread>Bid) ||
- (orderType==OP_SELL && SellMinPrice<borderPrice-spread && borderPrice-spread<Ask) ) {
- double oc = Bid - iClose(NULL, MainTimeFrame, 1) ;
- if( (orderType==OP_BUY && oc<0) || (orderType==OP_SELL && oc>0) )
- UpdateSlTp(orderType,borderPrice);
- }
- }*/
- //Entried値を戻す
- switch(orderType) {
- case OP_BUY:
- BuyTLEntried = TLEntried ;
- BuyFastMAEntried = FastMAEntried ;
- BuyMediumMAEntried = MediumMAEntried ;
- break;
- case OP_SELL:
- SellTLEntried = TLEntried ;
- SellFastMAEntried = FastMAEntried ;
- SellMediumMAEntried = MediumMAEntried ;
- break;
- }
- }while(0);
- //トレールによる利確/損切処理
- double trailPrice = TrailPrice(orderType);
- if(trailPrice>0.0) {
- bool orderMustClose=false;
- switch(orderType) {
- case OP_BUY:
- if(Bid<=trailPrice)
- orderMustClose=true;
- break;
- case OP_SELL:
- if(Ask>=trailPrice)
- orderMustClose=true;
- break;
- }
- if(orderMustClose) {
- CheckoutOrderAll(orderFlag);
- bool expired = Offsetting && OffsettingExpireMinutes>0 &&
- TimeCurrent() - MathMin(status.MinOpenTime,revStatus.MinOpenTime) >= OffsettingExpireMinutes*60 ;
- if(offs||expired) {
- CheckoutOrderAll(revOrderFlag);
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- bool InnerPoint(double v, double comp) {
- return comp-Point/2.0 < v && v < comp+Point/2.0 ;
- }
- //sl/tpの一括更新
- /*
- void UpdateSlTp(int orderType, double new_sl=0.0, double new_tp=0.0)
- {
- STATUS status ;
- //ステータス更新
- if(!CheckStatus(orderType, MAGICMA, status)) return ;
- double borderPrice = status.BorderPrice ;
- double profitPrice = status.ProfitPrice ;
- double padding = StoplossPadding*Point ;
- bool overBorder = orderType==OP_BUY ?
- Bid >= borderPrice+padding : borderPrice-padding >= Ask ;
- bool overProfit = orderType==OP_BUY ?
- Bid >= profitPrice+padding : profitPrice-padding >= Ask ;
- if(overBorder&&!overProfit) {
- // padding が borderPrice から profitPrice の範囲内にある
- switch(orderType) {
- case OP_BUY:
- profitPrice = Bid-padding ;
- break;
- case OP_SELL:
- profitPrice = Ask+padding ;
- break;
- }
- overProfit = true ;
- }
- // sl/tp 値をすべて更新する
- for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
- if( OrderSelect(i, SELECT_BY_POS) ) {
- if( OrderSymbol() != Symbol() ) continue ;
- if( MAGICMA != OrderMagicNumber() ) continue ;
- if( orderType != OrderType() ) continue ;
- double sl = new_sl, tp = new_tp ;
- double orderStoploss = OrderStopLoss();
- double orderTakeprofit = OrderTakeProfit();
- if(new_sl==0.0) {
- if( overProfit && MoveStoploss )
- sl = profitPrice;
- else
- sl = orderStoploss;
- }
- switch(orderType) {
- case OP_BUY:
- if(sl<orderStoploss)
- sl = orderStoploss;
- break;
- case OP_SELL:
- if(sl>orderStoploss)
- sl = orderStoploss;
- break;
- }
- if(new_tp==0.0)
- tp = orderTakeprofit;
- if(InnerPoint(sl,orderStoploss)) sl = orderStoploss ;
- if(InnerPoint(tp,orderTakeprofit)) tp = orderTakeprofit ;
- if(sl!=orderStoploss||tp!=orderTakeprofit) {
- if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl, tp,
- OrderExpiration(), orderType==OP_BUY?ClrLongArrow:ClrShortArrow)) {
- PrintLastError();
- }
- }
- }
- }
- }
- */
- //---------------------------------------------------------------------------
- //TL(TimeLimited)タイマー
- void TLInit(int orderType)
- {
- switch(orderType) {
- case OP_BUY: BuyKeepTimer=0; break;
- case OP_SELL: SellKeepTimer=0; break;
- }
- }
- //----
- int TL(int orderType, int inc=0)
- {
- switch(orderType) {
- case OP_BUY:
- BuyKeepTimer+=inc ;
- return BuyKeepTimer;
- case OP_SELL:
- SellKeepTimer+=inc ;
- return SellKeepTimer;
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- //すでに注文済みかどうか
- int AlreadyOrdered(int orderFlag, int magic)
- {
- int flag = 0 ;
- for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
- if( OrderSelect(i, SELECT_BY_POS) ) {
- int orderMagic = OrderMagicNumber() ;
- if( OrderSymbol() == Symbol() && magic==orderMagic ){
- if( OrderType() == OP_BUY && (orderFlag&FLAG_BUY)!=0 ){
- flag |= FLAG_BUY ; if(flag==orderFlag) break;
- }else if( OrderType() == OP_SELL && (orderFlag&FLAG_SELL)!=0 ){
- flag |= FLAG_SELL ; if(flag==orderFlag) break;
- }
- }
- }
- }
- return flag;
- }
- //---------------------------------------------------------------------------
- //キーキャンドルスティックのsl値を返す
- /*
- double StoplossKCSSl(int entryType)
- {
- double sl = entryType==OP_BUY ? Bid : Ask ;
- for(int i=1;i<=StoplossKCSDuration;i++) {
- switch(entryType) {
- case OP_BUY: {
- double cls = iLow(Symbol(),MainTimeFrame,i);
- if(cls<sl) sl = cls ;
- break;
- }
- case OP_SELL: {
- double cls = iHigh(Symbol(),MainTimeFrame,i) + (Ask-Bid) ; // Spread分、足す
- if(cls>sl) sl = cls ;
- break;
- }
- }
- }
- return sl;
- }
- */
- //---------------------------------------------------------------------------
- //EA用ポジションのエントリー
- bool EAEntryPosition(string detector, int orderFlag, int &busy)
- {
- // EAの注文を処理
- if((PositionFlag&orderFlag)!=0&&(busy&orderFlag)==0) {
- if(!busy||(PositionFlag&FLAG_DUPLEX)!=0) {
- int entry = orderFlag == FLAG_BUY ? OP_BUY : OP_SELL ;
- EntryPosition(detector, entry, Lots);
- busy |= orderFlag ;
- return true ;
- }
- }
- return false ;
- }
- //---------------------------------------------------------------------------
- //ポジションのエントリー(注文の発注簡易版)
- bool EntryPosition(string detector, int entryType, double lots, int magic=0, double sl=-1.0, double tp=-1.0)
- {
- switch(entryType) {
- case OP_BUY:
- if(sl<0.0) {
- /*
- sl = Bid - (Stoploss * Point);
- if(StoplossKCS) {
- double kcsSl = StoplossKCSSl(OP_BUY);
- if(sl<kcsSl) sl = kcsSl ;
- }
- */ sl=0.0;
- }
- if(tp<0.0) {
- tp=0.0;
- /*if(Takeprofit!=0.0)
- tp = Ask + (Takeprofit * Point);*/
- }
- BuyTLEntried=EntryTLPos;
- BuyFastMAEntried=EntryFastMAPos;
- BuyMediumMAEntried=EntryMediumMAPos;
- break;
- case OP_SELL:
- if(sl<0.0) {
- /*
- sl = Ask + (Stoploss * Point);
- if(StoplossKCS) {
- double kcsSl = StoplossKCSSl(OP_SELL);
- if(sl>kcsSl) sl = kcsSl ;
- }
- */ sl=0.0;
- }
- if(tp<0.0) {
- tp = 0.0 ;
- /*if(Takeprofit!=0.0)
- tp = Bid - (Takeprofit * Point);*/
- }
- SellTLEntried=EntryTLPos;
- SellFastMAEntried=EntryFastMAPos;
- SellMediumMAEntried=EntryMediumMAPos;
- break;
- }
- bool res = MakeOrder(entryType,lots,sl,tp,detector,magic) ;
- if(res) {
- switch(entryType) {
- case OP_BUY:
- BuyMaxPrice = Ask ;
- BuyLosscutTimer = 0 ;
- break;
- case OP_SELL:
- SellMinPrice = Bid ;
- SellLosscutTimer = 0 ;
- break;
- }
- TLInit(entryType);
- }
- return res ;
- }
- //---------------------------------------------------------------------------
- //注文の発注
- bool MakeOrder(int entryType, double lots, double sl, double tp, string detector, int magic)
- {
- bool entried=false ;
- double mulLots = 0.0 ;
- if(lots<0) {
- lots=-lots;
- mulLots=1.0;
- }else {
- switch(entryType) {
- case OP_BUY:
- if(BuyTLEntried) mulLots += 1.0 ;
- if(BuyFastMAEntried) mulLots += 1.0 ;
- if(BuyMediumMAEntried) mulLots += 1.0 ;
- break;
- case OP_SELL:
- if(SellTLEntried) mulLots += 1.0 ;
- if(SellFastMAEntried) mulLots += 1.0 ;
- if(SellMediumMAEntried) mulLots += 1.0 ;
- break;
- }
- }
- if(mulLots==0.0) return false ;
- for(int retry=0; retry<ORDER_RETRY; retry++) {
- if(MarketInfo(NULL,MODE_SPREAD) > Spread) { Sleep(2000); continue ; }
- double entryPrice = 0.0 ;
- color orderColor = clrNONE;
- switch(entryType) {
- case OP_BUY:
- entryPrice = Ask ;
- orderColor = ClrLongArrow ;
- break;
- case OP_SELL:
- entryPrice = Bid ;
- orderColor = ClrShortArrow ;
- break;
- }
- if(!entried) {
- if(MakeOrderSub(entryType,entryPrice,lots*mulLots,sl,tp,ENTRY_NAME"("+detector+")",magic,orderColor))
- entried = true ;
- }
- if(entried) {
- return true ;
- }
- Sleep(2000);
- }
- return false;
- }
- //---------------------------------------------------------------------------
- //注文発注サブルーチン
- bool MakeOrderSub(int entryType, double entryPrice, double lots, double sl, double tp,
- string comment,int magicNumber,color orderColor)
- {
- int res = OrderSend(
- NULL,
- entryType,
- lots,
- entryPrice,
- Slippage,
- sl,
- tp,
- comment,
- magicNumber,
- 0,
- orderColor
- );
- if(res<0)
- PrintLastError();
- return res>=0;
- }
- //---------------------------------------------------------------------------
- //注文の決済
- bool CheckoutOrder( int orderType, int orderTicket, double orderLots)
- {
- for(int retry=0; retry<ORDER_RETRY; retry++) {
- double checkoutPrice = 0.0 ;
- color orderColor = clrNONE ;
- switch(orderType) {
- case OP_BUY:
- checkoutPrice = Bid ;
- orderColor = ClrLongArrow ;
- break;
- case OP_SELL:
- checkoutPrice = Ask ;
- orderColor = ClrShortArrow ;
- break;
- }
- if(orderLots<MinLots) orderLots = MinLots ;
- if(OrderClose(orderTicket, orderLots, checkoutPrice, Slippage, orderColor))
- return true;
- Sleep(100);
- }
- PrintLastError();
- return false ;
- }
- //---------------------------------------------------------------------------
- struct OBJECT_CHECKOUT {
- int Ticket;
- double Profit;
- OBJECT_CHECKOUT() {
- Ticket = -1 ;
- Profit = 0.0 ;
- }
- OBJECT_CHECKOUT(int Ticket_, double Profit_) {
- Ticket = Ticket_ ;
- Profit = Profit_ ;
- }
- bool operator <(const OBJECT_CHECKOUT &rhs) const {
- return Profit < rhs.Profit ;
- }
- };
- //注文の全決済
- bool CheckoutOrderAll(int orderFlag, double lotsDenom=1.0)
- {
- bool result = true ;
- CArrayObj *array = new CArrayObj();
- for(int i = 0 ; i < OrdersTotal() ; i++){
- if(OrderSelect(i, SELECT_BY_POS)) {
- int magic = OrderMagicNumber();
- int orderType = OrderType() ;
- if( (orderType==OP_BUY&&(orderFlag&FLAG_BUY)!=0) ||
- (orderType==OP_SELL&&(orderFlag&FLAG_SELL)!=0) ) {
- if( OrderSymbol() == Symbol() && magic == MAGICMA ){
- AddToArray(array,OBJECT_CHECKOUT(OrderTicket(),OrderProfit()));
- }
- }
- }
- }
- array.Sort(ARRAY_SORT_DESCEND); // 利益が多い順に並べ替える
- for(int i=0;i<array.Total();i++) {
- CSortable<OBJECT_CHECKOUT> *node = (CSortable<OBJECT_CHECKOUT>*)array.At(i);
- if(OrderSelect(node.key.Ticket, SELECT_BY_TICKET)) {
- if(!CheckoutOrder(OrderType(),OrderTicket(),OrderLots()/lotsDenom)) {
- result = false ; break;
- }
- }
- }
- delete array ;
- return result ;
- }
- //---------------------------------------------------------------------------
- //000,000,000表示
- // http://chocottokozukai.seesaa.net/article/417824756.html
- string DoubleToAmount(double inputdata, int dig)
- {
- string returnstr = DoubleToStr(inputdata,dig);
- int length;
- int noofcomma;
- int firstcomma;
- length = StringLen(DoubleToStr(MathFloor(inputdata),0));
- if (inputdata >= 0) noofcomma = (int)MathFloor((length - 1) / 3);
- else noofcomma = (int)MathFloor((length - 2) / 3);
- if (noofcomma == 0) return (returnstr);
- firstcomma = length - noofcomma * 3;
- if (firstcomma == 0) firstcomma = 3;
- for (int i = 0; i < noofcomma; i++){
- returnstr = StringConcatenate(StringSubstr(returnstr, 0, firstcomma + i * 4),
- ",",StringSubstr(returnstr, firstcomma + i * 4));
- }
- return (returnstr);
- }
- //---------------------------------------------------------------------------
- //短期MA値を返す
- double ShortTermMA(int si)
- {
- return iMA(NULL, MainTimeFrame, ReferSlowMA?MediumMAPeriod:FastMAPeriod,
- MAShift, MAMode, MAPriceType, si);
- }
- //-----
- //長期MA値を返す
- double LongTermMA(int si)
- {
- return iMA(NULL, MainTimeFrame, ReferSlowMA?SlowMAPeriod:MediumMAPeriod,
- MAShift, MAMode, MAPriceType, si);
- }
- //---------------------------------------------------------------------------
- // MARK: Detector MARSIX
- //-----
- input group "Detector MAXRSIX ( MA RSI Cross )"
- input bool MARSIXDetector = true; // MARSIX Detector Enabled ( MA RSI Cross )
- input int MARSIXRangeDuration = 15; // MARSIX Range Search Duration period
- input int MARSIXVaildDuration = 5; // MARSIX Valid Duration period
- input double MARSIXMAMaxDistance = 50.0; // MARSIX MA Max Distance in points
- input bool MARSIXMACheckLineUp = false; // MARSIX MA Check Line Up
- input int MARSIXRSIPeriod = 14 ; // MARSIX RSI period
- input ENUM_APPLIED_PRICE MARSIXRSIPriceType = PRICE_CLOSE; // MARSIX RSI Price type
- input double MARSIXRSIBuyXStart = 55.0; // MARSIX RSI Buy Cross Start border
- input double MARSIXRSIBuyXEnd = 69.1; // MARSIX RSI Buy Cross End border
- input double MARSIXRSISellXStart = 45.0; // MARSIX RSI Sell Cross Start border
- input double MARSIXRSISellXEnd = 30.9; // MARSIX RSI Sell Cross End border
- //-----
- // MA RSI Cross のエントリ状態確認
- int CheckDetectorMARSIX(int si=0)
- {
- int flag=0, multiFlag=0 ;
- double maxDist = MARSIXMAMaxDistance*Point ;
- // 現在の状態を確認
- double HalfSpread = (Ask-Bid) / 2.0 ;
- double FastMA0 = ShortTermMA(si)+HalfSpread;
- double FastMA1 = ShortTermMA(si+1)+HalfSpread;
- double MediumMA = LongTermMA(si)+HalfSpread;
- double Distance = DBL_MAX ;
- double c = iClose(NULL, MainTimeFrame, 1);
- double RSI0 = iRSI(Symbol(), MainTimeFrame, MARSIXRSIPeriod, MARSIXRSIPriceType, si+0);
- if(Bid<=FastMA0&&FastMA0<=Ask) { // 検証不能
- return 0 ;
- }else if(Bid-c>0&&Ask>FastMA0&&FastMA0-FastMA1>0) {
- if(Ask-FastMA0<=maxDist && ((!MARSIXMACheckLineUp)||(FastMA0>MediumMA)) ) {
- if(RSI0>=MARSIXRSIBuyXEnd)
- flag = FLAG_BUY ;
- }
- }else if(Bid-c<0&&Bid<FastMA0&&FastMA0-FastMA1<0) {
- if(FastMA0-Bid<=maxDist && ((!MARSIXMACheckLineUp)||(FastMA0<MediumMA)) ) {
- if(RSI0<=MARSIXRSISellXEnd)
- flag = FLAG_SELL ;
- }
- }
- if(flag) {
- // RSIのクロスをチェック
- for (int i=1; i<=MARSIXRangeDuration; i++) {
- if(!multiFlag&&i>=MARSIXVaildDuration) break; // RSI Cross 検出範囲外
- double RSI1 = iRSI(Symbol(), MainTimeFrame, MARSIXRSIPeriod, MARSIXRSIPriceType, si+i);
- if(RSI0>=MARSIXRSIBuyXEnd) { // 買い
- if(RSI1<=MARSIXRSIBuyXStart) {
- multiFlag |= FLAG_BUY ;
- if(multiFlag==(FLAG_BUY|FLAG_SELL)) break;
- RSI0=RSI1 ;
- continue;
- }
- }else if(RSI0<=MARSIXRSISellXEnd) { // 売り
- if(RSI1>=MARSIXRSISellXStart) {
- multiFlag |= FLAG_SELL ;
- if(multiFlag==(FLAG_BUY|FLAG_SELL)) break;
- RSI0=RSI1 ;
- continue;
- }
- }else {
- RSI0=RSI1 ;
- }
- }
- if(flag==multiFlag) {
- return flag ; // 順張りの売買タイミング
- }
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- // MARK: Detector 2MMX
- // ( https://youtu.be/deBLPlt8N4E )
- //-----
- input group "Detector 2MMX ( 2 Momentum Cross )"
- input bool MMX2Detector = true ; // 2MMX Detector Enabled ( 2 Momentum Cross )
- input int MMX2FastPeriod = 10; // 2MMX Fast period
- input int MMX2SlowPeriod = 34; // 2MMX Slow period
- input int MMX2Duration = 5; // 2MMX Duration
- input ENUM_APPLIED_PRICE MMX2PriceType = PRICE_CLOSE; // 2MM Price type
- //-----
- int CheckDetectorMMX2(int si=0)
- {
- double FastMA0 = ShortTermMA(si);
- double MediumMA0 = LongTermMA(si);
- double SlowMM0 = iMomentum(NULL, MainTimeFrame, MMX2SlowPeriod, MMX2PriceType, si);
- int ma = 0, mm = 0 ;
- if(FastMA0>MediumMA0) ma = FLAG_BUY ;
- else if(FastMA0<MediumMA0) ma = FLAG_SELL ;
- if(SlowMM0>100.0) mm = FLAG_BUY ;
- else if(SlowMM0<100.0) mm = FLAG_SELL ;
- if(ma!=0&&ma==mm) {
- double FastMM0 = iMomentum(NULL, MainTimeFrame, MMX2FastPeriod, MMX2PriceType, si);
- double FastMM1 = iMomentum(NULL, MainTimeFrame, MMX2FastPeriod, MMX2PriceType, si+1);
- // Check fast momentum crossing
- if( mm == FLAG_BUY ? FastMM0>=100.0 && FastMM1<100.0 : FastMM0<=100.0 && FastMM1>100.0) {
- // Check duration
- for(int i=1;i<=MMX2Duration;i++) {
- double FastMAi = ShortTermMA(si+i);
- double MediumMAi = LongTermMA(si+i);
- if( mm == FLAG_BUY ? FastMAi < MediumMAi : FastMAi > MediumMAi) return 0;
- double SlowMMi = iMomentum(NULL, MainTimeFrame, MMX2SlowPeriod, MMX2PriceType, si+i);
- if( mm == FLAG_BUY ? SlowMMi < 100.0 : SlowMMi > 100.0 ) return 0;
- }
- // Valid entry position detected
- return mm ;
- }
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- // MARK: Detector COBRA
- // ( https://youtu.be/EbGK1FF2Q_c )
- //-----
- input group "Detector COBRA ( RSI-COBRA )"
- input bool COBRADetector = true ; // COBRA Detector Enabled ( RSI-COBRA )
- input ENUM_APPLIED_PRICE COBRARSIPriceType = PRICE_CLOSE ; // COBRA RSI Price type
- input int COBRARSIPeriod = 14 ; // COBRA RSI period
- input int COBRAMAPeriod = 50 ; // COBRA MA period
- input ENUM_MA_METHOD COBRAMAMethod = MODE_SMA ; // COBRA MA mode
- input int COBRADuration = 5; // COBRA Duration
- //-----
- int CheckDetectorCOBRA(int si=0)
- {
- double FastMA0 = ShortTermMA(si);
- double MediumMA0 = LongTermMA(si);
- int ma=0;
- if(FastMA0>MediumMA0) ma = FLAG_BUY ;
- else if(FastMA0<MediumMA0) ma = FLAG_SELL ;
- if(ma!=0) {
- // Check duration of Fast and Medium MA line up
- for(int i=1;i<=COBRADuration;i++) {
- double FastMAi = ShortTermMA(si+i);
- double MediumMAi = LongTermMA(si+i);
- if( ma == FLAG_BUY ? FastMAi < MediumMAi : FastMAi > MediumMAi) return 0;
- }
- // Make array of RSI
- double arRSI[] ;
- int nArRSI = COBRAMAPeriod+COBRADuration+1 ;
- ArrayResize(arRSI,nArRSI);
- for(int i=0;i<nArRSI;i++) {
- arRSI[i]=iRSI(NULL, MainTimeFrame, COBRARSIPeriod, COBRARSIPriceType, si+i);
- }
- // Check RSI-COBRA entry position
- double RSIMA0 = iMAOnArray(arRSI, nArRSI, COBRAMAPeriod, MAShift, COBRAMAMethod, 0);
- if( ma == FLAG_BUY ? RSIMA0>50.0 && arRSI[0]>=RSIMA0 && arRSI[1]<RSIMA0 :
- RSIMA0<50.0 && arRSI[0]<=RSIMA0 && arRSI[1]>RSIMA0) {
- // Check duration of RSI->MA line up
- for(int i=1;i<=COBRADuration;i++) {
- double RSIMAi = iMAOnArray(arRSI, nArRSI, COBRAMAPeriod, MAShift, COBRAMAMethod, i);
- if(ma == FLAG_BUY ? RSIMAi<50.0 : RSIMAi>50.0 ) return 0;
- }
- // Valid entry position detected
- return ma ;
- }
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- // MARK: Detector GXRSI
- //-----
- input group "Detector GXRSI ( RSI + MA Golden Cross )"
- input bool GXRSIDetector = true ; // GXRSI Detector Enabled ( RSI + MA Golden Cross )
- input int GXRSIValidDuration = 2; // GXRSI Valid Duration period
- input int GXRSIRSIPeriod = 14 ; // GXRSI RSI period
- input ENUM_APPLIED_PRICE GXRSIRSIPriceType = PRICE_CLOSE; // GXRSI RSI Price type
- input double GXRSIRSIBuyLine = 69.1; // GXRSI RSI Buy Line border
- input double GXRSIRSISellLine = 30.9; // GXRSI RSI Sell Line border
- //-----
- int CheckDetectorGXRSI(int si=0)
- {
- double RSI0 = iRSI(NULL, MainTimeFrame, GXRSIRSIPeriod, GXRSIRSIPriceType, si+0);
- int rsi = 0, gx = 0 ;
- if(RSI0>=GXRSIRSIBuyLine) rsi |= FLAG_BUY ;
- if(RSI0<=GXRSIRSISellLine) rsi |= FLAG_SELL ;
- if(rsi) { // RSI 買い または 売り の気配あり
- // MA ゴールデンクロス検出処理
- double FastMA0 = ShortTermMA(si);
- double MediumMA0 = LongTermMA(si);
- for(int i=0;i<GXRSIValidDuration;i++) {
- double FastMA1 = ShortTermMA(si+i+1);
- double MediumMA1 = LongTermMA(si+i+1);
- if(FastMA1<MediumMA1&&FastMA0>=MediumMA0) gx |= FLAG_BUY ;
- if(FastMA1>MediumMA1&&FastMA0<=MediumMA0) gx |= FLAG_SELL ;
- FastMA0 = FastMA1 ;
- MediumMA0 = MediumMA1 ;
- }
- }
- // RSI と MA ゴールデンクロス の 論理積 (両ビット立っているものを返す)
- return rsi & gx ;
- }
- //---------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment