| |
| |
| |
| |
| |
| #property copyright "Algorembrant, Rembrant Oyangoren Albeos" |
| #property link "https://github.com/Algorembrant" |
| #property version "1.00" |
|
|
| #include <Trade\Trade.mqh> |
| CTrade trade; |
|
|
| |
| input string ONNX_Filename = "RL_Agent_XAUUSD.onnx"; |
| input double RiskPercent = 2.0; |
|
|
| long model_handle = INVALID_HANDLE; |
| double max_lot_size = 20.0; |
|
|
| int OnInit() { |
| Print("Initializing RL XAUUSDc ONNX EA..."); |
| |
| |
| model_handle = OnnxCreate(ONNX_Filename, ONNX_DEFAULT); |
| if(model_handle == INVALID_HANDLE) { |
| Print("Error loading ONNX model ", ONNX_Filename, " : ", GetLastError()); |
| return INIT_FAILED; |
| } |
| |
| trade.SetExpertMagicNumber(2026101); |
| |
| return INIT_SUCCEEDED; |
| } |
|
|
| void OnDeinit(const int reason) { |
| if(model_handle != INVALID_HANDLE) |
| OnnxRelease(model_handle); |
| Print("EA Deinitialized."); |
| } |
|
|
| void OnTick() { |
| |
| static datetime last_time = 0; |
| datetime current_time = iTime(_Symbol, _Period, 0); |
| |
| |
| if(current_time == last_time) return; |
| last_time = current_time; |
| |
| |
| |
| |
| |
| float features[]; |
| int num_features = 100; |
| ArrayResize(features, num_features); |
| |
| for(int i=0; i<ArraySize(features); i++) { |
| |
| features[i] = 0.0f; |
| } |
| |
| |
| long action_output[] = {3}; |
| |
| |
| if(!OnnxRun(model_handle, ONNX_NO_CONVERSION, features, action_output)) { |
| Print("ONNX Run Error: ", GetLastError()); |
| return; |
| } |
| |
| long action = action_output[0]; |
| |
| |
| double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); |
| double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) * point; |
| double closePrice = iClose(_Symbol, _Period, 1); |
| double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); |
| double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); |
| |
| |
| if(PositionsTotal() > 0) return; |
|
|
| |
| double sl_dist = MathMax(closePrice * 0.005, spread * 10.0); |
| |
| |
| double balance = AccountInfoDouble(ACCOUNT_BALANCE); |
| double risk_amount = balance * (RiskPercent / 100.0); |
| |
| |
| double sl_dollar_risk_per_lot = sl_dist * 100.0; |
| double lots = 0.01; |
| |
| if(sl_dollar_risk_per_lot > 0) |
| lots = risk_amount / sl_dollar_risk_per_lot; |
| |
| |
| lots = MathRound(lots * 100.0) / 100.0; |
| if(lots < 0.01) lots = 0.01; |
| |
| |
| int fragments = 1; |
| double current_fragment_lot = lots; |
| |
| if(lots > max_lot_size) { |
| fragments = (int)MathCeil(lots / max_lot_size); |
| current_fragment_lot = max_lot_size; |
| Print("Notice: Position fragmentization triggered. Total Lot = ", lots, " -> Fragmented into ", fragments, " orders."); |
| } |
|
|
| if(action == 0) { |
| double stoploss = ask - sl_dist; |
| double takeprofit = ask + (sl_dist * 1.5); |
| |
| for(int f=0; f<fragments; f++) { |
| if(f == fragments - 1 && lots > max_lot_size) { |
| |
| current_fragment_lot = lots - (max_lot_size * (fragments - 1)); |
| } |
| trade.Buy(current_fragment_lot, _Symbol, ask, stoploss, takeprofit, "RL_BUY"); |
| } |
| } |
| else if(action == 1) { |
| double stoploss = bid + sl_dist; |
| double takeprofit = bid - (sl_dist * 1.5); |
| |
| for(int f=0; f<fragments; f++) { |
| if(f == fragments - 1 && lots > max_lot_size) { |
| current_fragment_lot = lots - (max_lot_size * (fragments - 1)); |
| } |
| trade.Sell(current_fragment_lot, _Symbol, bid, stoploss, takeprofit, "RL_SELL"); |
| } |
| } |
| } |
|
|