MtApi5: custom symbols support (CustomSymbol*, CustomRates*, CustomTicks*)#307
Open
biohazardxxx wants to merge 7 commits into
Open
MtApi5: custom symbols support (CustomSymbol*, CustomRates*, CustomTicks*)#307biohazardxxx wants to merge 7 commits into
biohazardxxx wants to merge 7 commits into
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MqlRates[]/MqlTick[] are serialized into the command payload as JSON arrays using the same field names the EA emits for the reverse direction. MqlTick gains a time_msc field (falls back to MtTime*1000 when unset). Int-returning functions propagate the native -1 failure value. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…340-350) Adds JsonToMqlRates/JsonToMqlTick (and array variants) to parse struct arrays from the command payload - the reverse of MqlRatesToJson / MqlTickToJson. Tick time is reconciled between seconds and time_msc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fix JsonToMqlRates/JsonToMqlTick always failing at runtime: they used json.mqh's checked out-parameter getters (getLong/getDouble/getInt with out params), which gate on isNumber() -- but JSONNumber constructors never call setType(JSON_NUMBER), so _type stays JSON_NULL and every numeric read returned false. All four struct-array commands (CustomRatesReplace/CustomRatesUpdate/CustomTicksAdd/CustomTicksReplace) therefore answered 'Failed to parse parameter Rates/Ticks'. Follow the house pattern of JsonToMqlTradeRequest instead: null-check jo.getValue(key), then read via the one-arg unchecked getters. Recompiled MtApi5.ex5 (0 errors, 0 warnings). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MqlTickToJson never emitted time_msc and the MtTick protocol DTO had no field for it, so the C# MqlTick.time_msc introduced with the custom symbols feature was always 0 on the receive path. Verified live: millisecond timestamps now populate for forex ticks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
|
Pushed a completing fix: MqlTickToJson never emitted time_msc and the MtTick protocol DTO had no field for it, so the C# MqlTick.time_msc added in this PR was always 0 on the receive path (CopyTicks/SymbolInfoTick). Now round-trips in both directions — verified live: millisecond timestamps populate for forex ticks (e.g. 1783588818147/…360/…372 within one second). Recompiled ex5 included. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds MT5 custom symbols support to the MtApi5 connector. MQL5 can create synthetic instruments and feed them history/ticks natively (
CustomSymbolCreate,CustomRatesUpdate,CustomTicksAdd, …) but none of it was reachable from the .NET client. This adds 11CustomSymbol*/CustomRates*/CustomTicks*functions end-to-end.C# client (
MtApi5) — 11 methods onMtApi5Client:bool CustomSymbolCreate(string symbolName, string symbolPath = "", string symbolOrigin = "")bool CustomSymbolDelete(string symbolName)bool CustomSymbolSetDouble(string symbolName, ENUM_SYMBOL_INFO_DOUBLE propertyId, double value)bool CustomSymbolSetInteger(string symbolName, ENUM_SYMBOL_INFO_INTEGER propertyId, long value)bool CustomSymbolSetString(string symbolName, ENUM_SYMBOL_INFO_STRING propertyId, string value)int CustomRatesDelete(string symbolName, DateTime from, DateTime to)int CustomRatesReplace(string symbolName, DateTime from, DateTime to, MqlRates[] rates)int CustomRatesUpdate(string symbolName, MqlRates[] rates)int CustomTicksAdd(string symbolName, MqlTick[] ticks)int CustomTicksDelete(string symbolName, long fromMsc, long toMsc)int CustomTicksReplace(string symbolName, long fromMsc, long toMsc, MqlTick[] ticks)MQL5 EA (
mq5/MtApi5.mq5) — 11Execute_Custom*handlers +ADD_EXECUTORregistrations (ids 340–350) + newJsonToMqlRates/JsonToMqlTick/JsonToMqlRatesArray/JsonToMqlTickArrayparse helpers.mq5/MtApi5.ex5recompiled and included.TestClient — a
CustomSymbolTestbutton that runs the full lifecycle manually (create → set int/double/string properties →CustomRatesUpdate3 bars →SymbolSelect→CustomTicksAdd2 ticks →CustomTicksDelete→CustomRatesDelete→ deselect →CustomSymbolDelete, each result logged).Implementation notes
MtApi5/MtProtocol/Mt5CommandType.csand the mq5ADD_EXECUTORregistrations.MqlRates[]uses theMqlRatesToJsonkeys (mt_time,open,high,low,close,tick_volume,spread,real_volume; datetimes as unix seconds),MqlTick[]uses theMqlTickToJsonkeys plusTimeMsc(Time,TimeMsc,Bid,Ask,Last,Volume,VolumeReal,Flags); flags sent asuint,volume_realasdouble. The mq5 parse helpers usejson.mqhwithZeroMemoryon struct elements and follow the house pattern ofJsonToMqlTradeRequest(null-checkgetValue(key)then read via the one-arg getters — the type-checked out-parameter getters injson.mqhdon't work for numbers because the parser never setsJSON_NUMBER).MqlTick(C#) gained an additive publiclong time_mscproperty (the class previously only had second-resolutionMtTime); serialization falls back toMtTime * 1000whentime_mscis 0, and the EA reconcilestime/time_mscin both directions.boolcommands propagate the raw native bool,intcommands propagate the raw native return including-1(success responses, noCreateErrorResponsemapping) — matching the calendar-PR philosophy (post-d8c459fd).MT5Connector.cppconvertSystemStringtruncates inbound command payloads at 1000 wide chars (memcpybounded bywcsnlen(..., 1000)), even though the EA-side buffer is 5000. Payloads with more than roughly 6 rates or 5–6 ticks per call get truncated at runtime and the EA answers "Failed to get payload". Callers must chunk large arrays:CustomRatesUpdate/CustomTicksAddare incremental so chunking is semantically safe; a chunkedCustomRatesReplace/CustomTicksReplaceis not equivalent to one atomic call. The TestClient action keeps its arrays within this cap.devand contains custom-symbols changes only.Testing
MtApi5builds clean (Release, 0 warnings / 0 errors);MtApi5TestClientbuilds with 0 errors (only pre-existing nullability-pattern warnings).mq5/MtApi5.mq5compiles via MetaEditor with "Result: 0 errors"; the recompiledMtApi5.ex5is included.CustomSymbolTestbutton is provided for a live round-trip, which I'd recommend before merge.🤖 Generated with Claude Code