指标名称:虚拟下单
版本:MT4 ver. 2.01(指标)
虚拟下单指标是一款便于交易者计算所有订单盈亏平衡价格的工具。通过模拟订单的方式,让交易者在实际交易前安全地测试和调整策略。
虚拟下单,计算盈亏平衡点位,实际上就是保本位置。
主要功能:
-
虚拟订单创建:
-
交易者可以根据需求创建虚拟订单,并手动指定每个订单的数量。
-
指标将自动计算这些虚拟订单的平均价格。
-
灵活操作:
使用鼠标即可拖动虚拟订单,实时调整订单的位置和数量。
-
适用范围:
-
对于新手交易者:帮助熟悉交易逻辑,评估交易策略的盈亏平衡点。
-
对于经验丰富的交易者:作为模拟工具,优化复杂的订单组合或验证交易计划。
使用鼠标直接拖动虚拟订单到目标位置,指标会实时更新平均价格。
通过使用虚拟下单指标,交易者可以更安全、更精准地规划交易策略,提升交易成功率。在复盘和回测过程中很有效。
参数可调整默认手数。
部分代码展示:
//+------------------------------------------------------------------+
//| 虚拟下单.mq4 |
//| Copyright © 2009-2024, www.QChaos.com |
//| https://www.qchaos.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 量化混沌, www.qchaos.com"
#property link "https://www.qchaos.com"
#property version "2.01"
#property strict#property indicator_chart_window
#property indicator_plots 0
#property indicator_buffers 0string iPrefix = "Price";
input double iLots = 0.01;//默认手数
struct str{
protected:string m_name_orders;int m_type_orders;double m_lots_orders;double m_cena_orders;MqlTick tick;
public:string GetName(void) { return m_name_orders; }int GetType(void) { return m_type_orders; }double GetLots(void) { return m_lots_orders; }double GetCena(void) { return m_cena_orders; }void SetName(string aName) { m_name_orders = aName;}void SetType(int aType) { m_type_orders = aType;}void SetLots(double aLots) { m_lots_orders = aLots;}void SetCena(double aCena) { m_cena_orders = aCena;}void SetAWpr(string aName, datetime aTime, double aPrice){ObjectSetInteger(0, iPrefix + "D" + aName, OBJPROP_TIME, 1, TimeCurrent() + PeriodSeconds() * 5);ObjectSetDouble(0, iPrefix + "D" + aName, OBJPROP_PRICE, 1, aPrice);}bool CreateBuy(string aName){if(!SymbolInfoTick(Symbol(), tick)){Print("SymbolInfoTick() failed, error = ", GetLastError());return false;}m_name_orders = aName;m_type_orders = 0;m_lots_orders = iLots;m_cena_orders = NormalizeDouble(tick.bid, Digits());ButtonCreate(0, iPrefix + "A" + aName, 0, 0, 0, 30, 18, CORNER_LEFT_UPPER, "Buy", "Arial", 10, clrWhite, clrBlue, clrBlue, true, true, true, false, 0);EditCreate(0, iPrefix + "B" + aName, 0, 10, 30, 36, 18, DoubleToString(m_lots_orders, 2), "Arial", 10, ALIGN_CENTER, false, CORNER_LEFT_UPPER, clrWhite, clrGray, clrBlue, false, false, false, 0);TrendCreate(0, iPrefix + "D" + aName, 0, TimeCurrent() - PeriodSeconds() * 10, m_cena_orders, TimeCurrent() + PeriodSeconds() * 10, m_cena_orders, clrBlue, STYLE_SOLID, 1, false, false, false, false, true, 0);ArrowCreate(0, iPrefix + "C" + aName, 0, TimeCurrent() + PeriodSeconds() * 10, m_cena_orders, clrBlue, STYLE_SOLID, 2, false, true, true, 0);OrderDrag(aName);return true;}bool CreateSel(string aName){if(!SymbolInfoTick(Symbol(), tick)){Print("SymbolInfoTick() failed, error = ", GetLastError());return false;}m_name_orders = aName;m_type_orders = 1;m_lots_orders = iLots;m_cena_orders = NormalizeDouble(tick.bid, Digits());ButtonCreate(0, iPrefix + "A" + aName, 0, 0, 0, 30, 18, CORNER_LEFT_UPPER, "Sell", "Arial", 10, clrWhite, clrTomato, clrTomato, true, true, true, false, 0);EditCreate(0, iPrefix + "B" + aName, 0, 10, 30, 36, 18, DoubleToString(m_lots_orders, 2), "Arial", 10, ALIGN_CENTER, false, CORNER_LEFT_UPPER, clrWhite, clrGray, clrTomato,false, false, false, 0);TrendCreate(0, iPrefix + "D" + aName, 0, TimeCurrent() - PeriodSeconds() * 10, m_cena_orders, TimeCurrent() + PeriodSeconds() * 10, m_cena_orders, clrTomato, STYLE_SOLID, 1, false, false, false, false, true, 0);ArrowCreate(0, iPrefix + "C" + aName, 0, TimeCurrent() + PeriodSeconds() * 10, m_cena_orders, clrTomato, STYLE_SOLID, 2, false, true, true, 0);OrderDrag(aName);return true;}void OrderDrag(string aName){datetime times = (datetime)ObjectGetInteger(0, iPrefix + "C" + aName, OBJPROP_TIME, 0);double price = ObjectGetDouble(0, iPrefix + "C" + aName, OBJPROP_PRICE, 0);string text = ObjectGetString(0, iPrefix + "B" + aName, OBJPROP_TEXT);m_lots_orders = StringToDouble(text);m_cena_orders = price;int x = 0, y = 0;if(ChartTimePriceToXY(0, 0, times, price, x, y)){ObjectSetInteger(0, iPrefix + "A" + aName, OBJPROP_XDISTANCE, x + 2 - 72);ObjectSetInteger(0, iPrefix + "A" + aName, OBJPROP_YDISTANCE, y + 2 - 10);ObjectSetInteger(0, iPrefix + "B" + aName, OBJPROP_XDISTANCE, x + 32 - 72);ObjectSetInteger(0, iPrefix + "B" + aName, OBJPROP_YDISTANCE, y + 2 - 10);ObjectSetInteger(0, iPrefix + "D" + aName, OBJPROP_TIME, 0, times);ObjectSetDouble(0, iPrefix + "D" + aName, OBJPROP_PRICE, 0, price);}}};
//************************************************************************************************/
//* */
//************************************************************************************************/
struct structura{
protected:public:str orders[];bool MenuCreate(void){EditCreate(0, iPrefix + "Menu", 0, 10, 30, 64, 22, "", "Arial", 10, ALIGN_CENTER, false, CORNER_LEFT_UPPER, clrWhite, clrGray, clrNONE, false, false, false, 0);ButtonCreate(0, iPrefix + "Buy", 0, 0, 0, 30, 18, CORNER_LEFT_UPPER, "Buy", "Arial", 10, clrWhite, clrBlue, clrBlue, false, false, false, true, 0);ButtonCreate(0, iPrefix + "Sel", 0, 0, 0, 30, 18, CORNER_LEFT_UPPER, "Sell", "Arial", 10, clrWhite, clrTomato, clrTomato, false, false, false, true, 0);ArrowCreate(0, iPrefix + "AW", 0, TimeCurrent() + PeriodSeconds() * 10, 0, clrGreen, STYLE_SOLID, 3, false, false, true, 0);MenuDrag();return true;}void MenuDrag(void){int x = (int)ObjectGetInteger(0, iPrefix + "Menu", OBJPROP_XDISTANCE);int y = (int)ObjectGetInteger(0, iPrefix + "Menu", OBJPROP_YDISTANCE);ObjectSetInteger(0, iPrefix + "Buy", OBJPROP_XDISTANCE, x + 2);ObjectSetInteger(0, iPrefix + "Buy", OBJPROP_YDISTANCE, y + 2);ObjectSetInteger(0, iPrefix + "Sel", OBJPROP_XDISTANCE, x + 32);ObjectSetInteger(0, iPrefix + "Sel", OBJPROP_YDISTANCE, y + +2);}bool GetStateBuy(void) { return (bool)ObjectGetInteger(0, iPrefix + "Buy", OBJPROP_STATE);}void SetStateBuy(void) { ObjectSetInteger(0, iPrefix + "Buy", OBJPROP_STATE, false);}bool GetStateSel(void) { return (bool)ObjectGetInteger(0, iPrefix + "Sel", OBJPROP_STATE);}void SetStateSel(void) { ObjectSetInteger(0, iPrefix + "Sel", OBJPROP_STATE, false);}};
structura st;//************************************************************************************************/
//* */
//************************************************************************************************/
int OnInit(){Comment("");ChartSetInteger(ChartID(), CHART_EVENT_MOUSE_MOVE, true);st.MenuCreate();return(INIT_SUCCEEDED);}
//************************************************************************************************/
//* */
//************************************************************************************************/
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam){if(id == CHARTEVENT_OBJECT_CLICK){if(st.GetStateBuy()){int u = ArraySize(st.orders);ArrayResize(st.orders, u + 1, 100);st.orders[u].CreateBuy(IntegerToString(u));st.SetStateBuy();}if(st.GetStateSel()){int u = ArraySize(st.orders);ArrayResize(st.orders, u + 1, 100);st.orders[u].CreateSel(IntegerToString(u));st.SetStateSel();}}if(id == CHARTEVENT_MOUSE_MOVE || id == CHARTEVENT_OBJECT_ENDEDIT)if(sparam == "1"){double buy_price = 0, sel_price = 0, buy_lot = 0, sel_lot = 0, price_aw = 0;int t = 0;for(int i = 0; i < ArraySize(st.orders); i++){st.orders[i].OrderDrag(IntegerToString(i));if(st.orders[i].GetType() == 0){buy_price += st.orders[i].GetCena() * st.orders[i].GetLots();buy_lot += st.orders[i].GetLots();t++;}if(st.orders[i].GetType() == 1){sel_price += st.orders[i].GetCena() * st.orders[i].GetLots();sel_lot += st.orders[i].GetLots();t++;}}if(t >= 2 && (buy_lot - sel_lot) != 0){price_aw = NormalizeDouble((buy_price - sel_price) / (buy_lot - sel_lot), Digits());if(price_aw > 0)for(int i = 0; i < ArraySize(st.orders); i++)st.orders[i].SetAWpr(IntegerToString(i), TimeCurrent(), price_aw);ObjectSetDouble(0, iPrefix + "AW", OBJPROP_PRICE, 0, price_aw);ObjectSetInteger(0, iPrefix + "AW", OBJPROP_TIME, 0, TimeCurrent() + PeriodSeconds() * 5);}st.MenuDrag();}ChartRedraw();}
//************************************************************************************************/
//* */
//************************************************************************************************/
int OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],const double &open[],const double &high[],const double &low[],const double &close[],const long &tick_volume[],const long &volume[],const int &spread[]){return(rates_total);}
//************************************************************************************************/
//* */
//************************************************************************************************/
void OnDeinit(const int reason){ObjectsDeleteAll(0, iPrefix);}
//************************************************************************************************/
//* */
//************************************************************************************************/
bool ButtonCreate(const long chart_ID = 0, // chart's IDconst string name = "Button", // button nameconst int sub_window = 0, // subwindow indexconst int x = 0, // X coordinateconst int y = 0, // Y coordinateconst int width = 50, // button widthconst int height = 18, // button heightconst ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoringconst string text = "Button", // textconst string font = "Arial", // fontconst int font_size = 10, // font sizeconst color clr = clrBlack, // text colorconst color back_clr = C'236,233,216', // background colorconst color border_clr = clrNONE, // border colorconst bool state = true, // pressed/releasedconst bool back = true, // in the backgroundconst bool selection = true, // highlight to moveconst bool hidden = false, // hidden in the object listconst long z_order = 0) // priority for mouse click{ResetLastError();if(ObjectCreate(chart_ID, name, OBJ_BUTTON, sub_window, 0, 0)){ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x);ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y);ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width);ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height);ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner);ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);ObjectSetString(chart_ID, name, OBJPROP_FONT, font);ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size);ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr);ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_COLOR, border_clr);ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);ObjectSetInteger(chart_ID, name, OBJPROP_STATE, state);ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);return(true);}Print(__FUNCTION__, ": failed to create the button! Error code = ", GetLastError());return(false);}
//+------------------------------------------------------------------+
bool TrendCreate(const long chart_ID = 0, // chart's IDconst string name = "TrendLine", // line nameconst int sub_window = 0, // subwindow indexdatetime time1 = 0, // first point timedouble price1 = 0, // first point pricedatetime time2 = 0, // second point timedouble price2 = 0, // second point priceconst color clr = clrRed, // line colorconst ENUM_LINE_STYLE style = STYLE_SOLID, // line styleconst int width = 1, // line widthconst bool back = false, // in the backgroundconst bool selection = true, // highlight to moveconst bool ray_left = false, // line's continuation to the leftconst bool ray_right = false, // line's continuation to the rightconst bool hidden = true, // hidden in the object listconst long z_order = 0) // priority for mouse click{ResetLastError();if(ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2)){ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);ObjectSetInteger(chart_ID, name, OBJPROP_RAY_LEFT, ray_left);ObjectSetInteger(chart_ID, name, OBJPROP_RAY_RIGHT, ray_right);ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);return(true);}Print(__FUNCTION__, ": failed to create a trend line! Error code = ", GetLastError());return(false);}
//+------------------------------------------------------------------+
bool EditCreate(const long chart_ID = 0, // chart's IDconst string name = "Edit", // object nameconst int sub_window = 0, // subwindow indexconst int x = 0, // X coordinateconst int y = 0, // Y coordinateconst int width = 50, // widthconst int height = 18, // heightconst string text = "Text", // textconst string font = "Arial", // fontconst int font_size = 10, // font sizeconst ENUM_ALIGN_MODE align = ALIGN_CENTER, // alignment typeconst bool read_only = false, // ability to editconst ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoringconst color clr = clrBlack, // text colorconst color back_clr = clrWhite, // background colorconst color border_clr = clrNONE, // border colorconst bool back = true, // in the backgroundconst bool selection = true, // highlight to moveconst bool hidden = false, // hidden in the object listconst long z_order = 0) // priority for mouse click{ResetLastError();if(ObjectCreate(chart_ID, name, OBJ_EDIT, sub_window, 0, 0)){ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x);ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y);ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width);ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height);ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);ObjectSetString(chart_ID, name, OBJPROP_FONT, font);ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size);ObjectSetInteger(chart_ID, name, OBJPROP_ALIGN, align);ObjectSetInteger(chart_ID, name, OBJPROP_READONLY, read_only);ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner);ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr);ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_COLOR, border_clr);ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);return(true);}Print(__FUNCTION__, ": failed to create \"Edit\" object! Error code = ", GetLastError());return(false);