Re: Coder en MQL5 le Portefeuille Permanent de Harry Browne
Publié : 15 nov. 2018, 20:25
Voilà , j'ai MT5, tout est pret
Bourse / Trading / Finance / Économie / Crypto Monnaies / FinTech
http://www.videobourse.fr/forum-forex/
Code : Tout sélectionner
//+------------------------------------------------------------------+
//| eaPermanentPortfolio.mq5 |
//| Copyright 2018, Pierre Rougier |
//| http://www.apprendre-mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Pierre Rougier"
#property link "http://www.apprendre-mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
CTrade myTradingControlPanel;
input int capital_dedicated_to_strategy=10000;
input string stocks= "VTI";
input string bonds ="TLTUS";
input string cash = "SHY";
input string gold = "GLD";
input int magicNumber=12345;
int year_saved=0;
bool is_trades_already_open=false;
double total_current_value=0;
double target_value=0;
double current_value_stocks= 0;
double current_value_bonds = 0;
double current_value_cash = 0;
double current_value_gold = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
MqlDateTime mql_datetime;
TimeToStruct(iTime(_Symbol,_Period,0),mql_datetime);
year_saved=mql_datetime.year;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
if(isNewYear())
{
if(!is_trades_already_open)
{StartStrategy();}
else
{RebalanceAllAssetsClass();}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool isNewYear()
{
MqlDateTime mql_datetime;
TimeToStruct(iTime(_Symbol,_Period,0),mql_datetime);
if(mql_datetime.year!=year_saved)
{
year_saved=mql_datetime.year;
return true;
}
else
{return false;}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void StartStrategy()
{
target_value=capital_dedicated_to_strategy/4;
Print("/*§§*/ total_current_value :"+DoubleToString(total_current_value));
Print("/*§§*/ target_value :"+DoubleToString(target_value));
Rebalance(stocks,0);
Rebalance(bonds,0);
Rebalance(cash,0);
Rebalance(gold,0);
is_trades_already_open=true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void RebalanceAllAssetsClass()
{
ComputeValuePositionsByAssetsClass();
total_current_value=current_value_stocks+current_value_bonds+current_value_cash+current_value_gold;
target_value=total_current_value/4;
Print("/*§§*/ total_current_value :"+DoubleToString(total_current_value));
Print("/*§§*/ target_value :"+DoubleToString(target_value));
Rebalance(stocks,current_value_stocks);
Rebalance(bonds,current_value_bonds);
Rebalance(cash,current_value_cash);
Rebalance(gold,current_value_gold);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Rebalance(string asset_class_type,double current_value_asset)
{
double amount=0;
int quantity=0;
double ask=SymbolInfoDouble(asset_class_type,SYMBOL_ASK);
if(current_value_asset>target_value)
{
amount=current_value_asset-target_value;
quantity=(int)NormalizeDouble((amount/ask),0);
if(quantity>0)
{
SellSurplusAssetClass(asset_class_type,quantity);
}
}
else
{
amount=target_value-current_value_asset;
quantity=(int)NormalizeDouble((amount/ask),0);
if(quantity>0)
{
BuyMissingPartAssetClass(asset_class_type,quantity);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void BuyMissingPartAssetClass(string asset_class_type,int quantity)
{
// Open a Buy (i.e. long) position
myTradingControlPanel.PositionOpen(asset_class_type,ORDER_TYPE_BUY,quantity,
0,
// SymbolInfoDouble(asset_class_type,SYMBOL_ASK),
0,0,"Buy Trade. Magic Number #"
+(string) myTradingControlPanel.RequestMagic());
// Request is completed or order placed
if(myTradingControlPanel.ResultRetcode()==TRADE_RETCODE_PLACED || myTradingControlPanel.ResultRetcode()==TRADE_RETCODE_DONE)
{
Print("Entry rules: A ",asset_class_type," Buy order has been successfully placed with Ticket#: ",myTradingControlPanel.ResultOrder());
}
else
{
Print("Entry rules: A ",asset_class_type," Buy order request could not be completed. Error: ",GetLastError());
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SellSurplusAssetClass(string asset_class_type,int quantity)
{
// Close position
myTradingControlPanel.PositionOpen(asset_class_type,ORDER_TYPE_SELL,quantity,
0,
// SymbolInfoDouble(asset_class_type,SYMBOL_ASK),
0,0,"Sell Trade. Magic Number #"
+(string) myTradingControlPanel.RequestMagic());
// Request is completed or order placed
if(myTradingControlPanel.ResultRetcode()==TRADE_RETCODE_PLACED || myTradingControlPanel.ResultRetcode()==TRADE_RETCODE_DONE)
{
Print("Entry rules: A ",asset_class_type," Sell order has been successfully placed with Ticket#: ",myTradingControlPanel.ResultOrder());
}
else
{
Print("Entry rules: A ",asset_class_type," Sell order request could not be completed. Error: ",GetLastError());
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ComputeValuePositionsByAssetsClass()
{
// Loop through all open positions
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticketNumber=0;
// This selects open position by the order they appear in our list of positions
ticketNumber=PositionGetTicket(i);
if(ticketNumber==0)
{
Print("Exit rules: Position exists but not selected. Error: ",GetLastError());
ResetLastError();
continue;
}
if(PositionGetInteger(POSITION_MAGIC)==magicNumber)
{
string symbol=PositionGetString(POSITION_SYMBOL);
if(symbol==stocks)
{
current_value_stocks=current_value_stocks+PositionGetDouble(POSITION_PRICE_CURRENT);
}
else if(symbol==bonds)
{
current_value_bonds=current_value_bonds+PositionGetDouble(POSITION_PRICE_CURRENT);
}
else if(symbol==cash)
{
current_value_cash=current_value_cash+PositionGetDouble(POSITION_PRICE_CURRENT);
}
else if(symbol==gold)
{
current_value_gold=current_value_gold+PositionGetDouble(POSITION_PRICE_CURRENT);
}
}
}
};
//+------------------------------------------------------------------+
Code : Tout sélectionner
//+------------------------------------------------------------------+
//| eaPermanentPortfolio.mq5 |
//| Copyright 2018, Pierre Rougier |
//| http://www.apprendre-mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Pierre Rougier"
#property link "http://www.apprendre-mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
CTrade trade_control;
input int capital_dedicated_to_strategy=10000;
input string stocks= "VTI";
input string bonds ="TLTUS";
input string cash = "SHY";
input string gold = "GLD";
input int magicNumber=12345;
int year_saved=0;
bool is_trades_already_open=false;
double total_current_value=0;
double target_value=0;
double current_value_stocks= 0;
double current_value_bonds = 0;
double current_value_cash = 0;
double current_value_gold = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
trade_control.SetExpertMagicNumber(magicNumber); // Set Magic Number
MqlDateTime mql_datetime;
TimeToStruct(iTime(_Symbol,_Period,0),mql_datetime);
year_saved=mql_datetime.year;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
if(isNewYear())
{
if(!is_trades_already_open)
{StartStrategy();}
else
{RebalanceAllAssetsClass();}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool isNewYear()
{
MqlDateTime mql_datetime;
TimeToStruct(iTime(_Symbol,_Period,0),mql_datetime);
if(mql_datetime.year!=year_saved)
{
year_saved=mql_datetime.year;
return true;
}
else
{return false;}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void StartStrategy()
{
target_value=capital_dedicated_to_strategy/4;
Print("/*§§*/ total_current_value :"+DoubleToString(total_current_value));
Print("/*§§*/ target_value :"+DoubleToString(target_value));
Rebalance(stocks,0);
Rebalance(bonds,0);
Rebalance(cash,0);
Rebalance(gold,0);
is_trades_already_open=true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void RebalanceAllAssetsClass()
{
ComputeValuePositionsByAssetsClass();
total_current_value=current_value_stocks+current_value_bonds+current_value_cash+current_value_gold;
target_value=total_current_value/4;
Print("/*§§*/ total_current_value :"+DoubleToString(total_current_value));
Print("/*§§*/ target_value :"+DoubleToString(target_value));
Rebalance(stocks,current_value_stocks);
Rebalance(bonds,current_value_bonds);
Rebalance(cash,current_value_cash);
Rebalance(gold,current_value_gold);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Rebalance(string asset_class_type,double current_value_asset)
{
double amount=0;
int quantity=0;
double ask=SymbolInfoDouble(asset_class_type,SYMBOL_ASK);
if(current_value_asset>target_value)
{
amount=current_value_asset-target_value;
quantity=(int)NormalizeDouble((amount/ask),0);
if(quantity>0)
{
SellSurplusAssetClass(asset_class_type,quantity);
}
}
else
{
amount=target_value-current_value_asset;
quantity=(int)NormalizeDouble((amount/ask),0);
if(quantity>0)
{
BuyMissingPartAssetClass(asset_class_type,quantity);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void BuyMissingPartAssetClass(string asset_class_type,int quantity)
{
// Open a Buy (i.e. long) position
trade_control.PositionOpen(asset_class_type,ORDER_TYPE_BUY,quantity,
0,
// SymbolInfoDouble(asset_class_type,SYMBOL_ASK),
0,0,"Buy Trade. Magic Number #"
+(string) trade_control.RequestMagic());
// Request is completed or order placed
if(trade_control.ResultRetcode()==TRADE_RETCODE_PLACED || trade_control.ResultRetcode()==TRADE_RETCODE_DONE)
{
Print("Entry rules: A ",asset_class_type," Buy order has been successfully placed with Ticket#: ",trade_control.ResultOrder());
}
else
{
Print("Entry rules: A ",asset_class_type," Buy order request could not be completed. Error: ",GetLastError());
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SellSurplusAssetClass(string asset_class_type,int quantity)
{
// Close position
trade_control.PositionClosePartial(asset_class_type,quantity);
// Request is completed or order placed
if(trade_control.ResultRetcode()==TRADE_RETCODE_PLACED || trade_control.ResultRetcode()==TRADE_RETCODE_DONE)
{
Print("Entry rules: A ",asset_class_type," Sell order has been successfully placed with Ticket#: ",trade_control.ResultOrder());
}
else
{
Print("Entry rules: A ",asset_class_type," Sell order request could not be completed. Error: ",GetLastError());
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ComputeValuePositionsByAssetsClass()
{
// Loop through all open positions
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticketNumber=0;
// This selects open position by the order they appear in our list of positions
ticketNumber=PositionGetTicket(i);
if(ticketNumber==0)
{
Print("Exit rules: Position exists but not selected. Error: ",GetLastError());
ResetLastError();
continue;
}
if(PositionGetInteger(POSITION_MAGIC)==magicNumber)
{
string symbol=PositionGetString(POSITION_SYMBOL);
if(symbol==stocks)
{
current_value_stocks=current_value_stocks+PositionGetDouble(POSITION_PROFIT);
}
else if(symbol==bonds)
{
current_value_bonds=current_value_bonds+PositionGetDouble(POSITION_PROFIT);
}
else if(symbol==cash)
{
current_value_cash=current_value_cash+PositionGetDouble(POSITION_PROFIT);
}
else if(symbol==gold)
{
current_value_gold=current_value_gold+PositionGetDouble(POSITION_PROFIT);
}
}
}
};
//+------------------------------------------------------------------+
Merci.Trader55 a écrit :C'est super Pierre !!!
Il faut faire un back test en daily, sinon le back test démarre plus tard.Trader55 a écrit :Pas de problèmes particuliers pour backtester en multipaires ?
Il a travaillé 2 fois pour moi.Trader55 a écrit :Au fait, en sortant juste un peu du sujet, quel retour d’expérience avec angevoyageur de mql ?
Je sais qu'il est top pour résoudre les pb sur le forum , et en temps que développeur ?
L'history quality pour une stratégie qui ouvre des ordres une fois par an est à mon avis sans importance.Trader55 a écrit :Ce qui est important ce n'est pas le graphique mais le rport.
Regardes le tien, tu as pris le gold comme chart source et ton history quality est de 2% vs le mien de 94%...
Il faut au moins un history qualtity de 90%, le mieux c'est 99%
Attention !!! , ma file n'est pas une incitation d'investir dans un portefeuille permanent, ou un autre genre de placement.Trader55 a écrit : J'envisage d'ouvrir une petite assurance vie supplémentaire et y repartir ce modèle en UC.
Je me rends compte que je me suis trompé.Trader55 a écrit :La demarche n'est pas mauvaise.
Heureusement il y a si peu de valeurs (4*13) qu'un bon fichier excel t'aidera à trouver le résultat exact...
Je peux faire çà ce weekend si tu me passes ici les valeurs des 4 ETF
au 1er janvier de 2005 à 2018 (enfin à la première date de cotation du début de l'année).
Have a nice evening