string str; ... if(str) // aparecerá o erro de compilação "Cannot convert type 'string' to 'bool'" (nas compilações anteriores não acontecia o erro) Print("str is true");É necessário escrever uma condição explícita:
string str; ... //--- verifica se a cadeia de caracteres é inicializada if(str!=NULL) Print("str is true"); ou //--- verifica se o valor da cadeia de caracteres é "true" if(StringCompare(str,"true",false)) Print("str is true"); ou //--- verifica se a cadeia de caracteres é um número e não é igual a zero if((int)str!=0) Print("str is true");
Correções de crash-logs.
void ArrayPrint( const void& array[], // matriz de saída uint digits=_Digits, // número de casas decimais const string separator=NULL, // delimitador entre os valores dos campos de estrutura ulong start=0, // índice do primeiro elemento de saída ulong count=WHOLE_ARRAY, // número de elementos de saída ulong flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN );ArrayPrint não exibe, no registro, todos os campos da matriz de estruturas, uma vez que os campos tanto de matriz como de ponteiros de objetos são omitidos. Para exibição de todos os campos dessa estrutura, será necessário escrever a função de saída em massa com a formatação desejada.
//--- exibe os valores das 10 últimas barras MqlRates rates[]; if(CopyRates(_Symbol,_Period,1,10,rates)) { ArrayPrint(rates); Print("Verificação\n[time]\t[open]\t[high]\t[low]\t[close]\t[tick_volume]\t[spread]\t[real_volume]"); for(int i=0;i<10;i++) { PrintFormat("[%d]\t%s\t%G\t%G\t%G\t%G\t%G\t%G\t%I64d\t",i, TimeToString(rates[i].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS), rates[i].open,rates[i].high,rates[i].low,rates[i].close, rates[i].tick_volume,rates[i].spread,rates[i].real_volume); } } else PrintFormat("CopyRates failed, error code=%d",GetLastError()); //--- exemplo de saída /* [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000 [1] 2016.11.09 05:00:00 1.12296 1.12825 1.11930 1.12747 17829 9 15632176000 [2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000 [3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000 [4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000 [5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000 [6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000 [7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000 [8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000 [9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000 Verificação [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000 [1] 2016.11.09 05:00:00 1.12296 1.12825 1.1193 1.12747 17829 9 15632176000 [2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000 [3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000 [4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000 [5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000 [6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000 [7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000 [8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000 [9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000 */
void OnStart() { int arr[]; //--- quanta memória é usada inicialmente Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- quanta memória é usado para uma matriz de tamanho 1, mas com uma reserva de ArrayResize(arr,1,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- após aumentar a matriz, o tamanho da memória utilizada não é alterado pela reserva ArrayResize(arr,1024*512,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- após reduzir a matriz, o tamanho da memória utilizada também não é alterado ArrayResize(arr,1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- a memória sem uso é liberada pela remoção da reserva ArrayResize(arr,1,-1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); }
#include <Graphics/Graphic.mqh> double Func1(double x) { return MathPow(x,2); } double Func2(double x) { return MathPow(x,3); } double Func3(double x) { return MathPow(x,4); } void OnStart() { GraphPlot(Func1,Func2,Func3,-2,2,0.05,CURVE_LINES); }Resultado:
#include <Math/Stat/Binomial.mqh> #include <Graphics/Graphic.mqh> void OnStart(void) { double vars[101]; double results[101]; const int N=2000; //--- MathSequence(0,N,20,vars); MathProbabilityDensityBinomial(vars,N,M_PI/10,true,results); ArrayPrint(results,4); GraphPlot(results); //--- }Resultado:
Documentação atualizada.
Na biblioteca padrão, foi incluía a versão MQL5 da biblioteca de análise numérica ALGLIB.
Possibilidades da biblioteca
Como usar
Os arquivos da biblioteca ALGLIB estão localizados no diretório \MQL5\Include\Math\Alglib. Para usar as funções, adicione o arquivo principal da biblioteca ao seu programa:
A biblioteca padrão foram adicionadas funções de trabalho com estatística matemática. Agora, em MQL5, estão disponíveis as possibilidades da linguagem R, ela é um dos melhores instrumentos de processamento estatístico e análise de dados.<br1>
Possibilidades da biblioteca
A biblioteca estatística contém funções para cálculo de características estatísticas de dados, bem como funções para trabalhar com distribuições estatísticas:
Como usar
Os arquivos da biblioteca ALGLIB estão localizados no diretório \MQL5\Include\Math\Stat. Para usar as funções, adicione o arquivo com as funções desejadas ao seu programa, por exemplo:
#include <Math\Stat\Binomal.mqh> #include <Math\Stat\Cauchy.mqh>
Leia descrições detalhadas das funções da biblioteca no artigo Distribuições estatísticas em MQL5: pegamos as melhores a partir de R.
Na biblioteca padrão, foi incluía a versão MQL5 da biblioteca Fuzzy, ela implementa sistemas de inferência de lógica difusa Mastop e Sugeno.
Possibilidades da biblioteca
Como usar
Os arquivos da biblioteca Fuzzy estão localizados no diretório \MQL5\Include\Math\Fuzzy. Para usar as funções, adicione o arquivo com as funções desejadas ao seu programa, por exemplo:
#include <Math\Fuzzy\mamdanifuzzysystem.mqh> #include <Math\Fuzzy\sugenofuzzysystem.mqh>
Uma descrição detalhada da biblioteca pode ser encontrada ni Code Base: Fuzzy, biblioteca para trabalhar com lógica difusa
long FileLoad( const string filename, // [in] nome do arquivo void &buffer[], // [out] matriz na qual é tomado em consideração o arquivo uint common_flag=0 // [in] 0 - busca do arquivo na pasta Files do terminal, FILE_COMMON - na pasta comum dos terminais ); bool FileSave( const string filename, // [in] nome do arquivo const void &buffer[], // [in] matriz armazenada no arquivo uint common_flag=0 // [in] 0 - criação do arquivo na pasta Files do terminal, FILE_COMMON - na pasta comum dos terminais );Exemplo de como armazenar, numa pasta, uma matriz de ticks e, em seguida, lê-la.
//--- parâmetros de entrada input int ticks_to_save=1000; // número de ticks //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { string filename=_Symbol+"_ticks.bin"; MqlTick ticks[]; //--- int copied=CopyTicks(_Symbol,ticks,COPY_TICKS_ALL,0,ticks_to_save); if(copied!=-1) { PrintFormat(" CopyTicks(%s) copied %d ticks",_Symbol,copied); //--- se o histórico de ticks estiver sincronizado, o código de erro será igual a zero if(!GetLastError()==0) PrintFormat("%s: Ticks are not synchronized. Error=",_Symbol,copied,_LastError); //--- armazenamos os ticks no arquivo if(!FileSave(filename,ticks,FILE_COMMON)) PrintFormat("FileSave() failed, error=%d",GetLastError()); } else PrintFormat("Failed CopyTicks(%s), Error=",_Symbol,GetLastError()); //--- agora lemos de volta estes ticks a partir do arquivo ArrayFree(ticks); long count=FileLoad(filename,ticks,FILE_COMMON); if(count!=-1) { Print("Time\tBid\tAsk\tLast\tVolume\tms\tflags"); for(int i=0;i<count;i++) { PrintFormat("%s.%03I64u:\t%G\t%G\t%G\t%I64u\t0x%04x", TimeToString(ticks[i].time,TIME_DATE|TIME_SECONDS),ticks[i].time_msc%1000, ticks[i].bid,ticks[i].ask,ticks[i].last,ticks[i].volume,ticks[i].flags); } } }
//--- velas pintadas na mesma cor #property indicator_label1 "One color candles" #property indicator_type1 DRAW_CANDLES //--- foi indicado apenas uma cor, por isso todas as velas terão apenas uma cor #property indicator_color1 clrGreenSe forem indicadas duas cores, os contornos das velas serão desenhadas usando a primeira cor, enquanto o corpo usando a segunda.
//--- a cor das velas difere da cor das sombras #property indicator_label1 "Two color candles" #property indicator_type1 DRAW_CANDLES //--- sombras e contorno de velas de cor verde, corpo de cor branca #property indicator_color1 clrGreen,clrWhiteSe forem indicadas duas cores, os contornos das velas serão desenhadas usando a primeira cor, enquanto o as velas de alta e baixa serão definidas usando uma segunda e terceira.
//--- o cor das velas é diferente da cor das sombras #property indicator_label1 "One color candles" #property indicator_type1 DRAW_CANDLES //--- as sombras e contornos de cor verde; o corpo da vela de alta de cor branca; corpo da vela de baixa de cor vermelha #property indicator_color1 clrGreen,clrWhite,clrRedAssim, usando o estilo DRAW_CANDLES, é possível criar suas próprias opções personalizadas para colorir velas. Também é possível alterar dinamicamente todas as cores -no processo de trabalho do indicador- mediante a função PlotIndexSetInteger(índice_de_construção_DRAW_CANDLES, PLOT_LINE_COLOR, número_de_modificador, cor), aqui o número_de_modificador pode ter os seguintes valores:
//--- definimos a cor do contorno e das sombras PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrBlue); //--- definimos a cor do corpo para a vela de alta PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrGreen); //--- definimos a cor do corpo para a vela de baixa PlotIndexSetInteger(0,PLOT_LINE_COLOR,2,clrRed);
Documentação atualizada.
class CFoo final { //--- corpo da classe }; class CBar : public CFoo { //--- тело класса };Ao tentar herdar a partir da classe com o modificador final, como foi mostrado no exemplo acima, o compilador exibirá o erro:
class CFoo { void virtual func(int x) const { } };Além disso, o método é substituído na classe herdada:
class CBar : public CFoo { void func(short x) { } };No entanto, de acordo com o erro, o tipo de argumento é alterado de int para short. De fato, neste caso, não acontece uma substituição, senão uma sobrecarga do método. Após agir segundo o algoritmo para determinar a função sobrecarregada, em determinadas situações, o compilador pode selecionar o método definido na classe base, em vez do método substituído.
class CBar : public CFoo { void func(short x) override { } };Se, durante a substituição, for alterada a assinatura do método, o compilador não poderá encontrar, na classe pai, o método com exatamente a mesma assinatura e exibirá o erro de compilação:
class CFoo { void virtual func(int x) final { } }; class CBar : public CFoo { void func(int) { } };Ao tentar substituir o método com o modificador final, como foi mostrado no exemplo acima, o compilador exibirá o erro:
Documentação atualizada.
class CFoo { }; class CBar { }; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { void *vptr[2]; vptr[0]=new CFoo(); vptr[1]=new CBar(); //--- for(int i=0;i<ArraySize(vptr);i++) { if(dynamic_cast<CFoo *>(vptr[i])!=NULL) Print("CFoo * object at index ",i); if(dynamic_cast<CBar *>(vptr[i])!=NULL) Print("CBar * object at index ",i); } CFoo *fptr=vptr[1]; // emitirá o erro de apresentação de ponteiros, vptr[1] não é um objeto CFoo } //+------------------------------------------------------------------+
string text="Hello"; ushort symb=text[0]; // retorna o código do símbolo 'H'
Documentação atualizada.
Foi corrigido o cálculo da comissão em porcentagens anuais.Ъ
Foi corrigido o recálculo e a exibição do saldo no gráfico formado durante o teste.
Após 2 meses de testes públicos, anunciamos o lançamento oficial da versão web da plataforma multimercado MetaTrader 5. Ela permite negociar nos mercados financeiros através de qualquer navegador em qualquer sistema operacional. E, para isso, não é necessário instalar nenhum programa no computador, de fato, basta ter acesso à internet ou qualquer navegador web.
O aplicativo combina as vantagens chave da plataforma desktop (velocidade, faceta multimercado e características de negociação melhoradas) com a comodidade e o caráter multi-plataforma. A principal novidade da versão atualizada é o livro de ofertas para avaliar a profundidade do mercado, bem como a colocação num clique de ordens de mercado e pendentes.
A plataforma web permite realizar análise técnica e executar
negociações da mesma forma como na versão desktop. No aplicativo, você
tem à sua disposição:
Agora tornou-se cômodo transferir certificados SSL a partir da plataforma desktop para a plataforma móvel. Você já não precisará de utilizar iTunes.
Na MetaTrader 5, é possível pôr em segurança a conta usando um certificado, sem o qual é impossível acessar a ela. Se você criar o certificado na versão desktop, para acessar a conta, irá precisar de o transferir para a plataforma móvel.
Para fazer isso, agora, basta abrir a plataforma desktop e selecionar a transferência usando o botão direito na conta, no navegador. A seguir, para pôr em segurança o certificado, será necessário estabelecer uma senha (conhecida só por você), abrir a plataforma móvel e acessar à conta. Seguidamente, será solicitado importar o certificado.
Além disso, aparecerá uma janela sobre migração para contas transferidas a partir da MetaTrader 4. Se a sua conta tiver sido transferida para a plataforma de quinta geração, você será calorosamente cumprimentado para lhe solicitar em seguida alterar a senha.
Foi | Tornou-se | |
---|---|---|
Ativação | Todos os tipos de ordens pendentes e ordens SL/TP segundo o Bid/Ask | Ordens limit segundo o Bid/Ask Ordens stop-limit e SL/TP segundo o Last |
Execução | Todos os tipos de ordens pendentes e ordens SL/TP segundo o preço na ordem anunciada | Todos os tipos de ordens pendentes e ordens SL/TP segundo o Bid/Ask no momento de ativação |
Examinemos um exemplo no instrumento Si-6.16. Tendo os atuais preços Bid=72570, Ask=72572, Last=72552 colocamos a ordem Buy Stop com preço de ativação 72580. No fluxo de preços, obtemos uns novos preços:
Nos instrumentos financeiros, o peço Last é o gatilho para a ativação de ordens stop. Por isso, a obtenção, no fluxo de preços, dum Last = 72 580 resultou na ativação das ordens Buy Stop. Anteriormente, o preço 72.580 era utilizado precisamente para a execução dessa ordem. Este comportamento era impróprio porque o preço Ask=72580, para a execução de operações de compra no mercado, não existia.
2016.05.10 12:47:53 Core 1 5.10 Mb of history processed in 0:00.842 2016.05.10 12:47:53 Core 1 GBPUSD: history synchronization completed [5225 Kb]
A atualização estará disponível através do sistema LiveUpdate.
Em resposta aos numerosos pedidos dos traders foi desenvolvida uma versão web da plataforma MetaTrader 5. O novo produto combina a comodidade e o caráter multi-plataforma com as vantagens da quinta versão para PC, isto é: velocidade, faceta multimercado e características de negociação melhoradas.
A plataforma web MetaTrader 5 agora está disponível no site da MQL5.community. Ela permite negociar nos mercados financeiros através de qualquer navegador em qualquer sistema operativo (Windows, Mac, Linux). E, para isso, não precisa de instalar nenhum programa adicional, de fato, basta ter acesso à internet.
Na versão beta, os traders têm imediatamente à sua disposição:
Sistema de compensação
Este sistema de registro implica que
num dado momento, possa haver apenas uma posição aberta, segundo um
mesmo símbolo, na conta:
Neste caso, não importa a ação pela qual é realizada a transação na
direção oposta, por outras palavras, é indiferente se foi resultado da
execução de uma ordem de mercado ou devido à ativação de uma ordem
pendente.
Abaixo mostramos um exemplo da execução de duas transações de compra de EURUSD com um volume de 0,5 lotes cada:
Como resultado da execução destas transações, temos uma posição geral com um volume de 1 lote.
Sistema de cobertura
Este sistema de registro permite que você tenha múltiplas posições do mesmo instrumento, incluindo em direções opostas.
Se, segundo um instrumento de negociação, existir uma posição aberta e o
trader executar uma nova transação (ou se estiver ativa uma ordem
pendente), ocorrerá a abertura de uma nova posição. A posição atual não
será alterada.
Abaixo mostramos um exemplo da execução de duas transações de compra de EURUSD com um volume de 0,5 lotes cada:
Como resultado da execução destas transações, temos a abertura de duas posições distintas.
Novo tipo de operação de negociação Close By
Para contas com
cobertura de registro de posições foi adicionado um novo tipo de
operação de negociação, isto é, o fechamento de uma posição usando uma
oposta. Esta operação permite fechar simultaneamente duas posições
opostas de um mesmo instrumento. Se as posições opostas tiverem
diferentes números de lotes, então, permanecerá aberta apenas uma das
duas ordens. O seu volume será igual à diferença dos lotes de duas
posições fechadas, e a direção da posição e o preço de abertura serão
iguais à maior (em volume) das posições fechadas.
Em comparação com o fechamento individual de duas posições, o fechamento da oposta permite ao trader poupar um spread:
Ao fechar uma posição usando uma oposta, você estará colocando uma ordem do tipo "close by". Nos comentários estão indicados os bilhetes das posições fechadas. Ao executar duas transações do tipo "out by", estará sendo fechado um par de posições opostas. O tamanho do lucro/perda brutos, resultante do fechamento de duas posições, é indicado apenas numa única transação.
Quando fizer a importação, os bilhetes de ordens e posições (incluindo
as ordens do histórico) não serão salvos, uma vez que uma entrada no
histórico de negociação MetaTrader 4 pode corresponder até a 4 entradas
no histórico da MetaTrader 5. São colocados novos bilhetes para todas as
entradas de negociação.
Os números das contas podem ser salvos ou substituídos por novos, dependendo de como a corretora faça a importação.
class CAnimal { public: CAnimal(); // construtor virtual void Sound() = 0; // função virtual pura private: double m_legs_count; // número de patas do animal };Aqui a função Sound() é virtual pura, porque está declarada pelo especificador da função virtual PURE (=0).
class CAnimal { public: virtual void Sound()=NULL; // PURE method, deve ser redefinido no descendente, a mesma classe tornou-se abstrata e não pode ser criada }; //--- descendente da classe abstrata class CCat : public CAnimal { public: virtual void Sound() { Print("Myau"); } // PURE redefinido, a classe CCat não é abstrata e pode ser criada }; //--- examples of wrong use new CAnimal; // erro 'CAnimal' - o compilador emitirá o erro "cannot instantiate abstract class" CAnimal some_animal; // erro 'CAnimal' - o compilador emitirá o erro "cannot instantiate abstract class" //--- exemplos de uso correto new CCat; // não há erro - a classe CCat não é abstrata CCat cat; // não há erro - a classe CCat não é abstrataRestrições sobre o uso de classes abstratas
//+------------------------------------------------------------------+ //| Classe básica abstrata | //+------------------------------------------------------------------+ class CAnimal { public: //--- função virtual pura virtual void Sound(void)=NULL; //--- função void CallSound(void) { Sound(); } //--- construtor CAnimal() { //--- chamada direta do método virtual Sound(); //--- chamada indireta (através de una terceira função) CallSound(); //--- no construtor e/ou destrutor sempre são chamadas suas funções, //--- apesar do caráter virtual e da redefinição da função da chamada no descendente //--- se a função chamada for virtual pura, então, //--- a chamada provocará um erro crítico de execução: "pure virtual function call" } };No entanto, os construtores e destruidores de classes abstratas podem chamar outras funções membro.
typedef int (*TFunc)(int,int);Agora TFunc é um tipo e é possível declarar o indicador mutável para a função:
TFunc func_ptr;Na mutável func_ptr é possível armazenar o endereço da função para, no futuro, chamá-la:
int sub(int x,int y) { return(x-y); } int add(int x,int y) { return(x+y); } int neg(int x) { return(~x); } func_ptr=sub; Print(func_ptr(10,5)); func_ptr=add; Print(func_ptr(10,5)); func_ptr=neg; // error: neg is not of int (int,int) type Print(func_ptr(10)); // error: there should be two parametersIndicadores para funções podem ser armazenados e transferidos como um parâmetro. É impossível obter um indicador para um método não estático de uma classe.
ulong PositionGetTicket( int index // número na lista de posições );
bool PositionSelectByTicket( ulong ticket // bilhete da posição );
Sistema de compensação
Este sistema de registro implica que
num dado momento, possa haver apenas uma posição aberta, segundo um
mesmo símbolo, na conta:
Neste caso, não importa a ação pela qual é realizada a transação na
direção oposta, por outras palavras, é indiferente se foi resultado da
execução de uma ordem de mercado ou devido à ativação de uma ordem
pendente.
Abaixo mostramos um exemplo da execução de duas transações de compra de EURUSD com um volume de 0,5 lotes cada:
Como resultado da execução destas transações, temos uma posição geral com um volume de 1 lote.
Sistema de cobertura
Este sistema de registro permite que você tenha múltiplas posições do mesmo instrumento, incluindo em direções opostas.
Se, segundo um instrumento de negociação, existir uma posição aberta e o
trader executar uma nova transação (ou se estiver ativa uma ordem
pendente), ocorrerá a abertura de uma nova posição. A posição atual não
será alterada.
Abaixo mostramos um exemplo da execução de duas transações de compra de EURUSD com um volume de 0,5 lotes cada:
Como resultado da execução destas transações, temos a abertura de duas posições distintas.
Novo tipo de operação de negociação Close By
Para contas com
cobertura de registro de posições foi adicionado um novo tipo de
operação de negociação, isto é, o fechamento de uma posição usando uma
oposta. Esta operação permite fechar simultaneamente duas posições
opostas de um mesmo instrumento. Se as posições opostas tiverem
diferentes números de lotes, então, permanecerá aberta apenas uma das
duas. O seu volume será igual à diferença dos lotes de duas posições
fechadas, e a direção da posição e o preço de abertura serão iguais à
maior (em volume) das posições fechadas.
Em comparação com o fechamento individual de duas posições, o fechamento da oposta permite ao trader poupar um spread:
Ao fechar a posição usando outra oposta, estabelece-se uma ordem do tipo "close by". No seu comentário são indicados os bilhetes das posições fechadas. O fechamento de duas posições opostas ocorre usando duas transações do tipo "out by". O tamanho do lucro/perda total, obtido como resultado do fechamento de ambas as posições, é indicado apenas em uma transação.
class CAnimal { public: CAnimal(); // construtor virtual void Sound() = 0; // função virtual pura private: double m_legs_count; // número de patas do animalAqui a função Sound() é virtual pura, porque está declarada pelo especificador da função virtual PURE (=0).
class CAnimal { public: virtual void Sound()=NULL; // PURE method, deve ser redefinido no descendente, a mesma classe tornou-se abstrata e não pode ser criada }; //--- descendente da classe abstrata class CCat : public CAnimal { public: virtual void Sound() { Print("Myau"); } // PURE redefinido, a classe CCat não é abstrata e pode ser criada }; //--- exemplos de uso correto new CAnimal; // erro 'CAnimal' - o compilador emitirá o erro "cannot instantiate abstract class" CAnimal some_animal; // erro 'CAnimal' - o compilador emitirá o erro "cannot instantiate abstract class" //--- exemplos de uso correto new CCat; // não há erro - a classe CCat não é abstrata CCat cat; // não há erro - a classe CCat não é abstrataRestrições sobre o uso de classes abstratas
//+------------------------------------------------------------------+ //| Classe básica abstrata | //+------------------------------------------------------------------+ class CAnimal { public: //--- função virtual pura virtual void Sound(void)=NULL; //--- função void CallSound(void) { Sound(); } //--- construtor CAnimal() { //--- chamada direta do método virtual Sound(); //--- chamada indireta (através de una terceira função) CallSound(); //--- no construtor e/ou destrutor sempre são chamadas suas funções, //--- apesar do caráter virtual e da redefinição da função da chamada no descendente //--- se a função chamada for virtual pura, então, //--- a chamada provocará um erro crítico de execução: "pure virtual function call" } };No entanto, os construtores e destruidores de classes abstratas podem chamar outras funções membro.
typedef int (*TFunc)(int,int);Agora TFunc é um tipo e é possível declarar o indicador mutável para a função:
TFunc func_ptr;Na mutável func_ptr é possível armazenar o endereço da função para, no futuro, chamá-la:
int sub(int x,int y) { return(x-y); } int add(int x,int y) { return(x+y); } int neg(int x) { return(~x); } func_ptr=sub; Print(func_ptr(10,5)); func_ptr=add; Print(func_ptr(10,5)); func_ptr=neg; // erro: neg não tem tipo int (int,int) Print(func_ptr(10)); // erro: deve ter dois parâmetrosIndicadores para funções podem ser armazenados e transferidos como um parâmetro. É impossível obter um indicador para um método não estático de uma classe.
ulong PositionGetTicket( int index // número na lista de posições );
bool PositionSelectByTicket(
ulong ticket // bilhete da posição
);