495 lines
54 KiB
MQL5
495 lines
54 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Equilibrium.mq5 |
|
|
//| Copyright 2019, Thomas Schwabhaeuser |
|
|
//| schwabhaeuser@icloud.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2019, Thomas Schwabhaeuser"
|
|
#property link "schwabhaeuser@icloud.com"
|
|
#property description "Product of rates of added symbols:"
|
|
#property description "1. uses ask/bid prices for Equilibrium's ask/bid rates,"
|
|
#property description "2. uses ask/bid according to symbol's direction for Equilibrium's enter/leave rate, resp."
|
|
#property description "(intended for adding symbols whose product should equal one.)"
|
|
#property version "1.00"
|
|
//+------------------------------------------------------------------+
|
|
//| BACKLOG |
|
|
//| |
|
|
//| 1. Extract the functions |
|
|
//| bool parsePortfolioString(portfolio,directions,symbols[]) |
|
|
//| bool parseDirection(portfolio,string_index,array[]) |
|
|
//| bool parseSymbol(portfolio,string_index,array[]) |
|
|
//| int getNextIndex(portfolio,string_index) |
|
|
//| void PrintNextIndex(fn,pf,i,p,m,r) |
|
|
//| bool IsValidSymbolName(string symbol) |
|
|
//| string ToString(string &array[]) |
|
|
//| string ToString(ENUM_DIRECTION &array[]) |
|
|
//| to a new class CPortfolio encapsulating the 2 arrays |
|
|
//| string ExtSymbols[]; |
|
|
//| ENUM_DIRECTION ExtDirections[]; |
|
|
//| and providing the methods |
|
|
//| parse(string portfolio); |
|
|
//| int Total(void); |
|
|
//| string GetSymbol(int i); |
|
|
//| ENUM_DIRECTION GetDiretion(int i); |
|
|
//| string ToString(); |
|
|
//| |
|
|
//| 2. An expert should use the buffer MARGIN for risk management |
|
|
//| as ususal: |
|
|
//| LotSize = AccountInfoDouble(ACCOUNT_MARGIN_FREE)/MARGIN |
|
|
//| where MARGIN is computed by the indicator as follows: |
|
|
//| for(int i=0;i<#Symbols;i++): |
|
|
//| OrderCalcMargin(ExtDirections[i],ExtSymbols[i],1.0, |
|
|
//| EnterPrice,value) |
|
|
//| MARGIN += value; |
|
|
//| |
|
|
//| 3. Then the OnTick() handler of an expert is straightforward |
|
|
//| if(CheckClose()): |
|
|
//| for(int i=0;i<#Symbols;i++): |
|
|
//| Trade.Close(ExtSymbols[i]); |
|
|
//| else: |
|
|
//| if(CheckOpen()): |
|
|
//| for(int i=0;i<#Symbols;i++): |
|
|
//| Trade.Open(LotSize,ExtSymbols[i]); |
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//#property indicator_chart_window // Выводить индикатор в окно графика
|
|
#property indicator_separate_window
|
|
#property indicator_buffers 5 // Количество буферов для расчёта индикатора
|
|
#property indicator_plots 4 // Количество графических серий
|
|
//--- Цвета цветовых буферов
|
|
//#property indicator_color1 clrDodgerBlue,C'0,50,100'
|
|
//#property indicator_color2 clrMagenta,C'130,0,130'
|
|
//#property indicator_color3 clrGold,C'160,140,0'
|
|
//#property indicator_color4 clrAqua,C'0,140,140'
|
|
//#property indicator_color5 clrLimeGreen,C'20,80,20'
|
|
//---
|
|
#property indicator_label1 "Enter"
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_color1 clrRed
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_width1 1
|
|
#property indicator_label2 "Leave"
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_color2 clrGreen
|
|
#property indicator_style2 STYLE_SOLID
|
|
#property indicator_width2 1
|
|
#property indicator_label3 "Bid"
|
|
#property indicator_type3 DRAW_LINE
|
|
#property indicator_color3 clrBlue
|
|
#property indicator_style3 STYLE_SOLID
|
|
#property indicator_width4 1
|
|
#property indicator_label4 "Ask"
|
|
#property indicator_type4 DRAW_LINE
|
|
#property indicator_color4 clrMagenta
|
|
#property indicator_style4 STYLE_SOLID
|
|
#property indicator_width4 1
|
|
#property indicator_label4 "Margin"
|
|
#property indicator_type4 DRAW_LINE
|
|
#property indicator_color4 clrFireBrick
|
|
#property indicator_style4 STYLE_SOLID
|
|
#property indicator_width4 1
|
|
//---
|
|
#include "../Include/MultiSymbolIndicator.mqh"
|
|
//--- input parameters
|
|
input string InpPortfolio="EURUSD-EURGBP-GBPUSD"; // Buy/Sell (+/-) Symbols
|
|
//---- buffers
|
|
//--- TODO:
|
|
// enum ENUM_BUFFERS_EQL
|
|
// {
|
|
// BUFFER_ENTER = 0,
|
|
// BUFFER_LEAVE = 1,
|
|
// BUFFER_BID = 2,
|
|
// BUFFER_ASK = 3,
|
|
// BUFFER_MARGIN = 4,
|
|
// BUFFERS_TOTAL = 5
|
|
// };
|
|
// struct BufferType { double data[]; };
|
|
// BufferType ExtBuffersEql[BUFFERS_TOTAL];
|
|
//--- SetPropertiesIndicator():
|
|
// for(int b=0; b<BUFFERS_TOTAL; b++)
|
|
// SetIndexBuffer(b,ExtBuffersEql[b].data,INDICATOR_DATA);
|
|
//--- PrepareOnCalculate():
|
|
// for(int b=0; b<BUFFERS_TOTAL; b++)
|
|
// ArrayInitialize(ExtBuffersEql[b].data,EMPTY_VALUE);
|
|
|
|
double ExtEnterBuffer[];
|
|
double ExtLeaveBuffer[];
|
|
double ExtBidBuffer[];
|
|
double ExtAskBuffer[];
|
|
double ExtMarginBuffer[];
|
|
//--- gobal variables
|
|
CMultiSymbolIndicator ExtIndicator;
|
|
//--- Portfolio
|
|
// TODO: To be extracted to CPortfolio
|
|
string ExtSymbols[];
|
|
ENUM_DIRECTION ExtDirections[];
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//--- TODO: Move parsing of portfolio string to CMultiSymbolIndicator
|
|
//--- TODO: Extract parsing of portfolio string into a separate class
|
|
|
|
//--- DONE: parse portfolio initializing global variables
|
|
ArrayResize(ExtSymbols,0);
|
|
ArrayResize(ExtDirections,0);
|
|
parsePortfolioString(InpPortfolio,ExtDirections,ExtSymbols);
|
|
|
|
//--- DONE: add symbols with their direction to CMultiSymbolIndicator
|
|
if(ArraySize(ExtSymbols)!=ArraySize(ExtDirections))
|
|
return(INIT_FAILED);
|
|
string s="";
|
|
for(int i=0;i<-1+ArraySize(ExtSymbols);i++) s+=ExtSymbols[i]+", ";
|
|
s+="and "+ExtSymbols[-1+ArraySize(ExtSymbols)];
|
|
Print(__FUNCTION__+": Adding watchers for the "+ArraySize(ExtSymbols)+" symbols "+s);
|
|
for(int i=0;i<ArraySize(ExtSymbols);i++)
|
|
{
|
|
//Print(__FUNCTION__+": ExtIndicator.Add("+ExtSymbols[i]+","+
|
|
// EnumToString(ExtDirections[i])+")");
|
|
if(!ExtIndicator.AddWatcher(ExtSymbols[i],ExtDirections[i]))
|
|
return(INIT_FAILED);
|
|
}
|
|
|
|
ExtIndicator.OnInit();
|
|
|
|
//--- TODO:
|
|
// Try to map indicator buffers in the class CMultiSymbolIndicator
|
|
// For adding the buffers to ExtIndicator one by one we are going to use
|
|
// ExtIndicator.AddEnterBuffer(double &buffer[]);
|
|
// ExtIndicator.AddLeaveBuffer(double &buffer[]);
|
|
// ExtIndicator.AddBidBuffer(double &buffer[]);
|
|
// ExtIndicator.AddAskBuffer(double &buffer[]);
|
|
// ExtIndicator.AddMarginBuffer(double &buffer[]);
|
|
// which still needs to be implemented.
|
|
|
|
//--- indicator buffers mapping
|
|
SetIndexBuffer(0,ExtEnterBuffer,INDICATOR_DATA);
|
|
SetIndexBuffer(1,ExtLeaveBuffer,INDICATOR_DATA);
|
|
SetIndexBuffer(2,ExtBidBuffer,INDICATOR_DATA);
|
|
SetIndexBuffer(3,ExtAskBuffer,INDICATOR_DATA);
|
|
SetIndexBuffer(4,ExtMarginBuffer,INDICATOR_DATA);
|
|
|
|
//--- indicator digits
|
|
IndicatorSetInteger(INDICATOR_DIGITS,_Digits+2);
|
|
//--- set draw begin is not necessary,
|
|
// we can start calculating at the first bar.
|
|
//--- indicator short name
|
|
IndicatorSetString(INDICATOR_SHORTNAME,"EQUILIBRIUM");
|
|
|
|
//---
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator iteration function |
|
|
//+------------------------------------------------------------------+
|
|
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[])
|
|
{
|
|
Print(__FUNCTION__+
|
|
"("+rates_total+","+prev_calculated+",...): delegating to CMultiSymbolIndicator::OnCalculate()");
|
|
//---
|
|
int result=ExtIndicator.OnCalculate(rates_total,prev_calculated,time,open,high,low,close,
|
|
tick_volume,volume,spread);
|
|
//--- TODO:
|
|
// Find out how to fill the buffers
|
|
// double ExtEnterBuffer[];
|
|
// double ExtLeaveBuffer[];
|
|
// double ExtBidBuffer[];
|
|
// double ExtAskBuffer[];
|
|
// Of course, we would prefer ExtIndicator.OnCalculate() to invoke the FillBuffer functions.
|
|
// However, the buffers to be filled are in this indicator main program file while the data
|
|
// for filling is maintained in the indicator class. Therefore we need to pass the indicator
|
|
// buffers by reference to filling methods of the indicator object.
|
|
// Thus the indicator values must be written to the indicator buffers as follows:
|
|
ExtIndicator.FillEnterBuffer(rates_total,prev_calculated,ExtEnterBuffer);
|
|
ExtIndicator.FillLeaveBuffer(rates_total,prev_calculated,ExtLeaveBuffer);
|
|
ExtIndicator.FillBidBuffer(rates_total,prev_calculated,ExtBidBuffer);
|
|
ExtIndicator.FillAskBuffer(rates_total,prev_calculated,ExtAskBuffer);
|
|
ExtIndicator.FillMarginBuffer(rates_total,prev_calculated,ExtMarginBuffer);
|
|
//--- return value of prev_calculated for next call
|
|
return(rates_total);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
//---
|
|
ExtIndicator.OnTimer();
|
|
|
|
}
|
|
|
|
//--- 2019.07.25
|
|
//
|
|
//DJ 0 18:49:50.619 Symbols EURUSD: symbol to be synchronized
|
|
//DL 0 18:49:50.620 Symbols EURUSD: symbol synchronized, 3544 bytes of symbol info received
|
|
//JN 0 18:49:50.880 History EURUSD: history synchronization started
|
|
//DG 0 18:49:51.097 History EURUSD: load 27 bytes of history data to synchronize in 0:00:00.002
|
|
//EL 0 18:49:51.097 History EURUSD: history synchronized from 2016.01.03 to 2019.03.25
|
|
//GE 0 18:49:51.097 Ticks EURUSD: ticks synchronization started
|
|
//QN 0 18:49:51.098 Ticks EURUSD: load 34 bytes of tick data to synchronize in 0:00:00.000
|
|
//HS 0 18:49:51.099 Ticks EURUSD: history ticks synchronized from 2018.12.20 to 2019.03.24
|
|
//DK 0 18:49:51.295 History EURUSD,M10: history cache allocated for 45737 bars and contains 37302 bars from 2018.01.01 23:00 to 2019.01.01 23:50
|
|
//JJ 0 18:49:51.295 History EURUSD,M10: history begins from 2018.01.01 23:00
|
|
//LN 0 18:49:51.556 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37302,0): start =0, Symbol=EURUSD
|
|
//
|
|
//FR 0 18:49:51.556 Symbols EURGBP: symbol to be synchronized
|
|
//HK 0 18:49:51.557 Symbols EURGBP: symbol synchronized, 3544 bytes of symbol info received
|
|
//JP 0 18:49:51.772 History EURGBP: history synchronization started
|
|
//FI 0 18:49:51.908 History EURGBP: load 27 bytes of history data to synchronize in 0:00:00.001
|
|
//MF 0 18:49:51.908 History EURGBP: history synchronized from 2017.01.02 to 2019.03.25
|
|
//RM 0 18:49:51.909 Ticks EURGBP: ticks synchronization started
|
|
//IF 0 18:49:54.830 Ticks EURGBP: load 34 bytes of tick data to synchronize in 0:00:02.922
|
|
//NI 0 18:49:54.830 Ticks EURGBP: history ticks synchronized from 2018.12.20 to 2019.03.13
|
|
//GQ 0 18:49:54.851 History EURGBP,M10: history cache allocated for 8439 bars and contains 4 bars from 2019.01.01 23:00 to 2019.01.01 23:50
|
|
//MN 0 18:49:54.851 History EURGBP,M10: history begins from 2019.01.01 23:00
|
|
//LF 0 18:49:54.851 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37302,0): start =0, Symbol=EURGBP
|
|
//
|
|
//CI 0 18:49:54.851 Symbols GBPUSD: symbol to be synchronized
|
|
//RP 0 18:49:54.851 Symbols GBPUSD: symbol synchronized, 3544 bytes of symbol info received
|
|
//LM 0 18:49:55.105 History GBPUSD: history synchronization started
|
|
//RE 0 18:49:55.234 History GBPUSD: load 27 bytes of history data to synchronize in 0:00:00.001
|
|
//QS 0 18:49:55.234 History GBPUSD: history synchronized from 2016.01.03 to 2019.03.25
|
|
//FR 0 18:49:55.235 Ticks GBPUSD: ticks synchronization started
|
|
//QI 0 18:49:58.432 Ticks GBPUSD: load 34 bytes of tick data to synchronize in 0:00:03.187
|
|
//PL 0 18:49:58.432 Ticks GBPUSD: history ticks synchronized from 2018.12.20 to 2019.03.13
|
|
//RS 0 18:49:58.651 History GBPUSD,M10: history cache allocated for 45729 bars and contains 37294 bars from 2018.01.01 23:00 to 2019.01.01 23:50
|
|
//DN 0 18:49:58.651 History GBPUSD,M10: history begins from 2018.01.01 23:00
|
|
//EF 0 18:49:58.653 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37302,0): start =0, Symbol=GBPUSD
|
|
//
|
|
//EI 0 18:49:58.653 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate: watchers prepared with data from i=start=0 while i<5<37302. INCOMPLETE!
|
|
//
|
|
//ES 3 18:50:01.631 Ticks EURGBP : 2019.03.14 23:59 - real ticks absent for 1 minutes out of 1434 total minute bars within a day
|
|
//ES 3 18:50:01.632 Ticks EURGBP : 2019.03.15 23:59 - real ticks absent for 1 minutes out of 1320 total minute bars within a day
|
|
//CR 3 18:50:01.632 Ticks EURGBP : 2019.03.17 23:59 - real ticks absent for 1 minutes out of 110 total minute bars within a day
|
|
//KS 3 18:50:01.632 Ticks EURGBP : 2019.03.18 23:59 - real ticks absent for 1 minutes out of 1440 total minute bars within a day
|
|
//KS 3 18:50:01.633 Ticks EURGBP : 2019.03.19 23:59 - real ticks absent for 1 minutes out of 1440 total minute bars within a day
|
|
//OS 3 18:50:01.633 Ticks EURGBP : 2019.03.20 23:59 - real ticks absent for 1 minutes out of 1439 total minute bars within a day
|
|
//NS 3 18:50:01.634 Ticks EURGBP : 2019.03.21 23:59 - real ticks absent for 1 minutes out of 1438 total minute bars within a day
|
|
//IS 3 18:50:01.634 Ticks EURGBP : 2019.03.22 23:59 - real ticks absent for 1 minutes out of 1320 total minute bars within a day
|
|
//GR 3 18:50:01.634 Ticks EURGBP : 2019.03.24 23:59 - real ticks absent for 1 minutes out of 114 total minute bars within a day
|
|
//IR 0 18:50:01.634 Ticks EURGBP : real ticks begin from 2018.12.20 00:00:00
|
|
//EH 3 18:50:01.634 Ticks EURGBP : 2019.01.02 00:00 - 2019.03.25 00:00 real ticks absent for 9 minutes of 83317 total minute bars, every tick generation used
|
|
//EI 0 18:50:03.652 Ticks EURUSD : real ticks begin from 2018.12.20 00:00:00
|
|
//KP 3 18:50:06.776 Ticks GBPUSD : 2019.03.11 23:59 - real ticks absent for 834 minutes out of 1440 total minute bars within a day
|
|
//RG 3 18:50:06.788 Ticks GBPUSD : 2019.03.12 23:59 - no real ticks within a day
|
|
//IN 3 18:50:06.802 Ticks GBPUSD : 2019.03.14 23:59 - real ticks absent for 1 minutes out of 1435 total minute bars within a day
|
|
//HN 3 18:50:06.803 Ticks GBPUSD : 2019.03.15 23:59 - real ticks absent for 1 minutes out of 1320 total minute bars within a day
|
|
//NS 3 18:50:06.803 Ticks GBPUSD : 2019.03.17 23:59 - real ticks absent for 1 minutes out of 113 total minute bars within a day
|
|
//DM 3 18:50:06.804 Ticks GBPUSD : 2019.03.18 23:59 - real ticks absent for 1 minutes out of 1436 total minute bars within a day
|
|
//QM 3 18:50:06.804 Ticks GBPUSD : 2019.03.19 23:59 - real ticks absent for 1 minutes out of 1438 total minute bars within a day
|
|
//HM 3 18:50:06.805 Ticks GBPUSD : 2019.03.20 23:59 - real ticks absent for 1 minutes out of 1438 total minute bars within a day
|
|
//NM 3 18:50:06.805 Ticks GBPUSD : 2019.03.21 23:59 - real ticks absent for 1 minutes out of 1440 total minute bars within a day
|
|
//MM 3 18:50:06.806 Ticks GBPUSD : 2019.03.22 23:59 - real ticks absent for 1 minutes out of 1320 total minute bars within a day
|
|
//IP 3 18:50:06.806 Ticks GBPUSD : 2019.03.24 23:59 - real ticks absent for 1 minutes out of 115 total minute bars within a day
|
|
//FR 0 18:50:06.806 Ticks GBPUSD : real ticks begin from 2018.12.20 00:00:00
|
|
//CH 3 18:50:06.806 Ticks GBPUSD : 2019.01.02 00:00 - 2019.03.25 00:00 real ticks absent for 2281 minutes of 83395 total minute bars, every tick generation used
|
|
//NE 3 18:50:06.806 Ticks GBPUSD : 2019.01.02 00:00 - 2019.03.25 00:00 real ticks absent for 1 whole days
|
|
//IJ 0 18:50:06.808 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 OnCalculate(37303,37302,...): delegating to CMultiSymbolIndicator::OnCalculate()
|
|
//QI 0 18:50:06.808 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate(37303,37302,...): start =37301, updating 3 watchers...
|
|
//KN 0 18:50:06.808 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37302): start =37301, Symbol=EURUSD
|
|
//RN 0 18:50:06.808 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37302): start =37301, Symbol=EURGBP
|
|
//RQ 0 18:50:06.808 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37302): start =37301, Symbol=GBPUSD
|
|
//HO 0 18:50:06.808 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate: watchers prepared with data from i=start=37301 while i<37301<37303. INCOMPLETE!
|
|
//KH 0 18:50:06.823 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 OnCalculate(37303,37303,...): delegating to CMultiSymbolIndicator::OnCalculate()
|
|
//GJ 0 18:50:06.823 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate(37303,37303,...): start =37302, updating 3 watchers...
|
|
//EO 0 18:50:06.823 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=EURUSD
|
|
//HO 0 18:50:06.823 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=EURGBP
|
|
//HP 0 18:50:06.823 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=GBPUSD
|
|
//IO 0 18:50:06.823 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate: watchers prepared with data from i=start=37302 while i<37302<37303. INCOMPLETE!
|
|
//KG 0 18:50:06.838 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 OnCalculate(37303,37303,...): delegating to CMultiSymbolIndicator::OnCalculate()
|
|
//FJ 0 18:50:06.838 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate(37303,37303,...): start =37302, updating 3 watchers...
|
|
//HL 0 18:50:06.838 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=EURUSD
|
|
//EN 0 18:50:06.838 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=EURGBP
|
|
//EO 0 18:50:06.838 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=GBPUSD
|
|
//EN 0 18:50:06.838 Equilibrium (EURUSD,M10) 2019.01.02 00:00:00 CMultiSymbolIndicator::OnCalculate: watchers prepared with data from i=start=37302 while i<37302<37303. INCOMPLETE!
|
|
//FG 0 18:50:06.852 Equilibrium (EURUSD,M10) 2019.01.02 00:00:01 OnCalculate(37303,37303,...): delegating to CMultiSymbolIndicator::OnCalculate()
|
|
//GI 0 18:50:06.852 Equilibrium (EURUSD,M10) 2019.01.02 00:00:01 CMultiSymbolIndicator::OnCalculate(37303,37303,...): start =37302, updating 3 watchers...
|
|
//EL 0 18:50:06.852 Equilibrium (EURUSD,M10) 2019.01.02 00:00:01 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=EURUSD
|
|
//HN 0 18:50:06.852 Equilibrium (EURUSD,M10) 2019.01.02 00:00:01 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=EURGBP
|
|
//HO 0 18:50:06.852 Equilibrium (EURUSD,M10) 2019.01.02 00:00:01 CSymbolWatcher::OnCalculate(37303,37303): start =37302, Symbol=GBPUSD
|
|
//---
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool parsePortfolioString(string portfolio,ENUM_DIRECTION &directions[],string &symbols[])
|
|
{
|
|
//int array_index=0;
|
|
int string_index=0;
|
|
int length=StringLen(portfolio);
|
|
|
|
while(string_index<length)
|
|
{
|
|
Print(__FUNCTION__+
|
|
"(\""+portfolio+"\","+ToString(directions)+","+ToString(symbols)+"): "+
|
|
"string_index=="+string_index+", length=="+length);
|
|
if(!getDirection(portfolio,string_index,directions))
|
|
return(false);
|
|
if(!getSymbol(portfolio,string_index,symbols))
|
|
return(false);
|
|
}
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool getDirection(string portfolio,int &string_index,ENUM_DIRECTION &array[])
|
|
{
|
|
ushort character=StringGetCharacter(portfolio,string_index);
|
|
ENUM_DIRECTION direction=BUY;
|
|
if(character=='+')
|
|
string_index+=1; // discard matched character
|
|
if(character=='-')
|
|
{
|
|
direction=SELL;
|
|
string_index+=1; // discard matched character
|
|
}
|
|
|
|
// DONE: add direction to ExtDirections
|
|
// if(array_index!=ArraySize(array))
|
|
// {
|
|
// Print(__FUNCTION__+": array_index=="+array_index+"!="+ArraySize(array)+"==ArraySize(array)");
|
|
// return(false);
|
|
// }
|
|
int array_index=ArraySize(array);
|
|
int new_size=array_index+1;
|
|
ArrayResize(array,new_size);
|
|
array[array_index]=direction;
|
|
Print(__FUNCTION__+": added direction array["+array_index+"]=="+
|
|
EnumToString(array[array_index]));
|
|
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool getSymbol(string portfolio,int &string_index,string &array[])
|
|
{
|
|
int next_index=getNextIndex(portfolio,string_index);
|
|
int length;
|
|
if(next_index==-1)
|
|
length=StringLen(portfolio)-string_index;
|
|
else
|
|
length=next_index-string_index;
|
|
|
|
Print(__FUNCTION__+
|
|
"(\""+portfolio+"\","+string_index+",array): "+
|
|
"next_index=="+next_index+", length=="+length);
|
|
|
|
if(length<3)
|
|
return(false);
|
|
|
|
string symbol=StringSubstr(portfolio,string_index,length);
|
|
string_index+=length; // discard what should be a symbol name
|
|
|
|
if(!IsValidSymbolName(symbol))
|
|
return(false);
|
|
|
|
// DONE: add symbol to ExtSymbols
|
|
int array_index=ArraySize(array);
|
|
int new_size=array_index+1;
|
|
ArrayResize(array,new_size);
|
|
array[array_index]=symbol;
|
|
Print(__FUNCTION__+": added symbol array["+array_index+"]=="+array[array_index]);
|
|
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void PrintNextIndex(string fn,string pf,int i,int p,int m,int r)
|
|
{
|
|
Print(fn+"(\""+pf+"\","+i+") == "+r+" <= "+"plus_index=="+p+", "+"minus_index=="+m);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int getNextIndex(string portfolio,int string_index)
|
|
{
|
|
int plus_index=StringFind(portfolio,"+",string_index);
|
|
int minus_index=StringFind(portfolio,"-",string_index);
|
|
|
|
if(plus_index==-1 && minus_index==-1)
|
|
{
|
|
PrintNextIndex(__FUNCTION__,portfolio,string_index,plus_index,minus_index,-1);
|
|
return(-1);
|
|
}
|
|
|
|
if(plus_index==-1)
|
|
{
|
|
PrintNextIndex(__FUNCTION__,portfolio,string_index,plus_index,minus_index,minus_index);
|
|
return(minus_index);
|
|
}
|
|
|
|
if(minus_index==-1)
|
|
{
|
|
PrintNextIndex(__FUNCTION__,portfolio,string_index,plus_index,minus_index,plus_index);
|
|
return(plus_index);
|
|
}
|
|
|
|
if(plus_index<minus_index)
|
|
{
|
|
PrintNextIndex(__FUNCTION__,portfolio,string_index,plus_index,minus_index,plus_index);
|
|
return(plus_index);
|
|
}
|
|
else
|
|
{
|
|
PrintNextIndex(__FUNCTION__,portfolio,string_index,plus_index,minus_index,minus_index);
|
|
return(minus_index);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool IsValidSymbolName(string symbol)
|
|
{
|
|
// TODO: check if symbol is the valid name of a selectable symbol
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string ToString(string &array[])
|
|
{
|
|
string result="{";
|
|
for(int i=0;i<ArraySize(array);i++)
|
|
{
|
|
result+=array[i];
|
|
if(i<ArraySize(array)-1)
|
|
result+=",";
|
|
}
|
|
result+="}";
|
|
return(result);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string ToString(ENUM_DIRECTION &array[])
|
|
{
|
|
string result="{";
|
|
for(int i=0;i<ArraySize(array);i++)
|
|
{
|
|
result+=EnumToString(array[i]);
|
|
if(i<ArraySize(array)-1)
|
|
result+=",";
|
|
}
|
|
result+="}";
|
|
return(result);
|
|
}
|
|
//+------------------------------------------------------------------+
|