Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // test_3ma_user_v3.mq5 (資金率換算版)
- // by 2024-2026 (c)hyrolean
- //---------------------------------------------------------------------------
- #property copyright "2024-2026, (c)hyrolean"
- #property link "https://pastebin.com/DvK0GaRg"
- #property version "3.02"
- #include <User/hyrDefs.mqh> // https://pastebin.com/iHZKAWqC
- #include <User/hyrTmpl.mqh> // https://pastebin.com/LG1vurny
- #include <User/hyrGlobal.mqh> // https://pastebin.com/2PdBW6NQ
- #include <User/hyrIQueue.mqh> // https://pastebin.com/3pRKTce4
- #include <User/hyrStatus.mqh> // https://pastebin.com/d9Z8P2qD
- // version 3.02
- // - エントリ時の初期手数料の値幅換算が狂っていたバグを修正
- // version 3.01
- // - CalcLotsFromSlDistance のロット計算方法を改訂(TYPE-II)
- // version 3.00
- // - OrderMethod input項目を追加
- // - Compounding(複利関連) input項目を削除し、RTPer(資金率) input項目を追加
- // version 2.03
- // - 初期手数料が勘定されない仕様のサーバーに対応
- // version 2.02
- // - 建値移動する際に手数料(スワップを除く)分を加味する工程を追加
- // version 2.01
- // - AmountDig input項目を削除
- // version 2.00
- // - ユーザーロット調整機能を追加
- // - 約定が失敗した際に音とエラーメッセージで知らせる処理を追加
- // - 主要関数を自作ライブラリに置換えてコンパクト化
- /*
- 3EMA 手法 ( 状態遷移情報をターミナルに格納する変数を必要としないバージョン )
- ・ 建玉するときに、EMA50をストップロスに設定する(Stoploss=0の場合)
- ※ 現在価格がEMA50を下回るところでは、建玉を行わないようにする
- ・ ストップロスが玉の価格より下にあるものに的を絞り、EMA50を基準にトレーリングを行う
- ※ ただし、玉の価格がEMA50より下にある場合は、上記の操作を見送ることとする
- ・ ストップロスが玉の価格より下にあるものに的を絞り、ロウソク足が5期間経過後から、
- 現在のプライスが超えた時点でストップロスをエントリープライスに移動し、ロットの1/3を利確する
- ロウソク足の期間の出し方:
- Bars(_Symbol, MainTimeFrame, <建玉時刻>, <現在時刻>)>=5
- ※ 5期間経過後に未だ現価が下にある場合は、現価が上に来るまでこの試行は継続
- されることとし、現価がロウソク足1期間でも抜けたら即ストップロスをエントリープライスに移動
- し、ロットの1/3利確することとする
- ・ 現在価格がEMA10を下回った場合、ストップロスがエントリープライスに一致する玉を検出し、
- EMA20の位置にストップロスを移動し、ロットの1/2を利確する(この時点でEMA20も現在価格
- を突破している場合は、全ロットを利確することとする)
- ※ ただし、玉の価格がEMA20より上にある場合は、上記の操作を見送ることとする
- ・ ストップロスが玉の価格より上にあるものに的を絞り、EMA20を基準にトレーリングを行う
- */
- /*
- 使い方::
- 1 クリック 約定モード: ( Order method on user entry = 1 click )
- 左上の|SELL|BUY|ボタンを選ぶと即座に約定されます。
- ポジションを打ったら、S/L(ストップロス)のBARを自分の好みの場所に移動させます。
- 2 ステップ約定モード: ( Order method on user entry = 2 steps )
- 左上の|SELL|BUY|ボタンを押すと、S/Lの赤いラインと|ENTRY|ボタンが表示されます。
- 赤いラインをドラッグしてS/Lの位置を決めてから、|ENTRY|ボタンを押すと約定されます。
- 約定前に取消する場合は、凹んでいる|SELL|BUY|ボタンをもう一度押してください。
- ロット数は最後の表記が'-'になっている場合は、資金率に応じて自動計算されます。
- 自分でロット数を決め打ちする場合は、最後の'-'を省いてから入力してください。
- 決め打ちのロット数から自動計算に戻す場合は、'-'だけをロット欄に入力してください。
- 以降、3EMAの手法に従って自動的に利確されます。(逆行しなければですが…)
- 運悪く逆行してしまった場合は、損益の㌫、または、slに応じて自動損切されます。
- エントリーのコツとしては、上から現在価格,EMA10,EMA20,EMA50の順番で並んでいるときは、
- ロング(買い)、逆に、上からEMA50,EMA20,EMA10,現在価格の順番で並んでいるときは、
- ショート(売り)でエントリーすると上手くいくかもしれないです。
- (利確のタイミングを図りたい場合など、自動処理を一時的に中断したい場合は、Automate
- Processing Orders をfalseに設定すると無効に出来ます。)
- MT5を閉じてもslとエントリープライスの位置だけで状態を把握する為、万が一VPS等が停止し
- てしまってもサーバー側に建玉の情報さえ残っていればMT5を再度立ち上げてこのEAを有
- 効化するだけで状態復帰可能な仕様に仕上げています。
- 以上ゞ
- */
- /*
- 手数料の書き方::
- 例1) 手数料が往復6ドルかかるサーバーを利用する場合:
- Initial Commission JPY per lot は、0.0 のまま
- Initial Commission USD per lot に、6.0 と記述
- 例2) 手数料が往復400円かかるサーバーを利用する場合:
- Initial Commission JPY per lot に、400.0 と記述
- Initial Commission USD per lot は、0.0 のまま
- 口座がドル建て円建てに関わらず、約定時にレートを拾ってきて自動換算されます。
- 通貨変換時に使用する通貨シンボルは、自動検索されますが、上手くいかない場合は、
- USDJPY Symbol name に USDJPY.raw や USDJPYp などの
- サーバーが保持している通貨名を直接入力してみてください。
- */
- #define ENTRY_NAME "3MAUserV3"
- #define ORDER_RETRY 10
- #define ORDER_RETRY_SLEEP 100
- #define ORDER_RETRY_DURATION 1000
- 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_ORDERMETHOD {
- ORDERMETHOD_ONE_CLICK, // 1 click
- ORDERMETHOD_TWO_STEPS // 2 steps ( S/L move -> entry )
- };
- enum ENUM_RTCALCTYPE {
- RTCALCTYPE_I, // TYPE-I ( Calculate with SYMBOL_TRADE_... )
- RTCALCTYPE_II // TYPE-II ( Use OrderCalcProfit function )
- };
- #define STATAG_CHECKEDOUT 1
- // ※ wine 環境だと文字化けする為、英字表記にしています
- input group "GENERAL"
- input bool Automation = true; // Automate processing orders
- input ENUM_TIMEFRAMES MainTimeFrame = PERIOD_CURRENT; // Main Time Frame
- input MAGIC MAGICMA = 0; // Magic Number
- input group "TIME CONTROL"
- 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 group "3MA"
- input ENUM_MA_METHOD MAMode= MODE_EMA; // MA mode
- input ENUM_APPLIED_PRICE MAPriceType = PRICE_CLOSE; // MA price type
- input bool MA3 = true; // 3MA Enabled
- input int MA3FastPeriod = 10; // 3MA Fast period
- input int MA3MediumPeriod = 20; // 3MA Medium period
- input int MA3SlowPeriod = 50; // 3MA Slow period
- input int MA3TLPeriod = 5; // 3MA TL(TimeLimited) period
- input group "ORDER"
- input int Slippage = 10; // Max Slippage
- input int Spread = 50; // Max Spread in points
- //input double BaseLots = 0.1; // Base Lots
- input double StepLots = 0.01; // Step Lots
- input double MinLots = 0.01; // Minimum Lots
- input double MaxLots = 50.0; // Maximum Lots
- input double LotsDenomTL = 3.0; // Lots denom of 3MA TL(TimeLimited)
- input double LotsDenomMAFast = 2.0; // Lots denom of 3MA Fast MA
- input double Takeprofit = 0; // Take profit in points (0 = unlimited)
- input double Stoploss = 100; // Stop loss in points (0 = Grossloss per or SlowMA trail)
- input ENUM_ORDERMETHOD OrderMethod = ORDERMETHOD_TWO_STEPS; // Order method on user entry
- input group "BALANCE"
- input double RTPer = 2.0; // Risk per Trade in percentage (資金率%)
- input ENUM_RTCALCTYPE RTCalcType = RTCALCTYPE_II; // Risk per Trade calculation type
- input double MaxGrosslossPer = 80.0; // Maximum Allowed Gross loss of Balance in percentage (EAの許容損失率%)
- input double MaxDrawDownPer = 80.0; // Maximum Allowed Draw down of Balance in percentage (口座の許容損失率%)
- //input bool Compounding = false; // Compounding interest Enabled
- //input double CompoundingBase = 100000; // Compounding Base Balance (Lots=BaseLots*Balance/BaseBalance)
- input bool BalanceIncludeCredit= true; // Balance include Credit (資金の計算にボーナスを加味するかどうか)
- input double InitialCommissionJPY = 0.0; // Initial Commission JPY per lot (1ロットあたりの初期手数料[JPY通貨単位])
- input double InitialCommissionUSD = 0.0; // Initial Commission USD per lot (1ロットあたりの初期手数料[USD通貨単位])
- input string USDJPYSymbolName = ""; // USDJPY Symbol name (USDJPY相互変換に使う通貨の名前[空の場合は自動検索])
- input group "TRAILING"
- input bool Trailing = false; // Trailing Enabled
- input double TrailingStart = 300; // Trailing Start in points
- input double TrailingStop = 200; // Trailing Stop in points
- input group "APPEARANCE"
- 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 ShowFlushTL = true; // Show a FLUSH TL button
- input bool ShowBEP = false; // Show BEP ( Break Even Price )
- input bool ShowAmount = true; // Show Current Amount
- //input int AmountDig = 0; // Amount Number of decimal places
- input color ClrAmountPosi = clrLightGoldenrod; // Amount Positive color
- input color ClrAmountNega = clrLightPink; // Amount Negative color
- input color ClrTimeControl = clrYellow; // Time Control Status color
- input color ClrBEPLong = clrSteelBlue; // Long BEP color
- input color ClrBEPShort = clrMediumPurple; // Short BEP color
- input color ClrUserStoploss = clrRed; // User entry Stoploss color
- input color ClrUserTakeprofit=clrOrange; // User entry Takeprofit color
- input group "DEBUGGING"
- input bool DBGMODE = true; // DEBUG MODE
- //===========================================================================
- // 型
- //---------------------------------------------------------------------------
- // OBJECT_PARTCLOSED
- struct OBJECT_PARTCLOSED {
- TICKET Ticket;
- OP Type;
- double Price;
- double Stoploss;
- datetime Time;
- OBJECT_PARTCLOSED(TICKET Ticket_, OP Type_, double Price_, datetime Time_, double Stoploss_=0) {
- Ticket = Ticket_ ;
- Type = Type_ ;
- Price = Price_ ;
- Time = Time_ ;
- Stoploss = Stoploss_ ;
- }
- OBJECT_PARTCLOSED(const OBJECT_PARTCLOSED &src) {
- Ticket = src.Ticket ;
- Type = src.Type ;
- Price = src.Price ;
- Time = src.Time ;
- Stoploss = src.Stoploss ;
- }
- bool operator <(const OBJECT_PARTCLOSED &rhs) const {
- //if(Ticket < rhs.Ticket) return true ;
- if(Type < rhs.Type) return true ;
- if(Price < rhs.Price) return true ;
- if(Time < rhs.Time) return true ;
- return false ;
- }
- };
- //===========================================================================
- double UserLots, Lots, CurBid, CurAsk, PrevBid, PrevAsk;
- #define MAShift 0
- datetime CurTime, TimeTick, StartTime, CancelTime, UserTime;
- FLAG UserEntry = 0, UserMode = 0 ;
- double UserStoploss=0.0, UserTakeprofit=0.0;
- bool FlushTL = false ;
- ENUM_ORDERMETHOD UserMethod ;
- int UserEntryBtnYPos = 0 ;
- // オーダーの状態
- STATUS BuyWholeStatus(OP_BUY,MAGICMA,InitialCommissionJPY,InitialCommissionUSD,USDJPYSymbolName);
- STATUS SellWholeStatus(OP_SELL,MAGICMA,InitialCommissionJPY,InitialCommissionUSD,USDJPYSymbolName);
- // サーバーがストップロスを更新しなかった場合のトラップ対策用配列
- CArrayObj *StoplossTrapArray = NULL;
- #define LOTSED_NAME "EntryLots"
- #define LOTSDEC_NAME "LotsDecBtn"
- #define LOTSINC_NAME "LotsIncBtn"
- #define SELLBTN_NAME "EntrySell"
- #define BUYBTN_NAME "EntryBuy"
- #define ENTRYBTN_NAME "EntryDecide"
- #define SLLINE_NAME "EntrySL"
- #define TPLINE_NAME "EntryTP"
- #define CLOSEALLBTN_NAME "CloseAll"
- #define CLOSELONGBTN_NAME "CloseLong"
- #define CLOSESHORTBTN_NAME "CloseShort"
- #define FLUSHTLBTN_NAME "FlushTL"
- #define LOTSSAVE_NAME (ENTRY_NAME "_UserLots_" + Symbol())
- #define OFFTIME_NAME "OFF TIME"
- bool OffTimeVisible = false ;
- #define AMOUNT_NAME "AMOUNT"
- #define AMOUNT_CLR_NEGA ClrAmountNega
- #define AMOUNT_CLR_POSI ClrAmountPosi
- #define DBGINFO_NAME "DEBUG INFO"
- double AdjLots(double lots) {
- lots = AdjustMarketLots(lots);
- double roundLots = MathRound( MathMax(lots,StepLots) / StepLots ) ;
- return MathMin(MathMax(roundLots*StepLots,MinLots),MaxLots) ;
- }
- double GetBid() { return SymbolInfoDouble(_Symbol, SYMBOL_BID); }
- double GetAsk() { return SymbolInfoDouble(_Symbol, SYMBOL_ASK); }
- //--- IQueue MA (3本分)
- CHyrIQueueMA QiFastMA, QiMediumMA, QiSlowMA;
- //--- IQueue ATR14 (デバッグ用)
- CHyrIQueueATR QiATR14;
- //---------------------------------------------------------------------------
- int OnInit()
- {
- //テスターで表示されるインジケータを非表示にする
- TesterHideIndicators(!DBGMODE);
- //--- IQueue MA 初期化(3本分)
- int qsize = MA3SlowPeriod * 3; // 余裕を持ったキューサイズ
- if(!QiFastMA.Init (_Symbol, MainTimeFrame, MA3FastPeriod, MAMode, MAPriceType, qsize) ||
- !QiMediumMA.Init(_Symbol, MainTimeFrame, MA3MediumPeriod, MAMode, MAPriceType, qsize) ||
- !QiSlowMA.Init (_Symbol, MainTimeFrame, MA3SlowPeriod, MAMode, MAPriceType, qsize))
- return INIT_FAILED;
- //--- IQueue ATR 14 (デバッグ用)
- if(!QiATR14.Init (_Symbol, PERIOD_CURRENT, 14, 2))
- return INIT_FAILED;
- CurTime = MainTime();
- TimeTick = StartTime = CancelTime = UserTime = BaseTime(TimeBase);
- GlobalSettings(
- ENTRY_NAME,
- Slippage,
- Spread,
- ORDER_RETRY,
- ORDER_RETRY_SLEEP,
- ORDER_RETRY_DURATION );
- bool LotsLoaded = false ;
- if(GlobalVariableCheck(LOTSSAVE_NAME)) {
- UserLots = GlobalVariableGet(LOTSSAVE_NAME);
- LotsLoaded = true ;
- }
- UserLots = AdjLots(UserLots);
- Lots = CalcLotsFromSlDistance(Stoploss,true) ;
- CurBid=PrevBid = GetBid() ;
- CurAsk=PrevAsk = GetAsk() ;
- UserMethod = OrderMethod ;
- if(UserMethod==ORDERMETHOD_TWO_STEPS) {
- if(Stoploss<=0.0) { // ストップロスがゼロ以下では2ステップモードの発動は不可能
- PrintMessage("Order method on user entry was force set to 1 click due to stoploss<=0");
- UserMethod = ORDERMETHOD_ONE_CLICK;
- }
- }
- //ストップロス更新確認用配列
- StoplossTrapArray = new CArrayObj();
- StoplossTrapArray.Sort(ARRAY_SORT_ASCEND);
- //DEBUG INFO
- if(DBGMODE) {
- ObjectCreate(0, DBGINFO_NAME, OBJ_LABEL, 0, 0, 0);
- ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_YDISTANCE, 15);
- ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
- ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
- 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(0, AMOUNT_NAME, OBJ_LABEL, 0, 0, 0);
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_XDISTANCE, 20);
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
- ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
- 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, ClrAmountPosi);
- }
- const int z_order = 1 ;
- //ユーザーエントリ用ボタン
- if(ShowUserEntry) {
- int edit_y_pos = 20;
- int btn_y_pos = edit_y_pos + 24;
- // < 減らすボタン
- ObjectCreate(0, LOTSDEC_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_YDISTANCE, edit_y_pos);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_XSIZE, 20);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_YSIZE, 20);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_COLOR, clrWhite);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_BGCOLOR, clrDimGray);
- ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, LOTSDEC_NAME, OBJPROP_TEXT, "<");
- ObjectSetString (0, LOTSDEC_NAME, OBJPROP_FONT, "Verdana");
- // エディットボックス
- ObjectCreate(0, LOTSED_NAME, OBJ_EDIT, 0, 0, 0);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_XDISTANCE, 31);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_YDISTANCE, edit_y_pos);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_XSIZE, 66);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_YSIZE, 20);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, LOTSED_NAME, OBJPROP_TEXT, DoubleToString(UserLots,2)+(LotsLoaded?"":"-"));
- ObjectSetInteger(0, LOTSED_NAME, OBJPROP_ALIGN, ALIGN_CENTER);
- ObjectSetString(0, LOTSED_NAME, OBJPROP_TOOLTIP,
- "Enter the lot size\n"
- "Press the < > button, then dec/inc lots step by " + DoubleToString(StepLots, 2) + "\n"
- "NOTE: It will be adjusted to the R/T lots if the text ends with a '-'" );
- // > 増やすボタン
- ObjectCreate(0, LOTSINC_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_XDISTANCE, 98);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_YDISTANCE, edit_y_pos);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_XSIZE, 20);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_YSIZE, 20);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_COLOR, clrWhite);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_BGCOLOR, clrDimGray);
- ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, LOTSINC_NAME, OBJPROP_TEXT, ">");
- ObjectSetString (0, LOTSINC_NAME, OBJPROP_FONT, "Verdana");
- //SELLボタン
- ObjectCreate(0, SELLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_YDISTANCE, btn_y_pos);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_XSIZE, 53);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_YSIZE, 27);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_FONTSIZE, 12);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_COLOR, White);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString(0, SELLBTN_NAME, OBJPROP_TEXT, "SELL");
- ObjectSetString(0, SELLBTN_NAME, OBJPROP_FONT, "Verdana");
- //BUYボタン
- ObjectCreate(0, BUYBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_XDISTANCE, 65);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_YDISTANCE, btn_y_pos);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_XSIZE, 53);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_YSIZE, 27);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_FONTSIZE, 12);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_COLOR, White);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString(0, BUYBTN_NAME, OBJPROP_TEXT, "BUY");
- ObjectSetString(0, BUYBTN_NAME, OBJPROP_FONT, "Verdana");
- UserEntryBtnYPos = btn_y_pos+30 ;
- }
- int btn_ofs_x = 0 ;
- const int btn_distance = 102 ;
- //全決済ボタン
- if(ShowCloseAll) {
- ObjectCreate(0, CLOSEALLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_LOWER);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_COLOR, clrWhite);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_BGCOLOR, clrDarkSlateGray);
- ObjectSetInteger(0, CLOSEALLBTN_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, CLOSEALLBTN_NAME, OBJPROP_TEXT, "CLOSE ALL");
- ObjectSetString (0, CLOSEALLBTN_NAME, OBJPROP_FONT, "Verdana");
- btn_ofs_x += btn_distance;
- }
- //LONG決済ボタン
- if(ShowCloseLong) {
- ObjectCreate(0, CLOSELONGBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_LOWER);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_COLOR, clrWhite);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
- ObjectSetInteger(0, CLOSELONGBTN_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, CLOSELONGBTN_NAME, OBJPROP_TEXT, "CLOSE LONG");
- ObjectSetString (0, CLOSELONGBTN_NAME, OBJPROP_FONT, "Verdana");
- btn_ofs_x += btn_distance;
- }
- //SHORT決済ボタン
- if(ShowCloseShort) {
- ObjectCreate(0, CLOSESHORTBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_LOWER);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_COLOR, clrWhite);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
- ObjectSetInteger(0, CLOSESHORTBTN_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, CLOSESHORTBTN_NAME, OBJPROP_TEXT, "CLOSE SHORT");
- ObjectSetString (0, CLOSESHORTBTN_NAME, OBJPROP_FONT, "Verdana");
- btn_ofs_x += btn_distance;
- }
- //TLフラッシュ決算ボタン
- if(ShowFlushTL) {
- ObjectCreate(0, FLUSHTLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_YDISTANCE, 35);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_XSIZE, 100);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_YSIZE, 25);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_LOWER);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_FONTSIZE, 10);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_COLOR, clrWhite);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_BGCOLOR, clrDarkSlateBlue);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_ZORDER, z_order);
- ObjectSetString (0, FLUSHTLBTN_NAME, OBJPROP_TEXT, "FLUSH TL");
- ObjectSetString (0, FLUSHTLBTN_NAME, OBJPROP_FONT, "Verdana");
- }
- //ユーザーエントリをリセット
- UserEntry=0;
- return(INIT_SUCCEEDED);
- }
- //---------------------------------------------------------------------------
- void OnDeinit(const int reason)
- {
- if(ShowBEP) BEPDelete(FLAG_BUY|FLAG_SELL,true);
- if(ShowFlushTL) ObjectDelete(0, FLUSHTLBTN_NAME);
- if(ShowCloseShort) ObjectDelete(0, CLOSESHORTBTN_NAME) ;
- if(ShowCloseLong) ObjectDelete(0, CLOSELONGBTN_NAME) ;
- if(ShowCloseAll) ObjectDelete(0, CLOSEALLBTN_NAME) ;
- if(ShowUserEntry) {
- LeaveUserOrdering();
- string lots_str = ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT) ;
- int ln = StringLen(lots_str);
- if(ln>0) {
- if(lots_str[ln-1]=='-') {
- if(GlobalVariableCheck(LOTSSAVE_NAME))
- GlobalVariableDel(LOTSSAVE_NAME);
- }else {
- double lots = StringToDouble(lots_str);
- if(lots>0) {
- lots = AdjLots(lots) ;
- if(UserLots!=lots) {
- UserLots = lots ;
- GlobalVariableSet(LOTSSAVE_NAME, UserLots);
- }
- }
- }
- }
- ObjectDelete(0, BUYBTN_NAME);
- ObjectDelete(0, SELLBTN_NAME);
- ObjectDelete(0, LOTSINC_NAME);
- ObjectDelete(0, LOTSDEC_NAME);
- ObjectDelete(0, LOTSED_NAME);
- }
- if(OffTimeVisible) {
- ObjectDelete(0, OFFTIME_NAME) ;
- OffTimeVisible=false ;
- }
- if(ShowAmount) {
- ObjectDelete(0, AMOUNT_NAME) ;
- }
- if(DBGMODE) {
- ObjectDelete(0, DBGINFO_NAME) ;
- }
- if(StoplossTrapArray!=NULL) {
- delete StoplossTrapArray ;
- StoplossTrapArray = NULL ;
- }
- }
- //---------------------------------------------------------------------------
- void OnTick()
- {
- datetime nextTime = MainTime() ;
- bool nextTimed = nextTime != CurTime ;
- CurTime = nextTime ;
- datetime nextTick = BaseTime(TimeBase) ;
- bool nextTicked = nextTick != TimeTick ;
- TimeTick = nextTick;
- CurBid = GetBid(); CurAsk = GetAsk();
- // キュー更新
- QiFastMA .Update();
- QiMediumMA .Update();
- QiSlowMA .Update();
- QiATR14 .Update();
- // タイムコントロールチェック
- CheckTimeControl(nextTicked);
- // 動作チェック
- CheckBehavior(nextTimed);
- double atr14 = QiATR14.latest() ;
- double spread = CurAsk-CurBid ;
- // デバッグ欄表示のサンプル
- 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))
- );
- }
- // ユーザーオーダー予約情報更新
- UpdateUserOrdering();
- // ユーザーロット情報自動更新(ロットの最後が'-'で終わっている場合)
- if(ShowUserEntry) {
- string LotsStr = ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT) ;
- int ln = StringLen(LotsStr);
- if(ln>0) {
- if(LotsStr[ln-1]=='-') {
- if(UserLots!=Lots) {
- UserLots = Lots;
- ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT, DoubleToString(UserLots, 2)+"-");
- }
- }
- }
- }
- // エントリー処理
- if( AccountInfoInteger(ACCOUNT_TRADE_EXPERT) &&
- TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) ) {
- FLAG busy = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA) ;
- // ユーザーの注文
- if(UserEntry) {
- // ユーザーのエントリを確認
- if(TimeTick-UserTime<60) { // 発行されてから60秒以内の注文
- FLAG user = UserEntry ;
- // 注文
- if(user/*&&!AlreadyOrdered(user,MAGICMA)*/) {
- // ユーザーロット取得と更新
- if(ShowUserEntry) {
- double lots = StringToDouble(ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT));
- if(lots>0) {
- lots = AdjLots(lots) ;
- if(UserLots!=lots) {
- UserLots = lots ;
- GlobalVariableSet(LOTSSAVE_NAME, UserLots);
- }
- }
- }
- OP entry = user == FLAG_BUY ? OP_BUY : OP_SELL ;
- if(EntryManualPosition("USER", entry, UserLots, UserStoploss, UserTakeprofit)>0)
- busy |= user ;
- else {
- PrintMessage("Order failed by USER.");
- PlaySound("timeout.wav");
- }
- LeaveUserOrdering();
- UserEntry=0;
- }
- }else { UserEntry=0; }
- }
- // MARK: 自動注文
- /*
- do {
- // 自動注文 開始時間調整
- if(StartTime>TimeTick||CancelTime>TimeTick)
- break ;
- // スプレッド幅のチェック
- if(MarketInfo(NULL,MODE_SPREAD) > Spread)
- break ;
- // 自動注文 XMA+ZigZag Detector
- if(nextTimed)
- EAEntryXMAZigZagPosition(busy,1);
- }while(0);
- */
- }else {
- if(StartTime-TimeTick<10)
- StartTime = TimeTick+10 ;
- }
- /*
- if(PmdTiming) {
- PmdPrevBid = (PmdPrevBid+Bid)/2.0 ; PmdPrevAsk = (PmdPrevAsk+Ask)/2.0 ;
- }*/
- PrevBid = CurBid ; PrevAsk = CurAsk ;
- }
- //---------------------------------------------------------------------------
- void OnChartEvent(
- const int id,
- const long &lparam,
- const double &dparam,
- const string &sparam
- )
- {
- if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == LOTSED_NAME) {
- string lotsStr = ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT);
- int ln = StringLen(lotsStr);
- bool invalid = true ;
- if(ln > 0 && lotsStr[ln-1] != '-') {
- // 数値として評価してチェック
- double lots = StringToDouble(lotsStr);
- if(lots > 0) {
- // 正常値 → AdjLots で丸めて反映
- lots = AdjLots(lots);
- UserLots = lots;
- GlobalVariableSet(LOTSSAVE_NAME, UserLots);
- ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT,
- DoubleToString(UserLots, 2));
- invalid = false ; // 適正値
- }
- }
- if(invalid) { // 不正値、または、自動ロット設定値("-"で終わる場合)
- UserLots = Lots;
- ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT,
- DoubleToString(Lots, 2) + "-");
- }
- }
- if(id == CHARTEVENT_OBJECT_CLICK &&
- (sparam == LOTSDEC_NAME || sparam == LOTSINC_NAME)) {
- double lots = StringToDouble(ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT));
- lots += (sparam == LOTSINC_NAME ? +StepLots : -StepLots);
- lots = AdjLots(lots);
- UserLots = lots;
- GlobalVariableSet(LOTSSAVE_NAME, UserLots);
- ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT, DoubleToString(UserLots, 2));
- Sleep(100);
- ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
- }
- 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 ;
- CheckoutOrders(orderFlag);
- Sleep(100);
- ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
- // 60秒エントリーを停止する
- CancelTime = TimeTick + 60 ;
- }
- if(sparam == FLUSHTLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
- FlushTL=true;
- Sleep(100);
- ObjectSetInteger(0, FLUSHTLBTN_NAME, OBJPROP_STATE, false);
- }
- if(sparam == SELLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
- switch(UserMethod) {
- case ORDERMETHOD_ONE_CLICK:
- DecideUserOrdering(FLAG_SELL);
- Sleep(100);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_STATE, false);
- break;
- case ORDERMETHOD_TWO_STEPS:
- ToggleUserOrdering(FLAG_SELL);
- break;
- }
- }
- if(sparam == BUYBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
- switch(UserMethod) {
- case ORDERMETHOD_ONE_CLICK:
- DecideUserOrdering(FLAG_BUY);
- Sleep(100);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_STATE, false);
- break;
- case ORDERMETHOD_TWO_STEPS:
- ToggleUserOrdering(FLAG_BUY);
- break;
- }
- }
- if(sparam == ENTRYBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
- DecideUserOrdering(UserMode);
- Sleep(100);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_STATE, false);
- }
- }
- //---------------------------------------------------------------------------
- // MARK: ユーザーオーダー予約
- //-----
- // ユーザーオーダー予約決定
- void DecideUserOrdering(FLAG UserOrderFlag)
- {
- UserEntry = UserOrderFlag ;
- CancelTime = UserTime = TimeTick ; CancelTime+=60 ;
- }
- //-----
- // ユーザーオーダー予約状態のトグル切替
- void ToggleUserOrdering(FLAG modFlag)
- {
- bool buyDn = (bool)ObjectGetInteger(0, BUYBTN_NAME, OBJPROP_STATE);
- bool sellDn = (bool)ObjectGetInteger(0, SELLBTN_NAME, OBJPROP_STATE);
- switch(modFlag) {
- case FLAG_BUY:
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_STATE, false);
- sellDn=false;
- break;
- case FLAG_SELL:
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_STATE, false);
- buyDn=false;
- break;
- }
- FLAG mode = 0 ;
- if(buyDn) mode |= FLAG_BUY ;
- if(sellDn) mode |= FLAG_SELL ;
- if(!mode||mode==(FLAG_BUY|FLAG_SELL)) {
- // オーダー予約取消
- LeaveUserOrdering();
- return ;
- }
- // オーダー予約開始
- EnterUserOrdering(mode);
- }
- //-----
- // ユーザーオーダー予約開始
- void EnterUserOrdering(FLAG UserOrderMode)
- {
- //ENTRYボタン
- ObjectCreate(0, ENTRYBTN_NAME, OBJ_BUTTON, 0, 0, 0);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_YDISTANCE, UserEntryBtnYPos);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_XSIZE, 108);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_YSIZE, 27);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_FONTSIZE, 12);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_COLOR, White);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_BGCOLOR, clrDarkOrchid);
- ObjectSetInteger(0, ENTRYBTN_NAME, OBJPROP_ZORDER, 1);
- ObjectSetString(0, ENTRYBTN_NAME, OBJPROP_TEXT, "ENTRY");
- ObjectSetString(0, ENTRYBTN_NAME, OBJPROP_FONT, "Verdana");
- double slDist = Stoploss*_Point;
- double slPrice = UserOrderMode==FLAG_BUY ? CurAsk-slDist : CurBid+slDist ;
- double tpDist = Takeprofit*_Point;
- double tpPrice = UserOrderMode==FLAG_BUY ? CurAsk+tpDist : CurBid-tpDist ;
- //ストップロス調整用ライン
- ObjectCreate(0, SLLINE_NAME, OBJ_HLINE, 0, 0, slPrice);
- ObjectSetInteger(0, SLLINE_NAME, OBJPROP_COLOR, ClrUserStoploss);
- ObjectSetInteger(0, SLLINE_NAME, OBJPROP_WIDTH, 2);
- ObjectSetInteger(0, SLLINE_NAME, OBJPROP_SELECTABLE, true);
- ObjectSetInteger(0, SLLINE_NAME, OBJPROP_SELECTED, true); // すぐ動かせるように
- ObjectSetString(0, SLLINE_NAME, OBJPROP_TEXT,
- "Entry SL "+DoubleToString(slPrice,_Digits));
- ObjectSetString(0, SLLINE_NAME, OBJPROP_TOOLTIP,
- "Move S/L, next press the ENTRY button to open your position.");
- //テイクプロフィット確認用ライン
- if(Takeprofit>0.0) {
- ObjectCreate(0, TPLINE_NAME, OBJ_HLINE, 0, 0, tpPrice);
- ObjectSetInteger(0, TPLINE_NAME, OBJPROP_COLOR, ClrUserTakeprofit);
- ObjectSetInteger(0, TPLINE_NAME, OBJPROP_WIDTH, 2);
- ObjectSetInteger(0, TPLINE_NAME, OBJPROP_SELECTABLE, false);
- ObjectSetString(0, TPLINE_NAME, OBJPROP_TEXT,
- "Entry TP "+DoubleToString(tpPrice,_Digits));
- ObjectSetString(0, TPLINE_NAME, OBJPROP_TOOLTIP, "Estimated T/P");
- }
- UserMode = UserOrderMode ;
- UpdateUserOrdering();
- }
- //-----
- // ユーザーオーダー予約終了
- void LeaveUserOrdering()
- {
- ObjectDelete(0, TPLINE_NAME);
- ObjectDelete(0, SLLINE_NAME);
- ObjectDelete(0, ENTRYBTN_NAME);
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_STATE, false);
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_STATE, false);
- UserStoploss = 0 ;
- UserTakeprofit = 0 ;
- UserMode = 0 ;
- }
- //-----
- // ユーザーオーダー予約更新
- void UpdateUserOrdering()
- {
- if(UserMode) {
- double slPrice = ObjectGetDouble(0, SLLINE_NAME, OBJPROP_PRICE);
- switch(UserMode) {
- case FLAG_BUY:
- if(slPrice>CurAsk) {
- ObjectSetInteger(0, SELLBTN_NAME, OBJPROP_STATE, true);
- ToggleUserOrdering(FLAG_SELL);
- ObjectSetDouble(0, SLLINE_NAME, OBJPROP_PRICE, slPrice);
- }
- break;
- case FLAG_SELL:
- if(slPrice<CurBid) {
- ObjectSetInteger(0, BUYBTN_NAME, OBJPROP_STATE, true);
- ToggleUserOrdering(FLAG_BUY);
- ObjectSetDouble(0, SLLINE_NAME, OBJPROP_PRICE, slPrice);
- }
- break;
- }
- double slDist = UserMode==FLAG_BUY ? CurAsk-slPrice : slPrice-CurBid ;
- Lots = CalcLotsFromSlDistance(slDist/_Point,true);
- ObjectSetString(0, SLLINE_NAME, OBJPROP_TEXT,
- "Entry SL "+DoubleToString(slPrice,_Digits));
- UserStoploss = slPrice ;
- if(Takeprofit>0.0) {
- double ratioRR = Takeprofit/Stoploss ;
- double tpDist = slDist * ratioRR ;
- double commDist = MathAbs(CalcCommissionPointsFromTime(
- CurTime,UserMode==FLAG_BUY?BuyWholeStatus:SellWholeStatus)) * _Point ;
- double tpPrice = UserMode==FLAG_BUY ?
- tpDist+CurAsk+commDist : CurBid-tpDist-commDist ;
- ObjectSetDouble(0, TPLINE_NAME, OBJPROP_PRICE, tpPrice);
- ObjectSetString(0, TPLINE_NAME, OBJPROP_TEXT,
- "Entry TP "+DoubleToString(tpPrice,_Digits));
- UserTakeprofit = tpPrice ;
- }
- }else {
- Lots = CalcLotsFromSlDistance(Stoploss,true);
- }
- }
- //---------------------------------------------------------------------------
- // MARK: BEP ( Break Even Price )
- #define BEPLONG_NAME "BEPLong"
- #define BEPSHORT_NAME "BEPShort"
- FLAG BEPFlag=0;
- //-----
- void BEPDelete(FLAG flag, bool force=false)
- {
- if((flag&FLAG_BUY)!=0&&(force||(BEPFlag&FLAG_BUY)!=0)) {
- ObjectDelete(0, BEPLONG_NAME);
- BEPFlag &= ~FLAG_BUY ;
- }
- if((flag&FLAG_SELL)!=0&&(force||(BEPFlag&FLAG_SELL)!=0)) {
- ObjectDelete(0, BEPSHORT_NAME);
- BEPFlag &= ~FLAG_SELL ;
- }
- }
- //-----
- void BEPUpdate(const STATUS &Status)
- {
- FLAG flag = Status.Flag ;
- if(!Status.Positions) {
- BEPDelete(flag);
- return ;
- }
- double bep = Status.BorderPrice ;
- color col = (flag&FLAG_BUY)!=0 ? ClrBEPLong : ClrBEPShort ;
- string nam = (flag&FLAG_BUY)!=0 ? BEPLONG_NAME : BEPSHORT_NAME ;
- string tip = (flag&FLAG_BUY)!=0 ? "LONG BEP" : "SHORT BEP" ;
- if((flag&BEPFlag)!=0) { // BEP 表示中
- ObjectSetDouble(0, nam, OBJPROP_PRICE, bep);
- }else { // 新規
- ObjectCreate(0, nam, OBJ_HLINE, 0, 0, bep);
- ObjectSetInteger(0, nam, OBJPROP_COLOR, col);
- ObjectSetInteger(0, nam, OBJPROP_STYLE, STYLE_DOT);
- ObjectSetInteger(0, nam, OBJPROP_SELECTABLE, false);
- ObjectSetString(0, nam, OBJPROP_TOOLTIP, tip );
- BEPFlag |= flag ;
- }
- ObjectSetString(0, nam, OBJPROP_TEXT, tip+" "+DoubleToString(bep,_Digits));
- }
- //---------------------------------------------------------------------------
- //DBGOUT
- void DBGOUT(string text)
- {
- if(DBGMODE) {
- ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, text);
- }
- }
- //---------------------------------------------------------------------------
- //タイムコントロールチェック
- void CheckTimeControl(bool nextTicked)
- {
- if(!TimeControl) {
- if(OffTimeVisible) {
- ObjectDelete(0, OFFTIME_NAME);
- OffTimeVisible = false ;
- }
- return ;
- }
- if(!nextTicked) return ;
- if(!ControlTimeAction(
- TimeTick,StringToTime(TimeStart),StringToTime(TimeEnd),
- StartTime,MAGICMA,TimeAction)) {
- datetime timOff = StartTime - TimeTick ;
- if(!OffTimeVisible) {
- // OFF TIME テキストを表示
- ObjectCreate(0, OFFTIME_NAME, OBJ_LABEL, 0, 0, 0);
- ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_XDISTANCE, 10);
- ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_YDISTANCE, 25);
- ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
- ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
- 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 ;
- }
- }else if(OffTimeVisible) {
- ObjectDelete(0, OFFTIME_NAME);
- OffTimeVisible = false ;
- }
- }
- //---------------------------------------------------------------------------
- //メインタイムを返す
- datetime MainTime(int shift=0)
- {
- return iTime(Symbol(), MainTimeFrame, shift);
- }
- //---------------------------------------------------------------------------
- //メインPERIODを返す
- int MainPeriod()
- {
- int period = MainTimeFrame ;
- if(!period) period = Period();
- return period ;
- }
- //---------------------------------------------------------------------------
- //金額表示の更新
- void UpdateAmount(double amount, int positions)
- {
- if(ShowAmount) {
- if(positions>0) {
- string s = DoubleToAmount(amount,(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS)) ;
- 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+"-");
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- //MARK:動作チェック
- void CheckBehavior(bool nextTimed)
- {
- // 全体のステータスを取得
- for(int n=0;n<2;n++) {
- CheckStatus(OP_BUY, MAGICMA, &BuyWholeStatus);
- BuyWholeStatus.OrdersSort(ORDERSORT_PRICE_ASCEND);
- if(!CheckoutStoplossTrappedOrders(&BuyWholeStatus)) break;
- }
- for(int n=0;n<2;n++) {
- CheckStatus(OP_SELL, MAGICMA, &SellWholeStatus);
- SellWholeStatus.OrdersSort(ORDERSORT_PRICE_DESCEND);
- if(!CheckoutStoplossTrappedOrders(&SellWholeStatus)) break;
- }
- StoplossTrapArray.Clear();
- // BEP 更新
- if(ShowBEP) {
- BEPUpdate(BuyWholeStatus);
- BEPUpdate(SellWholeStatus);
- }
- // 金額を更新
- double CurAmount = BuyWholeStatus.GrossProfit+SellWholeStatus.GrossProfit ;
- int CurPositions = BuyWholeStatus.Positions+SellWholeStatus.Positions ;
- UpdateAmount(CurAmount,CurPositions);
- // 自動処理
- if(Automation) {
- // 最大損益のチェック
- if(CurAmount<0) {
- double balance = AccountInfoDouble(ACCOUNT_BALANCE);
- if(BalanceIncludeCredit) balance += AccountInfoDouble(ACCOUNT_CREDIT);
- double equity = AccountInfoDouble(ACCOUNT_EQUITY);
- bool grossloss = balance*MaxGrosslossPer/100.0<=-CurAmount ;
- bool drawdown = balance*MaxDrawDownPer/100.0<=balance-equity ;
- if( grossloss || drawdown ) {
- //最大損益を超えた場合は、すべて決済する
- CheckoutOrders(FLAG_BUY|FLAG_SELL);
- string reason = grossloss ?
- "over Maximum Allowed Gross loss" :
- "over Maximum Allowed Draw down" ;
- PrintMessage("Check-out orders by " + reason);
- return;
- }
- }
- // オーダーの処理
- ProcessOrders(nextTimed, OP_BUY, BuyWholeStatus, SellWholeStatus);
- ProcessOrders(nextTimed, OP_SELL, SellWholeStatus, BuyWholeStatus);
- }
- FlushTL=false;
- }
- //---------------------------------------------------------------------------
- //MARK:オーダーの処理
- void ProcessOrders(bool nextTimed, OP orderType, const STATUS &status, const STATUS &revStatus)
- {
- if(status.Positions<=0) return ;
- // トレーリング
- if(Trailing) {
- double tstart = TrailingStart*_Point ;
- double tstop = TrailingStop*_Point ;
- double minPadding = tstart+tstop ;
- for(int i=0;i<status.OrdersCount();i++) {
- COrderStatus *order = status.OrdersAt(i) ;
- if((order.Tag&STATAG_CHECKEDOUT)!=0) continue ; // 決済済
- if( orderType==OP_BUY ?
- order.BorderPrice>CurBid-minPadding : order.BorderPrice<CurAsk+minPadding )
- break;
- double sl=0.0 ;
- if( order.Stoploss==0.0 ||
- ( orderType==OP_BUY ?
- order.Stoploss<order.BorderPrice : order.Stoploss>order.BorderPrice ) ) {
- //初回トレール
- sl = orderType==OP_BUY ? order.BorderPrice+tstart : order.BorderPrice-tstart ;
- }else {
- //既にトレール済
- sl = order.Stoploss ;
- }
- while( ( orderType==OP_BUY ? CurBid-sl : sl-CurAsk ) >= tstop*2 ) {
- //カクカクにトレール幅を狭めていく
- sl += orderType==OP_BUY ? +tstop : -tstop ;
- }
- if(!InnerPoint(sl,order.Stoploss)) {
- //ストップロスを更新
- if(ModifyOrderSlTp(order.Ticket,sl,order.Takeprofit)) {
- order.Stoploss = sl ;
- EntryStoplossTrap(orderType, order, sl);
- }else PrintLastError();
- }
- }
- }
- // 3EMA処理
- if(MA3 && (nextTimed||FlushTL)) {
- double HalfSpread = (CurAsk-CurBid)/2.0;
- double FastMA0 = QiFastMA.latest() +HalfSpread ;
- double MediumMA0 = QiMediumMA.latest() +HalfSpread ;
- double SlowMA0 = QiSlowMA.latest() +HalfSpread ;
- for(int i=0;i<status.OrdersCount();i++) {
- COrderStatus *order = status.OrdersAt(i) ;
- if((order.Tag&STATAG_CHECKEDOUT)!=0) continue ; // 決済済
- double price = order.InitialBorderPrice ;
- double sl = order.Stoploss ;
- double trail_sl=0.0;
- double checkout_denom=0.0;
- string checkout_reason="";
- if(InnerPoint(sl,price)) { // プライスがslに一致
- if(FlushTL&&!nextTimed) continue;
- if(!InnerPoint(MediumMA0,price) &&
- (orderType==OP_BUY?MediumMA0-HalfSpread>price:MediumMA0+HalfSpread<price)) { // Medium MA がプライス以上
- if(orderType==OP_BUY?FastMA0>CurAsk:FastMA0<CurBid) { // Fast MA が現価以上
- // 決済設定
- checkout_denom = LotsDenomMAFast ;
- checkout_reason = "Check-out by Fast MA" ;
- if(orderType==OP_BUY?MediumMA0>CurAsk:MediumMA0<CurBid) // Medium MA が現価より上
- { checkout_reason += " & Medium MA"; checkout_denom = 1.0 ;} // 全決済する
- // ストップロスを Medium MA 値に更新する
- trail_sl = MediumMA0 + (orderType==OP_BUY?-HalfSpread:+HalfSpread) ;
- }
- }
- }else if(sl!=0.0&&(orderType==OP_BUY?sl>price:sl<price)) { //プライスがslより下
- if(FlushTL&&!nextTimed) continue;
- if(orderType==OP_BUY?CurAsk<=MediumMA0:CurBid>=MediumMA0) { //現価が Medium MA より下になった
- // 決済設定
- checkout_denom = 1.0 ; // 全決済
- checkout_reason = "Check-out by Medium MA" ;
- }
- }else { //プライスがslより上、もしくは、slが設定されていない
- if(FlushTL||MA3TLPeriod>0) { // TL(TimeLimited) ポジションが有効
- //ロウソク足の期間を計測
- /* 旧方式
- datetime tperiod = MainPeriod() * 60 ;
- int period = int((CurTime-order.OpenTime)/tperiod);
- bool overTime = period>=MA3TLPeriod-1 ;
- */
- // 新方式
- int period = Bars(_Symbol, MainTimeFrame, order.OpenTime, CurTime);
- bool overTime = period>=MA3TLPeriod ;
- if(FlushTL||overTime) { //TL(TimeLimited)期間が過ぎている
- if(orderType==OP_BUY?CurBid>price:CurAsk<price) { // 利確できる位置にある
- if(!FlushTL&&(orderType==OP_BUY?FastMA0>CurAsk||MediumMA0>CurAsk:FastMA0<CurBid||MediumMA0<CurBid)) { // 2MA が現価より上
- // 現価が 2MA を抜かすまでの間、ストップロスを建値ギリギリまで引き上げておく
- trail_sl = price + (orderType==OP_BUY?-_Point:+_Point);
- }else { // FastMA が現価以下
- // 決済設定
- checkout_denom = LotsDenomTL ;
- checkout_reason = "Check-out by TL(TimeLimited)" ;
- // ストップロスを建値に引き上げる
- trail_sl = price ;
- }
- }
- }
- }
- if(!FlushTL||nextTimed) {
- if(sl==0.0) { //ストップロスが設定されていない
- if(MaxGrosslossPer>=100.0) { // Max Gross loss が 100%以上
- if(orderType==OP_BUY?CurAsk<=SlowMA0:CurBid>=SlowMA0) { //現価が Slow MA より下になった
- // 損切設定
- checkout_denom = 1.0 ; // 全決済
- checkout_reason = "Loss-cut order by Slow MA" ;
- }
- }
- }
- }
- }
- if(trail_sl!=0.0) {
- //MAによるトレーリング
- if(sl==0.0||(!InnerPoint(sl,trail_sl)&&(orderType==OP_BUY?sl<trail_sl:sl>trail_sl))) {
- sl = trail_sl ;
- if(ModifyOrderSlTp(order.Ticket,sl,order.Takeprofit)) {
- order.Stoploss = sl ;
- EntryStoplossTrap(orderType, order, sl);
- }else PrintLastError();
- }
- }
- if(checkout_denom>0.0) {
- //MAによる決済処理
- double lots = AdjLots(order.Lots/checkout_denom) ;
- if(lots<MinLots) lots = MinLots ;
- if(lots>order.Lots) lots = order.Lots ;
- if(CheckoutOrder(orderType,order.Ticket,lots)) {
- PrintMessage(checkout_reason);
- order.Lots -= lots ;
- if(order.Lots<=0)
- order.Tag |= STATAG_CHECKEDOUT ; // 決済済
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- //マニュアルポジション発注
- TICKET EntryManualPosition(string detector, OP entryType, double lots,
- double sl=0.0, double tp=0.0)
- {
- double slDist = Stoploss*_Point ;
- double tpDist = Takeprofit*_Point ;
- double ratioRR = tpDist/slDist ;
- if(sl>0.0) {
- slDist = MathAbs( entryType==OP_BUY ? CurAsk-sl : sl-CurBid );
- tpDist = slDist * ratioRR ;
- }
- if(tpDist!=0.0)
- tpDist += MathAbs(CalcCommissionPointsFromTime(
- CurTime,entryType==OP_BUY?BuyWholeStatus:SellWholeStatus))*_Point;
- if(tp>0.0) {
- tpDist = MathAbs( entryType==OP_BUY ? tp-CurAsk : CurBid-tp );
- }
- switch(entryType) {
- case OP_BUY:
- if(slDist!=0.0) sl = CurAsk-slDist ;
- if(sl>0.0&&sl>=CurBid) {
- PrintMessage("Entring failed due to s/l over BID reached");
- return 0 ; // invalid
- }
- if(tpDist!=0.0) tp = CurAsk+tpDist ;
- break;
- case OP_SELL:
- if(slDist!=0.0) sl = CurBid+slDist ;
- if(sl>0.0&&sl<=CurAsk) {
- PrintMessage("Entring failed due to s/l under ASK reached");
- return 0 ; // invalid
- }
- if(tpDist!=0.0) tp = CurBid-tpDist ;
- break;
- }
- if(sl==0.0) {
- if(MaxGrosslossPer>=100.0) {
- // SlowMAの現在位置がAsk/Bidよりも上回っていないことを確認する
- double HalfSpread = (CurAsk-CurBid)/2.0;
- double SlowMA0 = QiSlowMA.latest()+HalfSpread ;
- if(entryType==OP_BUY?SlowMA0>=CurAsk:SlowMA0<=CurBid) {
- string reason = entryType==OP_BUY ? "over" : "under" ;
- PrintMessage("Entring failed due to Slow MA "+reason+" price reached");
- return 0 ; // invalid
- }
- }
- }
- return MakeOrder(entryType,lots,sl,tp,detector,MAGICMA);
- }
- //---------------------------------------------------------------------------
- //マジックナンバーと一致する全オーダーのチェックアウト
- void CheckoutOrders(FLAG flag)
- {
- CheckoutOrderAll(flag,MAGICMA);
- }
- //---------------------------------------------------------------------------
- // オーダーを StoplossTrapArray に登録
- bool EntryStoplossTrap(OP type, const COrderStatus *order, double stoploss=0)
- {
- if(stoploss==0) stoploss = order.Stoploss ;
- if(stoploss==0) return false ;
- OBJECT_PARTCLOSED part(order.Ticket,type,order.Price,order.OpenTime,stoploss);
- int idx = SearchSortedArray(StoplossTrapArray,part);
- if(idx>=0) { // 既にエントリ済
- CSortable<OBJECT_PARTCLOSED>* obj =
- (CSortable<OBJECT_PARTCLOSED>*)StoplossTrapArray.At(idx) ;
- obj.v.Stoploss = stoploss ; // ストップロスの値を更新
- }else { // 新規エントリ
- AddToSortedArray(StoplossTrapArray,part);
- }
- return true ;
- }
- //---------------------------------------------------------------------------
- // オーダーのストップロスが前回登録したストップロス情報と一致しているか調べる
- bool CheckStoplossTrap(OP type, const COrderStatus *order, double stoploss=0)
- {
- if(stoploss==0) stoploss = order.Stoploss ;
- if(stoploss==0) return true ; // 無視
- OBJECT_PARTCLOSED part(order.Ticket,type,order.Price,order.OpenTime,stoploss);
- int idx = SearchSortedArray(StoplossTrapArray,part);
- if(idx>=0) { // 既にエントリ済
- CSortable<OBJECT_PARTCLOSED>* obj =
- (CSortable<OBJECT_PARTCLOSED>*)StoplossTrapArray.At(idx) ;
- return InnerPoint(obj.v.Stoploss, stoploss); // ストップロスの一致を返す
- }
- return true ; // エントリされていないので無視
- }
- //---------------------------------------------------------------------------
- // ストップロスが更新されていないオーダーを全て決済する
- int CheckoutStoplossTrappedOrders(STATUS *status)
- {
- int n=0;
- for(int i=status.OrdersCount()-1;i>=0;i--) {
- COrderStatus *order = status.OrdersAt(i);
- if((order.Tag&STATAG_CHECKEDOUT)!=0) continue ;
- if(!CheckStoplossTrap(status.Type,order)) {
- if(CheckoutOrder(status.Type,order.Ticket,order.Lots)) {
- order.Lots = 0 ;
- order.Tag |= STATAG_CHECKEDOUT ;
- PrintMessage("Checkout Order by ST(StoplossTrapped)");
- n++;
- }
- }
- }
- return n;
- }
- //---------------------------------------------------------------------------
- //MARK: ストップロスの幅からロットを換算して返す @ 2026/06/23
- double CalcLotsFromSlDistance(double slPoints, bool adjustable=false)
- {
- // 口座残高を計算
- double balance = AccountInfoDouble(ACCOUNT_BALANCE);
- if(BalanceIncludeCredit) balance += AccountInfoDouble(ACCOUNT_CREDIT);
- double equity = AccountInfoDouble(ACCOUNT_EQUITY);
- // 口座残高のRTPer%をリスク額とする
- double riskAmount = MathMin(balance, equity) * RTPer/100.0 ;
- // リスク額とS/Lから生ロット値計算
- double rawLot = 0.0;
- switch(RTCalcType) {
- case RTCALCTYPE_I:
- rawLot = CalcLotsFromSlDistance_TYPE_I(slPoints, riskAmount) ;
- break;
- case RTCALCTYPE_II:
- rawLot = CalcLotsFromSlDistance_TYPE_II(slPoints, riskAmount) ;
- break;
- }
- return adjustable ? AdjLots(rawLot) : rawLot ;
- }
- //-----(TYPE-I)-----
- //SymbolInfoDouble(SYMBOL_TRADE_...)系から情報を取得して換算する
- //(※サーバー側が間違った情報を返す場合は、正常に機能しないことがある)
- double CalcLotsFromSlDistance_TYPE_I(double slPoints, double riskAmount)
- {
- // ティックサイズ(値幅の最小単位)を得る
- double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
- // 1ロットあたり、1ポイント動いた時の価格を取得
- //double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
- // 1ロットあたり、1ポイント動いた時の価格(口座通貨ベース)を取得
- double tickValueProfit = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE_PROFIT);
- // ポイント値をティック数に換算
- double stopTicks = (slPoints * _Point) / tickSize ;
- // ロット数を計算 (リスク額 / (S/Lのティック数 * 1ティックの口座価値))
- double rawLot = riskAmount / (stopTicks * tickValueProfit);
- return rawLot ;
- }
- //-----(TYPE-II)-----
- //MT5が自前で用意しているOrderCalcProfit関数から損益を取得してロットを換算する
- double CalcLotsFromSlDistance_TYPE_II(double slPoints, double riskAmount)
- {
- double price = CurAsk ;
- double sl = CurAsk - (slPoints * _Point);
- double lot1 = 1.0 ; // 1 lot
- double lossPerLot = 0.0 ;
- if(OrderCalcProfit(ORDER_TYPE_BUY, _Symbol, lot1, price, sl, lossPerLot)) {
- // 損失額はマイナスで返るため正数に変換
- double riskPerLot = MathAbs(lossPerLot);
- // ロット数を計算 (リスク額 / ロット当たりの損失額)
- double rawLot = riskAmount / riskPerLot ;
- return rawLot ;
- }
- return 0.0;
- }
- //---------------------------------------------------------------------------
- // タイム値から手数料に掛かる値幅(ポイント)を換算して返す
- double CalcCommissionPointsFromTime(datetime time, STATUS &status)
- {
- // 1ポイントあたりの利益額(口座通貨)
- double point_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE_PROFIT)
- / _Point ;
- if(point_value == 0) return 0;
- return status.USDJPYCommissionPerLotAt(time) / point_value ;
- }
- //---------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment