# 重映射 MT4 的快捷键像同花顺一样 1. 需要写指标响应 `CHARTEVENT_KEYDOWN` 事件 2. 需要 Autohotkey 重映射快捷键 效果: 1. **<**/**>** 切换品种 2. **Ctrl+Left**/**Ctrl+Right** 快速移动图表 3. **Up**/**Down** 放大缩小图表 4. **0** 键 还原图表坐标轴缩放 5. **P** 键 隐藏/显示坐标轴 6. **M** 月线 **W** 周线 **D** 日线 ![](https://100w123.com/_extern/wiki/MT4/hotkeys.png?1200) ## MT4 指标 **Symbol changer-hotkeys.mq4** // Symbol changer-hotkeys 1.0.0 #property indicator_chart_window #property indicator_buffers 0 #property strict extern int currentIndex = 0; extern string Symbols = "US30;NAS100;SPX500;US2000;GER30;UK100;FRA40;*;USDOLLAR;USDJPY;EURUSD;GBPUSD;AUDUSD;USDCNH;*;XAUUSD;XAGUSD;*;USOil;UKOil;*;BTCUSD;ETHUSD"; // List of symbols (separated by ";" extern string str1 = ""; // and "*" new line) extern string prefix = ""; // prefix Symbol extern string suffix = ""; // suffix Symbol extern string UniqueID = "SymbolChanger-hotkeys"; // Indicator unique ID extern int WindowIndex = 0; // SubWIndow extern int XShift = 8; // Horizontal shift extern int YShift = 16; // Vertical shift extern int XSize = 52; // Width of buttons extern int YSize = 18; // Height of buttons extern int FSize = 8; // Font size extern color Bcolor = C'53,53,53'; // Button color extern color Dcolor = clrDimGray; // Button border color extern color SBcolor = clrDodgerBlue; // Button selected color extern color SDcolor = clrDeepSkyBlue; // Button selected border color extern color Tncolor = clrDarkGray; // Text color - normal extern color Sncolor = clrGold; // Text color - selected extern bool Transparent = false; // Transparent buttons? // extern bool ShowTimeframe = false; // Show Timeframe buttons extern bool UseAsMasterChart = true; // Use this Chart as Master extern string sound = "tick.wav"; // Play sound on button click extern string ProfitLossColorInput = "==================================="; extern color TradeInProfitBColor = C'53,53,53'; // Trade in PROFIT background color extern color TradeInProfitDColor = clrLimeGreen; // Trade in PROFIT border color extern color TradeInLossBColor = clrMaroon; // Trade in LOSS background color extern color TradeInLossDColor = clrRed; // Trade in LOSS border color extern color TradeInZeroBColor = clrGray; // Trade in ZERO or PENDING background color extern color TradeInZeroDColor = clrWhite; // Trade in ZERO or PENDING border color #define KEY_MONTHLY 57 #define KEY_WEEKLY 56 #define KEY_DAILY 55 #define KEY_4HOUR 54 #define KEY_1HOUR 53 #define KEY_5MIN 50 #define KEY_30MIN 52 #define KEY_15MIN 51 #define KEY_1MIN 49 #define KEY_CHARTFIX 48 #define KEY_P 80 //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- string aSymbols[]; int yswitch; bool visibleButtons = true; bool ShowTimeframe = 1; int ButtonsInARow; // ------------------------------------------------ int OnInit() { Symbols = StringTrimLeft(StringTrimRight(Symbols)); if(StringSubstr(Symbols, StringLen(Symbols) - 1, 1) != ";") Symbols = StringConcatenate(Symbols, ";"); int s = 0, i = StringFind(Symbols, ";", s); string current; while(i > 0) { current = StringSubstr(Symbols, s, i - s); if(current != "*") current = StringConcatenate(prefix, current, suffix); ArrayResize(aSymbols, ArraySize(aSymbols) + 1); aSymbols[ArraySize(aSymbols) - 1] = current; s = i + 1; i = StringFind(Symbols, ";", s); } int xpos = 0, ypos = 0, maxx = 0, maxy = 0; yswitch = YShift + 1; createButton(UniqueID + ":master:", "v", XShift, yswitch, 16, 16); ObjectSet(UniqueID + ":master:", OBJPROP_BGCOLOR, White); ObjectSetText(UniqueID + ":master:", "v", FSize, "Arial", Black); ObjectSetString(WindowIndex, UniqueID + ":master:", OBJPROP_TOOLTIP, "Symbol Changer"); ypos += YSize + 1; for(i = 0; i < ArraySize(aSymbols); i++) { if(aSymbols[i] == "*") { xpos = 0; ypos += YSize + 1; } else { createButton(UniqueID + ":symbol:" + string(i), aSymbols[i], XShift + xpos, YShift + ypos, XSize, YSize); xpos += XSize + 1; } } xpos = 0; ypos += YSize * 2; if(ShowTimeframe) for(i = 0; i < ArraySize(sTfTable); i++) { if(i > 0 && MathMod(i, ButtonsInARow) == 0) { xpos = 0; ypos += YSize + 1; } createButton(UniqueID + ":time:" + string(i), sTfTable[i], XShift + xpos + 25, yswitch, XSize - 1, YSize - 1); xpos += XSize + 1; } setSymbolButtonColor(); setPeriodButtonColor(); // if (ShowTimeframe) setTimeFrameButtonColor(); // Set MasterChart if(UseAsMasterChart) StoreChartPair(); IndicatorShortName(""); EventSetTimer(3); return(0); } // ------------------------------------------------ void OnDeinit(const int reason) { switch(reason) { case REASON_CHARTCHANGE : case REASON_RECOMPILE : case REASON_CLOSE : break; default : { string lookFor = UniqueID + ":"; int lookForLength = StringLen(lookFor); for(int i = ObjectsTotal() - 1; i >= 0; i--) { string objectName = ObjectName(i); if(StringSubstr(objectName, 0, lookForLength) == lookFor) ObjectDelete(objectName); } } } EventKillTimer(); } // ------------------------------------------------ void createButton(string name, string caption, int xpos, int ypos, int xsize, int ysize) { if(ObjectFind(name) != 0) ObjectCreate(0, name, OBJ_BUTTON, WindowIndex, 0, 0, 0); ObjectSet(name, OBJPROP_CORNER, 0); ObjectSet(name, OBJPROP_XDISTANCE, xpos); ObjectSet(name, OBJPROP_YDISTANCE, ypos); ObjectSet(name, OBJPROP_XSIZE, xsize); ObjectSet(name, OBJPROP_YSIZE, ysize); ObjectSetText(name, caption, FSize, "Arial", Tncolor); ObjectSet(name, OBJPROP_FONTSIZE, FSize); ObjectSet(name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSet(name, OBJPROP_COLOR, Tncolor); ObjectSet(name, OBJPROP_BGCOLOR, Bcolor); ObjectSet(name, OBJPROP_BACK, Transparent); ObjectSet(name, OBJPROP_BORDER_COLOR, Dcolor); ObjectSet(name, OBJPROP_STATE, false); ObjectSet(name, OBJPROP_HIDDEN, true); } // ------------------------------------------------ void setSymbolButtonColor() { string lookFor = UniqueID + ":symbol:"; int lookForLength = StringLen(lookFor); for(int i = ObjectsTotal() - 1; i >= 0; i--) { string objectName = ObjectName(i); if(StringSubstr(objectName, 0, lookForLength) == lookFor) { string symbol = ObjectGetString(0, objectName, OBJPROP_TEXT); if(symbol != _Symbol) ObjectSet(objectName, OBJPROP_COLOR, Tncolor); else ObjectSet(objectName, OBJPROP_COLOR, Sncolor); } } } // ------------------------------------------------ void setPeriodButtonColor() { string lookFor = UniqueID + ":time:"; int lookForLength = StringLen(lookFor); for(int i = ObjectsTotal() - 1; i >= 0; i--) { string objectName = ObjectName(i); if(StringSubstr(objectName, 0, lookForLength) == lookFor) { string period = ObjectGetString(0, objectName, OBJPROP_TEXT); if(stringToTimeFrame(period) != _Period) ObjectSet(objectName, OBJPROP_COLOR, Tncolor); else ObjectSet(objectName, OBJPROP_COLOR, Sncolor); } } } // ------------------------------------------------ void setTimeFrameButtonColor() { string lookFor = UniqueID + ":time:"; int lookForLength = StringLen(lookFor); for(int i = ObjectsTotal() - 1; i >= 0; i--) { string objectName = ObjectName(i); if(StringSubstr(objectName, 0, lookForLength) == lookFor) { int time = stringToTimeFrame(ObjectGetString(0, objectName, OBJPROP_TEXT)); if(time != _Period) ObjectSet(objectName, OBJPROP_COLOR, Tncolor); else ObjectSet(objectName, OBJPROP_COLOR, Sncolor); } } } // ------------------------------------------------ string sTfTable[] = {"M1", "M5", "M15", "M30", "H1", "H4", "D1", "W1", "MN"}; int iTfTable[] = {1, 5, 15, 30, 60, 240, 1440, 10080, 43200}; //string sTfTable[] = {"H4","D1","W1","MN"}; //int iTfTable[] = {240,1440,10080,43200}; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string timeFrameToString(int tf) { for(int i = ArraySize(iTfTable) - 1; i >= 0; i--) if(tf == iTfTable[i]) return(sTfTable[i]); return(""); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int stringToTimeFrame(string tf) { for(int i = ArraySize(sTfTable) - 1; i >= 0; i--) if(tf == sTfTable[i]) return(iTfTable[i]); return(0); } // ------------------------------------------------ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StoreChartPair() { string n = "SC-" + Symbol(); varDel("SC-"); GlobalVariableSet(n, 0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string varDel(string sVarPrefix) { string text; int nVar = GlobalVariablesTotal(); for(int jVar = 0; jVar < nVar; jVar++) { string sVarName = GlobalVariableName(jVar); int x = StringFind(sVarName, sVarPrefix); if(x >= 0) { GlobalVariableDel(sVarName); } } return(text); } // ------------------------------------------------ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_KEYDOWN) { int keycode = int(lparam); Print(keycode); if (keycode == 188) { currentIndex = (int)GlobalVariableGet("hotkey:currentIndex"); if (currentIndex > 0) currentIndex--; else currentIndex = ArraySize(aSymbols) - 1; if (aSymbols[currentIndex] == "*") { currentIndex--; } GlobalVariableSet("hotkey:currentIndex", currentIndex); Print(aSymbols[currentIndex]); ChartSetSymbolPeriod(0, aSymbols[currentIndex], _Period); } if (keycode == 190) { currentIndex = (int)GlobalVariableGet("hotkey:currentIndex"); if (currentIndex < ArraySize(aSymbols) - 1) currentIndex++; else currentIndex = 0; if (aSymbols[currentIndex] == "*") { currentIndex++; } GlobalVariableSet("hotkey:currentIndex", currentIndex); Print(aSymbols[currentIndex]); ChartSetSymbolPeriod(0, aSymbols[currentIndex], _Period); } if (keycode == KEY_MONTHLY || keycode == 77) { ChartSetSymbolPeriod(0, NULL, 43200); } else if (keycode == KEY_WEEKLY || keycode == 87) { ChartSetSymbolPeriod(0, NULL, 10080); } else if (keycode == KEY_DAILY || keycode == 68) { ChartSetSymbolPeriod(0, NULL, 1440); } else if (keycode == KEY_4HOUR) { ChartSetSymbolPeriod(0, NULL, 240); } else if (keycode == KEY_1HOUR) { ChartSetSymbolPeriod(0, NULL, 60); } else if (keycode == KEY_5MIN) { ChartSetSymbolPeriod(0, NULL, 5); } else if (keycode == KEY_30MIN) { ChartSetSymbolPeriod(0, NULL, 30); } else if (keycode == KEY_15MIN) { ChartSetSymbolPeriod(0, NULL, 15); } else if (keycode == KEY_1MIN) { ChartSetSymbolPeriod(0, NULL, 1); } else if (keycode == KEY_CHARTFIX) { bool isFixed = ChartGetInteger(0, CHART_SCALEFIX, true); if(!isFixed) { ChartSetInteger(0, CHART_SCALEFIX, true); } else { ChartSetInteger(0, CHART_SCALEFIX, false); } } else if (keycode == KEY_P) { bool isFixed = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE, true); if(!isFixed) { ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); } else { ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false); } } } if(id == CHARTEVENT_OBJECT_CLICK && ObjectGet(sparam, OBJPROP_TYPE) == OBJ_BUTTON) { if(StringFind(sparam, UniqueID + ":symbol:", 0) == 0) ChartSetSymbolPeriod(0, ObjectGetString(0, sparam, OBJPROP_TEXT), _Period); if(StringFind(sparam, UniqueID + ":time:", 0) == 0) ChartSetSymbolPeriod(0, _Symbol, stringToTimeFrame(ObjectGetString(0, sparam, OBJPROP_TEXT))); if(StringFind(sparam, UniqueID + ":back:", 0) == 0) ObjectSet(sparam, OBJPROP_STATE, false); if(StringFind(sparam, UniqueID + ":master:", 0) == 0) { hideButtons(); visibleButtons = !visibleButtons; } if(UseAsMasterChart) StoreChartPair(); if(sound != "") PlaySound(sound); setSymbolButtonColorProfit(); } } // // // // // //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int start() { setSymbolButtonColorProfit(); return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { setSymbolButtonColorProfit(); return; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void hideButtons() { string lookFor = UniqueID + ":"; int lookForLength = StringLen(lookFor); for(int i = ObjectsTotal() - 1; i >= 0; i--) { string objectName = ObjectName(i); if(objectName == UniqueID + ":master:") continue; if(StringSubstr(objectName, 0, lookForLength) == lookFor) { // ObjectDelete(objectName); if(visibleButtons) ObjectSetInteger(WindowIndex, objectName, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); else ObjectSetInteger(WindowIndex, objectName, OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void setSymbolButtonColorProfit() { if(!visibleButtons) return; int tip, b, s, bo, so; int i; string objectName, symbol; double Profit, profit; string lookFor = UniqueID + ":symbol:"; int lookForLength = StringLen(lookFor); for(int j = ObjectsTotal() - 1; j >= 0; j--) { objectName = ObjectName(j); if(StringSubstr(objectName, 0, lookForLength) == lookFor) { symbol = ObjectGetString(0, objectName, OBJPROP_TEXT); b = 0; s = 0; bo = 0; so = 0; profit = 0.0; Profit = 0.0; for(i = 0; i < OrdersTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { // && (Magic == OrderMagicNumber() || Magic == -1) if(OrderSymbol() == symbol) { profit = OrderProfit() + OrderSwap() + OrderCommission(); Profit += profit; // price = OrderOpenPrice(); // lot = OrderLots(); tip = OrderType(); if(tip == OP_BUY) { // ProfitB += profit; // price_b += price*lot; b++; // lot_b+=lot; } if(tip == OP_SELL) { // ProfitS += profit; // price_s += price*lot; s++; // lot_s+=lot; } if(tip == OP_BUYSTOP || tip == OP_BUYLIMIT) { // price_bo += price*lot; // lot_bo+=lot; bo++; } if(tip == OP_SELLSTOP || tip == OP_SELLLIMIT) { // price_so += price*lot; // lot_so+=lot; so++; } } } } if(Profit > 0) { ObjectSet(objectName, OBJPROP_BGCOLOR, TradeInProfitBColor); if(bo + so > 0) ObjectSet(objectName, OBJPROP_BORDER_COLOR, TradeInZeroDColor); else ObjectSet(objectName, OBJPROP_BORDER_COLOR, TradeInProfitDColor); } else { if(Profit < 0) { ObjectSet(objectName, OBJPROP_BGCOLOR, TradeInLossBColor); if(bo + so > 0) ObjectSet(objectName, OBJPROP_BORDER_COLOR, TradeInZeroDColor); else ObjectSet(objectName, OBJPROP_BORDER_COLOR, TradeInLossDColor); } else { if(Profit == 0.0 && b + s + bo + so > 0) { ObjectSet(objectName, OBJPROP_BGCOLOR, TradeInZeroBColor); ObjectSet(objectName, OBJPROP_BORDER_COLOR, TradeInZeroDColor); } else { if(symbol != _Symbol) { ObjectSet(objectName, OBJPROP_BGCOLOR, Bcolor); ObjectSet(objectName, OBJPROP_BORDER_COLOR, Dcolor); } else { ObjectSet(objectName, OBJPROP_BGCOLOR, SBcolor); ObjectSet(objectName, OBJPROP_BORDER_COLOR, SDcolor); } } } } } } return; } //+------------------------------------------------------------------+ ## AHK 脚本 **MT4.ahk** #SingleInstance force #NoEnv #MaxHotkeysPerInterval 1000 DetectHiddenWindows, On SetTitleMatchMode, RegEx SetTitleMatchMode, Slow SetWorkingDir %A_ScriptDir% ;------------------------------------------------ ; MT4 #ifWinActive, ahk_exe terminal.exe Up:: send {NumpadAdd} return Down:: send {NumpadSub} return ^Left:: send {PgUp} return ^Right:: send {PgDn} return #ifWinActive ## 脚本打包下载 - [MT4-Symbol changer-hotkeys.7z](https://100w123.com/_extern/wiki/MT4/MT4-Symbol%20changer-hotkeys.7z)