commit 279385d8fc1eedefb38ed10aca22ab8ff3708014 Author: gavindiaz Date: Fri Jul 3 15:30:55 2026 +0800 first commit diff --git a/Experts/MtApi5.ex5 b/Experts/MtApi5.ex5 new file mode 100644 index 0000000..95e1746 Binary files /dev/null and b/Experts/MtApi5.ex5 differ diff --git a/Mt5Bridge.csproj b/Mt5Bridge.csproj new file mode 100644 index 0000000..c3c712d --- /dev/null +++ b/Mt5Bridge.csproj @@ -0,0 +1,25 @@ + + + + Exe + net8.0 + enable + enable + + + + + libs\MtApi5.dll + true + + + libs\MtClient.dll + true + + + libs\Newtonsoft.Json.dll + true + + + + \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..20409df --- /dev/null +++ b/Program.cs @@ -0,0 +1,386 @@ +using MtApi5; +using System.Reflection; + +var builder = WebApplication.CreateBuilder(args); +builder.WebHost.UseUrls("http://localhost:8080"); +builder.Services.AddSingleton(sp => +{ + var client = new MtApi5Client(); + try + { + var prop = typeof(MtApi5Client).GetProperty("CommandTimeout"); + if (prop != null && prop.CanWrite) + { + prop.SetValue(client, 120000); + } + else + { + var field = typeof(MtApi5Client).GetField("_command_timeout", + BindingFlags.NonPublic | BindingFlags.Instance); + field?.SetValue(client, 120000); + } + Console.WriteLine("CommandTimeout set to 120000ms"); + } + catch (Exception ex) + { + Console.WriteLine($"Could not set CommandTimeout: {ex.Message}"); + } + return client; +}); +builder.Services.AddHostedService(); +var app = builder.Build(); + +app.MapGet("/health", (MtApi5Client mt) => +{ + var connected = mt.ConnectionState == Mt5ConnectionState.Connected; + return new { status = connected ? "healthy" : "disconnected", mt5_connected = connected, mt5_version = "unknown", api_version = "1.0.0" }; +}); + +app.MapGet("/account", (MtApi5Client mt) => +{ + var login = (ulong)mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_LOGIN); + var leverage = (uint)mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_LEVERAGE); + var tradeAllowed = mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_TRADE_ALLOWED) != 0; + var tradeExpert = mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_TRADE_EXPERT) != 0; + var currency = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_CURRENCY) ?? "USD"; + var server = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_SERVER) ?? ""; + var name = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_NAME) ?? ""; + var company = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_COMPANY) ?? ""; + var balance = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_BALANCE); + var equity = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_EQUITY); + var profit = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_PROFIT); + var margin = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN); + var marginFree = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN_FREE); + var marginLevel = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN_LEVEL); + + return new + { + data = new[] + { + new { login, leverage, trade_allowed = tradeAllowed, trade_expert = tradeExpert, currency, currency_digits = 2, server, name, company, balance, equity, profit, margin, margin_free = marginFree, margin_level = marginLevel } + }, + count = 1, + format = "json" + }; +}); + +app.MapGet("/symbols/{symbol}", (string symbol, MtApi5Client mt) => +{ + try + { + var digits = (int)mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_DIGITS); + var spreadFloat = mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD_FLOAT) != 0; + var spread = (int)mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD); + var point = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_POINT); + var bid = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID); + var ask = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_ASK); + var volumeMin = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_MIN); + var volumeMax = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_MAX); + var volumeStep = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_STEP); + var contractSize = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_TRADE_CONTRACT_SIZE); + + string description = "", currencyBase = "", currencyProfit = "", path = ""; + try { description = mt.SymbolInfoString(symbol, ENUM_SYMBOL_INFO_STRING.SYMBOL_DESCRIPTION) ?? ""; } catch { } + try { currencyBase = mt.SymbolInfoString(symbol, ENUM_SYMBOL_INFO_STRING.SYMBOL_CURRENCY_BASE) ?? ""; } catch { } + try { currencyProfit = mt.SymbolInfoString(symbol, ENUM_SYMBOL_INFO_STRING.SYMBOL_CURRENCY_PROFIT) ?? ""; } catch { } + try { path = mt.SymbolInfoString(symbol, ENUM_SYMBOL_INFO_STRING.SYMBOL_PATH) ?? ""; } catch { } + + return Results.Ok(new + { + data = new[] + { + new { name = symbol, description, digits, point, bid, ask, spread, spread_float = spreadFloat, volume_min = volumeMin, volume_max = volumeMax, volume_step = volumeStep, trade_contract_size = contractSize, currency_base = currencyBase, currency_profit = currencyProfit, category = path } + }, + count = 1, + format = "json" + }); + } + catch (Exception ex) + { + Console.WriteLine($"ERROR /symbols/{symbol}: {ex.Message}"); + return Results.Problem($"Error: {ex.Message}"); + } +}); + +app.MapGet("/symbols/{symbol}/tick", (string symbol, MtApi5Client mt) => +{ + var tick = mt.SymbolInfoTick(symbol); + if (tick == null) return Results.NotFound(new { detail = $"Tick for {symbol} not found" }); + + return Results.Json(new + { + data = new[] + { + new + { + time = tick.time.ToString("yyyy-MM-ddTHH:mm:ss"), + bid = tick.bid, + ask = tick.ask, + last = tick.last, + volume = tick.volume, + time_msc = tick.time.ToString("yyyy-MM-ddTHH:mm:ss.fff000"), + flags = 6, + volume_real = tick.volume_real + } + }, + count = 1, + format = "json" + }); +}); + +app.MapGet("/rates/from-pos", (string symbol, string timeframe, int start_pos, int count, MtApi5Client mt) => +{ + try + { + var tf = timeframe switch + { + "TIMEFRAME_M1" => ENUM_TIMEFRAMES.PERIOD_M1, + "TIMEFRAME_M5" => ENUM_TIMEFRAMES.PERIOD_M5, + "TIMEFRAME_M15" => ENUM_TIMEFRAMES.PERIOD_M15, + "TIMEFRAME_M30" => ENUM_TIMEFRAMES.PERIOD_M30, + "TIMEFRAME_H1" => ENUM_TIMEFRAMES.PERIOD_H1, + "TIMEFRAME_H4" => ENUM_TIMEFRAMES.PERIOD_H4, + "TIMEFRAME_D1" => ENUM_TIMEFRAMES.PERIOD_D1, + _ => ENUM_TIMEFRAMES.PERIOD_M5 + }; + + const int chunkSize = 1000; + var allRates = new List(); + int remaining = count; + int currentPos = start_pos; + + while (remaining > 0) + { + int chunk = Math.Min(remaining, chunkSize); + var result = mt.CopyRates(symbol, tf, currentPos, chunk, out MqlRates[]? rates); + Console.WriteLine($"CopyRates pos={currentPos} chunk={chunk} result={result}, rates={(rates != null ? rates.Length.ToString() : "null")}"); + + if (rates != null && rates.Length > 0) + { + allRates.AddRange(rates); + currentPos += rates.Length; + remaining -= rates.Length; + if (rates.Length < chunk) break; + } + else + { + break; + } + } + + var data = allRates.Select(r => new + { + time = r.time.ToString("yyyy-MM-ddTHH:mm:ss"), + r.open, + r.high, + r.low, + r.close, + tick_volume = r.tick_volume, + r.spread, + real_volume = r.real_volume + }).ToArray(); + + return Results.Ok(new { data, count = data.Length, format = "json" }); + } + catch (Exception ex) + { + Console.WriteLine($"ERROR /rates/from-pos: {ex.Message}\n{ex.StackTrace}"); + return Results.Problem($"Error: {ex.Message}"); + } +}); + +app.MapGet("/positions", (MtApi5Client mt) => +{ + var total = mt.PositionsTotal(); + var positions = new List(); + for (int i = 0; i < total; i++) + { + var ticket = mt.PositionGetTicket(i); + if (ticket == 0) continue; + positions.Add(new + { + ticket, + symbol = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_SYMBOL), + type = (int)mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_TYPE), + volume = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_VOLUME), + price_open = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PRICE_OPEN), + sl = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_SL), + tp = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_TP), + price_current = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PRICE_CURRENT), + swap = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_SWAP), + profit = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PROFIT), + comment = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_COMMENT), + magic = (ulong)mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_MAGIC) + }); + } + return new { data = positions, count = positions.Count, format = "json" }; +}); + +app.MapGet("/orders", (string? symbol, MtApi5Client mt) => +{ + var total = mt.OrdersTotal(); + var orders = new List(); + for (int i = 0; i < total; i++) + { + var ticket = mt.OrderGetTicket(i); + if (ticket == 0) continue; + var orderSymbol = mt.OrderGetString(ENUM_ORDER_PROPERTY_STRING.ORDER_SYMBOL); + if (symbol != null && orderSymbol != symbol) continue; + orders.Add(new + { + ticket, + symbol = orderSymbol, + type = (int)mt.OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER.ORDER_TYPE), + volume_initial = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_VOLUME_INITIAL), + price_open = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_PRICE_OPEN), + sl = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_SL), + tp = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_TP), + magic = (ulong)mt.OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER.ORDER_MAGIC), + comment = mt.OrderGetString(ENUM_ORDER_PROPERTY_STRING.ORDER_COMMENT) + }); + } + return new { data = orders, count = orders.Count, format = "json" }; +}); + +app.MapPost("/order/check", (TradeRequestDto body, MtApi5Client mt) => +{ + var request = ToMqlTradeRequest(body); + mt.OrderCheck(request, out MqlTradeCheckResult? checkResult); + if (checkResult == null) return new { data = new { retcode = 0u, balance = 0.0, equity = 0.0, profit = 0.0, margin = 0.0, margin_free = 0.0, margin_level = 0.0, comment = "Check failed" }, count = 1, format = "json" }; + return new { data = new { retcode = checkResult.Retcode, balance = checkResult.Balance, equity = checkResult.Equity, profit = checkResult.Profit, margin = checkResult.Margin, margin_free = checkResult.Margin_free, margin_level = checkResult.Margin_level, comment = checkResult.Comment ?? "" }, count = 1, format = "json" }; +}); + +app.MapPost("/order/send", (TradeRequestBody body, MtApi5Client mt) => +{ + var request = ToMqlTradeRequest(body.request); + mt.OrderSend(request, out MqlTradeResult? result); + if (result == null) return new { data = new { retcode = 0u, order = 0ul, comment = "Send failed" }, count = 1, format = "json" }; + return new { data = new { retcode = result.Retcode, order = result.Order, comment = result.Comment ?? "" }, count = 1, format = "json" }; +}); + +app.MapGet("/history/deals", (string date_from, string date_to, string? symbol, MtApi5Client mt) => +{ + var fromDt = DateTime.Parse(date_from); + var toDt = DateTime.Parse(date_to); + mt.HistorySelect(fromDt, toDt); + var total = mt.HistoryDealsTotal(); + var dealList = new List(); + for (int i = 0; i < total; i++) + { + var ticket = mt.HistoryDealGetTicket(i); + if (ticket == 0) continue; + var dealSymbol = mt.HistoryDealGetString(ticket, ENUM_DEAL_PROPERTY_STRING.DEAL_SYMBOL); + if (symbol != null && dealSymbol != symbol) continue; + var dealTime = MtTimeToDateTime(mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_TIME)); + dealList.Add(new + { + ticket, + time = dealTime.ToString("yyyy-MM-ddTHH:mm:ss"), + entry = (int)mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_ENTRY), + magic = (ulong)mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_MAGIC), + volume = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_VOLUME), + price = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PRICE), + profit = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PROFIT), + commission = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_COMMISSION), + swap = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_SWAP), + symbol = dealSymbol, + comment = mt.HistoryDealGetString(ticket, ENUM_DEAL_PROPERTY_STRING.DEAL_COMMENT) ?? "" + }); + } + return new { data = dealList, count = dealList.Count, format = "json" }; +}); + +app.Run(); + +DateTime MtTimeToDateTime(long mtTime) +{ + return new DateTime(1970, 1, 1).AddSeconds(mtTime); +} + +MqlTradeRequest ToMqlTradeRequest(TradeRequestDto r) +{ + return new MqlTradeRequest + { + Action = (ENUM_TRADE_REQUEST_ACTIONS)r.action, + Symbol = r.symbol, + Volume = r.volume ?? 0, + Type = (ENUM_ORDER_TYPE)(r.order_type ?? 0), + Price = r.price ?? 0, + Sl = r.sl ?? 0, + Tp = r.tp ?? 0, + Magic = r.magic ?? 0, + Comment = r.comment ?? "", + Order = r.order ?? 0, + Position = r.position ?? 0, + Deviation = r.deviation ?? 0 + }; +} + +class TradeRequestDto +{ + public uint action { get; set; } + public string symbol { get; set; } = ""; + public double? volume { get; set; } + public uint? order_type { get; set; } + public double? price { get; set; } + public double? sl { get; set; } + public double? tp { get; set; } + public ulong? magic { get; set; } + public string? comment { get; set; } + public ulong? order { get; set; } + public ulong? position { get; set; } + public ulong? deviation { get; set; } +} + +class TradeRequestBody +{ + public TradeRequestDto request { get; set; } = new(); +} + +class MtConnectionService : BackgroundService +{ + private readonly MtApi5Client _client; + private readonly ILogger _logger; + + public MtConnectionService(MtApi5Client client, ILogger logger) + { + _client = client; + _logger = logger; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + var tcs = new TaskCompletionSource(); + _client.ConnectionStateChanged += (s, e) => + { + _logger.LogInformation("MT5 Connection: {Status}", e.Status); + if (e.Status == Mt5ConnectionState.Connected || e.Status == Mt5ConnectionState.Failed || e.Status == Mt5ConnectionState.Disconnected) + tcs.TrySetResult(e.Status == Mt5ConnectionState.Connected); + }; + + _logger.LogInformation("Connecting to MT5 via MtApi5 on port 8228..."); + _client.BeginConnect(8228); + await tcs.Task; + + if (_client.ConnectionState != Mt5ConnectionState.Connected) + { + _logger.LogError("Failed to connect to MT5. Ensure MtApi5 EA is loaded in MT5."); + return; + } + + _logger.LogInformation("MT5 Bridge ready on http://localhost:8080"); + while (!stoppingToken.IsCancellationRequested) + { + await Task.Delay(30000, stoppingToken); + if (_client.ConnectionState != Mt5ConnectionState.Connected) + { + _logger.LogWarning("MT5 disconnected, attempting reconnect..."); + tcs = new TaskCompletionSource(); + _client.BeginConnect(8228); + await tcs.Task; + if (_client.ConnectionState == Mt5ConnectionState.Connected) + _logger.LogInformation("MT5 reconnected."); + } + } + } +} \ No newline at end of file diff --git a/README.md.md b/README.md.md new file mode 100644 index 0000000..5e8def0 --- /dev/null +++ b/README.md.md @@ -0,0 +1,413 @@ +# Mt5Bridge — MT5 HTTP API 网关 + +通过 HTTP REST 接口操控 MetaTrader 5,零依赖、可独立部署。 + +## 架构 + +``` +任何语言的项目 (Rust / Python / Node / Go / ...) + │ + ▼ HTTP REST API (localhost:8080) + │ + Mt5Bridge (C# + MtApi5) + │ + ▼ localhost:8228 + MtApi5 EA (MT5 图表上运行) + │ + ▼ + MetaTrader 5 客户端 +``` + +## 快速开始 + +### 前置条件 + +| 依赖 | 说明 | +| ------------------- | ------------------------------------------------------- | +| .NET 8 SDK | 编译运行 | +| MetaTrader 5 客户端 | 已登录任意账户 | +| MtApi5 EA | 挂载在 MT5 任意图表上,默认监听端口 8228 | +| MtApi5 已安装 | `C:\Program Files\MtApi5\`(本项目 `libs/` 下已有 DLL) | + +### 启动 + +```bash +cd Mt5Bridge +dotnet run +``` + +看到以下输出即启动成功: + +``` +info: MtConnectionService[0] + Connecting to MT5 via MtApi5 on port 8228... +info: MtConnectionService[0] + MT5 Connection: Connected +info: MtConnectionService[0] + MT5 Bridge ready on http://localhost:8080 +``` + +### 健康检查 + +```bash +curl http://localhost:8080/health +``` + +响应示例: + +```json +{ + "status": "healthy", + "mt5_connected": true, + "mt5_version": "unknown", + "api_version": "1.0.0" +} +``` + +--- + +## API 接口 + +### 账户 + +#### `GET /health` + +健康检查,返回 MT5 连接状态。 + +#### `GET /account` + +获取当前账户信息。 + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ------------- | ------ | ---------------- | +| login | number | 账户号 | +| leverage | number | 杠杆 | +| balance | number | 余额 | +| equity | number | 净值 | +| profit | number | 浮动盈亏 | +| margin | number | 已用保证金 | +| margin_free | number | 可用保证金 | +| margin_level | number | 保证金比例 | +| currency | string | 账户币种 | +| server | string | 服务器名 | +| name | string | 账户名称 | +| company | string | 经纪商 | +| trade_allowed | bool | 是否允许交易 | +| trade_expert | bool | 是否允许 EA 交易 | + +--- + +### 品种 + +#### `GET /symbols/{symbol}` + +获取品种详细信息。 + +**示例:** `GET /symbols/XAUUSDc` + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ------------------- | ------ | ------------ | +| name | string | 品种名 | +| description | string | 描述 | +| digits | int | 小数位数 | +| point | double | 点值 | +| spread | int | 点差 | +| spread_float | bool | 是否浮动点差 | +| bid | double | 卖价 | +| ask | double | 买价 | +| volume_min | double | 最小手数 | +| volume_max | double | 最大手数 | +| volume_step | double | 手数步长 | +| trade_contract_size | double | 合约大小 | +| currency_base | string | 基础货币 | +| currency_profit | string | 盈亏货币 | +| category | string | 品种路径 | + +#### `GET /symbols/{symbol}/tick` + +获取品种最新报价。 + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ----------- | ------ | ------------------- | +| time | string | 报价时间 (ISO 8601) | +| bid | double | 卖价 | +| ask | double | 买价 | +| last | double | 最新成交价 | +| volume | double | 成交量 | +| volume_real | double | 真实成交量 | + +--- + +### 行情数据 + +#### `GET /rates/from-pos` + +从指定位置获取历史 K 线。 + +**参数:** + +| 参数 | 类型 | 说明 | +| --------- | ------ | ----------------------- | +| symbol | string | 品种名 | +| timeframe | string | 周期,如 `TIMEFRAME_M5` | +| start_pos | int | 起始位置(0 为最新) | +| count | int | 获取数量 | + +**支持的周期:** + +| 值 | 含义 | +| --------------- | ------- | +| `TIMEFRAME_M1` | 1 分钟 | +| `TIMEFRAME_M5` | 5 分钟 | +| `TIMEFRAME_M15` | 15 分钟 | +| `TIMEFRAME_M30` | 30 分钟 | +| `TIMEFRAME_H1` | 1 小时 | +| `TIMEFRAME_H4` | 4 小时 | +| `TIMEFRAME_D1` | 日线 | + +**响应:** 每根 K 线包含 `time`, `open`, `high`, `low`, `close`, `tick_volume`, `spread`, `real_volume`。 + +> 单次请求最大 50000 根,内部自动分批(每批 1000 根)。 + +--- + +### 持仓 + +#### `GET /positions` + +获取当前所有持仓。 + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ------------- | ------ | ------------- | +| ticket | number | 持仓号 | +| symbol | string | 品种 | +| type | int | 0=Buy, 1=Sell | +| volume | double | 手数 | +| price_open | double | 开仓价 | +| sl | double | 止损 | +| tp | double | 止盈 | +| price_current | double | 当前价 | +| swap | double | 库存费 | +| profit | double | 浮动盈亏 | +| comment | string | 注释 | +| magic | number | Magic Number | + +--- + +### 挂单 + +#### `GET /orders?symbol={symbol}` + +获取挂单列表。可选参数 `symbol` 过滤品种。 + +**响应字段:** + +| 字段 | 类型 | 说明 | +| -------------- | ------ | ------------ | +| ticket | number | 订单号 | +| symbol | string | 品种 | +| type | int | 订单类型 | +| volume_initial | double | 原始手数 | +| price_open | double | 挂单价 | +| sl | double | 止损 | +| tp | double | 止盈 | +| magic | number | Magic Number | +| comment | string | 注释 | + +--- + +### 交易 + +#### `POST /order/check` + +校验订单参数(不实际下单),检查保证金是否足够。 + +**请求体:** + +```json +{ + "action": 1, + "symbol": "XAUUSDc", + "volume": 0.01, + "order_type": 0, + "price": 4170.50, + "sl": 4168.00, + "tp": 4175.00, + "magic": 12345, + "comment": "test" +} +``` + +**action 取值:** + +| 值 | 含义 | +| ---- | -------- | +| 1 | 市价单 | +| 6 | 限价挂单 | + +**order_type 取值:** + +| 值 | 含义 | +| ---- | ---------- | +| 0 | Buy | +| 1 | Sell | +| 2 | Buy Limit | +| 3 | Sell Limit | +| 4 | Buy Stop | +| 5 | Sell Stop | + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ----------- | ------ | ------------------ | +| retcode | uint | 返回码,0 表示成功 | +| balance | double | 模拟下单后余额 | +| equity | double | 净值 | +| margin | double | 所需保证金 | +| margin_free | double | 可用保证金 | +| comment | string | 错误描述 | + +#### `POST /order/send` + +实际下单/改单/平仓。 + +**请求体(嵌套结构):** + +```json +{ + "request": { + "action": 6, + "symbol": "XAUUSDc", + "volume": 0.01, + "order_type": 2, + "price": 4165.00, + "sl": 4160.00, + "tp": 4175.00, + "magic": 12345, + "comment": "my_bot", + "order": 0, + "position": 0, + "deviation": 10 + } +} +``` + +**字段说明:** + +| 字段 | 类型 | 说明 | +| ---------- | ------ | -------------------------- | +| action | uint | 参考上表 | +| symbol | string | 品种 | +| volume | double | 手数 | +| order_type | uint | 订单类型 | +| price | double | 价格(市价单可不填) | +| sl | double | 止损价 | +| tp | double | 止盈价 | +| magic | ulong | 自定义标识 | +| comment | string | 注释 | +| order | ulong | 要修改的订单号(改单时用) | +| position | ulong | 要平仓的持仓号(平仓时用) | +| deviation | ulong | 最大滑点 | + +**修改订单:** 设置 `order` 为目标订单号,只需传要修改的字段。 + +**平仓:** 设置 `position` 为持仓号,`action=1`,`order_type` 与持仓方向相反。 + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ------- | ------ | ------------------------ | +| retcode | uint | 返回码,`10009` 表示成功 | +| order | ulong | 成交/挂单号 | +| comment | string | 服务器返回信息 | + +--- + +### 历史记录 + +#### `GET /history/deals` + +查询历史成交记录。 + +**参数:** + +| 参数 | 类型 | 说明 | +| --------- | ------ | --------------------- | +| date_from | string | 起始日期 `yyyy-MM-dd` | +| date_to | string | 结束日期 `yyyy-MM-dd` | +| symbol | string | 可选,过滤品种 | + +**响应字段:** + +| 字段 | 类型 | 说明 | +| ---------- | ------ | ------------ | +| ticket | number | 成交号 | +| time | string | 成交时间 | +| entry | int | 0=In, 1=Out | +| magic | number | Magic Number | +| volume | double | 手数 | +| price | double | 成交价 | +| profit | double | 盈亏 | +| commission | double | 佣金 | +| swap | double | 库存费 | +| symbol | string | 品种 | +| comment | string | 注释 | + +--- + +## 项目结构 + +``` +Mt5Bridge/ +├── Program.cs # 全部代码(单文件 ASP.NET Core) +├── Mt5Bridge.csproj # 项目文件 +├── libs/ # MtApi5 依赖 DLL +│ ├── MtApi5.dll +│ ├── MtClient.dll +│ └── Newtonsoft.Json.dll +└── README.md +``` + +## 部署到其他机器 + +1. 拷贝整个 `Mt5Bridge/` 文件夹 +2. 确保目标机器安装了 .NET 8 SDK +3. 确保 MT5 客户端已登录 + MtApi5 EA 挂载在图表上 +4. `dotnet run` 即可启动 + +## 修改端口 + +编辑 `Program.cs` 第 5 行: + +```csharp +builder.WebHost.UseUrls("http://localhost:8080"); +``` + +将 `8080` 改为其他端口即可。 + +## 连接超时 + +当前 CommandTimeout 设为 120 秒(通过反射设置),适用于请求大量历史 K 线的场景。如需调整,修改 `Program.cs` 第 14 行即可。 + +## 常见问题 + +**Q: 启动后一直显示 "Connecting..."?** + +A: 确保 MT5 已打开并登录,且 MtApi5 EA 已挂载在任意图表上。EA 默认监听 8228 端口。 + +**Q: 请求返回 500 错误?** + +A: 查看 Bridge 控制台输出的错误日志,常见原因:品种名不存在、MT5 断连、数据量过大超时。 + +**Q: 能用在其他语言的项目中吗?** + +A: 可以。Bridge 是标准 HTTP REST API,任何语言的 HTTP 客户端都能调用。详见上方 API 文档。 + diff --git a/bin/Debug/net8.0/Mt5Bridge.deps.json b/bin/Debug/net8.0/Mt5Bridge.deps.json new file mode 100644 index 0000000..b1b55d0 --- /dev/null +++ b/bin/Debug/net8.0/Mt5Bridge.deps.json @@ -0,0 +1,67 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v8.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v8.0": { + "Mt5Bridge/1.0.0": { + "dependencies": { + "MtApi5": "2.0.0.0", + "MtClient": "1.0.0.0", + "Newtonsoft.Json": "13.0.0.0" + }, + "runtime": { + "Mt5Bridge.dll": {} + } + }, + "MtApi5/2.0.0.0": { + "runtime": { + "MtApi5.dll": { + "assemblyVersion": "2.0.0.0", + "fileVersion": "2.0.0.0" + } + } + }, + "MtClient/1.0.0.0": { + "runtime": { + "MtClient.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "Newtonsoft.Json/13.0.0.0": { + "runtime": { + "Newtonsoft.Json.dll": { + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.3.27908" + } + } + } + } + }, + "libraries": { + "Mt5Bridge/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "MtApi5/2.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "MtClient/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Newtonsoft.Json/13.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/bin/Debug/net8.0/Mt5Bridge.dll b/bin/Debug/net8.0/Mt5Bridge.dll new file mode 100644 index 0000000..1f3ac7d Binary files /dev/null and b/bin/Debug/net8.0/Mt5Bridge.dll differ diff --git a/bin/Debug/net8.0/Mt5Bridge.exe b/bin/Debug/net8.0/Mt5Bridge.exe new file mode 100644 index 0000000..07fe1d2 Binary files /dev/null and b/bin/Debug/net8.0/Mt5Bridge.exe differ diff --git a/bin/Debug/net8.0/Mt5Bridge.pdb b/bin/Debug/net8.0/Mt5Bridge.pdb new file mode 100644 index 0000000..9baf395 Binary files /dev/null and b/bin/Debug/net8.0/Mt5Bridge.pdb differ diff --git a/bin/Debug/net8.0/Mt5Bridge.runtimeconfig.json b/bin/Debug/net8.0/Mt5Bridge.runtimeconfig.json new file mode 100644 index 0000000..5e604c7 --- /dev/null +++ b/bin/Debug/net8.0/Mt5Bridge.runtimeconfig.json @@ -0,0 +1,19 @@ +{ + "runtimeOptions": { + "tfm": "net8.0", + "frameworks": [ + { + "name": "Microsoft.NETCore.App", + "version": "8.0.0" + }, + { + "name": "Microsoft.AspNetCore.App", + "version": "8.0.0" + } + ], + "configProperties": { + "System.GC.Server": true, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false + } + } +} \ No newline at end of file diff --git a/bin/Debug/net8.0/MtApi5.dll b/bin/Debug/net8.0/MtApi5.dll new file mode 100644 index 0000000..44f465d Binary files /dev/null and b/bin/Debug/net8.0/MtApi5.dll differ diff --git a/bin/Debug/net8.0/MtClient.dll b/bin/Debug/net8.0/MtClient.dll new file mode 100644 index 0000000..94d0277 Binary files /dev/null and b/bin/Debug/net8.0/MtClient.dll differ diff --git a/bin/Debug/net8.0/Newtonsoft.Json.dll b/bin/Debug/net8.0/Newtonsoft.Json.dll new file mode 100644 index 0000000..d035c38 Binary files /dev/null and b/bin/Debug/net8.0/Newtonsoft.Json.dll differ diff --git a/libs/MtApi5.dll b/libs/MtApi5.dll new file mode 100644 index 0000000..44f465d Binary files /dev/null and b/libs/MtApi5.dll differ diff --git a/libs/MtClient.dll b/libs/MtClient.dll new file mode 100644 index 0000000..94d0277 Binary files /dev/null and b/libs/MtClient.dll differ diff --git a/libs/Newtonsoft.Json.dll b/libs/Newtonsoft.Json.dll new file mode 100644 index 0000000..d035c38 Binary files /dev/null and b/libs/Newtonsoft.Json.dll differ diff --git a/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs b/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs new file mode 100644 index 0000000..2217181 --- /dev/null +++ b/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] diff --git a/obj/Debug/net8.0/Mt5Bridge.AssemblyInfo.cs b/obj/Debug/net8.0/Mt5Bridge.AssemblyInfo.cs new file mode 100644 index 0000000..c28ad46 --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.AssemblyInfo.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("Mt5Bridge")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+4fcaca631b5248ef99a4298f2c4b6aad64db78f3")] +[assembly: System.Reflection.AssemblyProductAttribute("Mt5Bridge")] +[assembly: System.Reflection.AssemblyTitleAttribute("Mt5Bridge")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// 由 MSBuild WriteCodeFragment 类生成。 + diff --git a/obj/Debug/net8.0/Mt5Bridge.AssemblyInfoInputs.cache b/obj/Debug/net8.0/Mt5Bridge.AssemblyInfoInputs.cache new file mode 100644 index 0000000..47d6fc9 --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +33186613575b28ec79f4f05d1201256e888df42aa2ca8bfeae92d758f37c4c84 diff --git a/obj/Debug/net8.0/Mt5Bridge.GeneratedMSBuildEditorConfig.editorconfig b/obj/Debug/net8.0/Mt5Bridge.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..83e5c6e --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,19 @@ +is_global = true +build_property.TargetFramework = net8.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = true +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = Mt5Bridge +build_property.RootNamespace = Mt5Bridge +build_property.ProjectDir = C:\Users\Administrator\Desktop\ares\Mt5Bridge\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.RazorLangVersion = 8.0 +build_property.SupportLocalizedComponentNames = +build_property.GenerateRazorMetadataSourceChecksumAttributes = +build_property.MSBuildProjectDirectory = C:\Users\Administrator\Desktop\ares\Mt5Bridge +build_property._RazorSourceGeneratorDebug = diff --git a/obj/Debug/net8.0/Mt5Bridge.GlobalUsings.g.cs b/obj/Debug/net8.0/Mt5Bridge.GlobalUsings.g.cs new file mode 100644 index 0000000..025530a --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.GlobalUsings.g.cs @@ -0,0 +1,17 @@ +// +global using global::Microsoft.AspNetCore.Builder; +global using global::Microsoft.AspNetCore.Hosting; +global using global::Microsoft.AspNetCore.Http; +global using global::Microsoft.AspNetCore.Routing; +global using global::Microsoft.Extensions.Configuration; +global using global::Microsoft.Extensions.DependencyInjection; +global using global::Microsoft.Extensions.Hosting; +global using global::Microsoft.Extensions.Logging; +global using global::System; +global using global::System.Collections.Generic; +global using global::System.IO; +global using global::System.Linq; +global using global::System.Net.Http; +global using global::System.Net.Http.Json; +global using global::System.Threading; +global using global::System.Threading.Tasks; diff --git a/obj/Debug/net8.0/Mt5Bridge.MvcApplicationPartsAssemblyInfo.cache b/obj/Debug/net8.0/Mt5Bridge.MvcApplicationPartsAssemblyInfo.cache new file mode 100644 index 0000000..e69de29 diff --git a/obj/Debug/net8.0/Mt5Bridge.assets.cache b/obj/Debug/net8.0/Mt5Bridge.assets.cache new file mode 100644 index 0000000..c55d72d Binary files /dev/null and b/obj/Debug/net8.0/Mt5Bridge.assets.cache differ diff --git a/obj/Debug/net8.0/Mt5Bridge.csproj.AssemblyReference.cache b/obj/Debug/net8.0/Mt5Bridge.csproj.AssemblyReference.cache new file mode 100644 index 0000000..adc239f Binary files /dev/null and b/obj/Debug/net8.0/Mt5Bridge.csproj.AssemblyReference.cache differ diff --git a/obj/Debug/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache b/obj/Debug/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..626a4dd --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +24217677bf38b3110e8f08546d3dc4465f97487641f8f2dc6cd22a663bb79f21 diff --git a/obj/Debug/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt b/obj/Debug/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..0906da1 --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt @@ -0,0 +1,28 @@ +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.csproj.AssemblyReference.cache +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.AssemblyInfoInputs.cache +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.AssemblyInfo.cs +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.csproj.CoreCompileInputs.cache +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.MvcApplicationPartsAssemblyInfo.cache +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\Mt5Bridge.exe +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\Mt5Bridge.deps.json +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\Mt5Bridge.runtimeconfig.json +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\Mt5Bridge.dll +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\Mt5Bridge.pdb +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\MtApi5.dll +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\MtClient.dll +C:\Users\Administrator\Desktop\ares\Mt5Bridge\bin\Debug\net8.0\Newtonsoft.Json.dll +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets.build.json +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets.development.json +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets\msbuild.Mt5Bridge.Microsoft.AspNetCore.StaticWebAssets.props +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets\msbuild.build.Mt5Bridge.props +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets\msbuild.buildMultiTargeting.Mt5Bridge.props +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets\msbuild.buildTransitive.Mt5Bridge.props +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\staticwebassets.pack.json +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\scopedcss\bundle\Mt5Bridge.styles.css +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.csproj.Up2Date +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.dll +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\refint\Mt5Bridge.dll +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.pdb +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\Mt5Bridge.genruntimeconfig.cache +C:\Users\Administrator\Desktop\ares\Mt5Bridge\obj\Debug\net8.0\ref\Mt5Bridge.dll diff --git a/obj/Debug/net8.0/Mt5Bridge.csproj.Up2Date b/obj/Debug/net8.0/Mt5Bridge.csproj.Up2Date new file mode 100644 index 0000000..e69de29 diff --git a/obj/Debug/net8.0/Mt5Bridge.dll b/obj/Debug/net8.0/Mt5Bridge.dll new file mode 100644 index 0000000..1f3ac7d Binary files /dev/null and b/obj/Debug/net8.0/Mt5Bridge.dll differ diff --git a/obj/Debug/net8.0/Mt5Bridge.genruntimeconfig.cache b/obj/Debug/net8.0/Mt5Bridge.genruntimeconfig.cache new file mode 100644 index 0000000..b0d1370 --- /dev/null +++ b/obj/Debug/net8.0/Mt5Bridge.genruntimeconfig.cache @@ -0,0 +1 @@ +d1ebbd23b71aef41cd0fc60ac0cb097334a2e9c856ee1cb44e91c163c704c5fc diff --git a/obj/Debug/net8.0/Mt5Bridge.pdb b/obj/Debug/net8.0/Mt5Bridge.pdb new file mode 100644 index 0000000..9baf395 Binary files /dev/null and b/obj/Debug/net8.0/Mt5Bridge.pdb differ diff --git a/obj/Debug/net8.0/apphost.exe b/obj/Debug/net8.0/apphost.exe new file mode 100644 index 0000000..07fe1d2 Binary files /dev/null and b/obj/Debug/net8.0/apphost.exe differ diff --git a/obj/Debug/net8.0/ref/Mt5Bridge.dll b/obj/Debug/net8.0/ref/Mt5Bridge.dll new file mode 100644 index 0000000..3a0e9ac Binary files /dev/null and b/obj/Debug/net8.0/ref/Mt5Bridge.dll differ diff --git a/obj/Debug/net8.0/refint/Mt5Bridge.dll b/obj/Debug/net8.0/refint/Mt5Bridge.dll new file mode 100644 index 0000000..3a0e9ac Binary files /dev/null and b/obj/Debug/net8.0/refint/Mt5Bridge.dll differ diff --git a/obj/Debug/net8.0/staticwebassets.build.json b/obj/Debug/net8.0/staticwebassets.build.json new file mode 100644 index 0000000..bd8744b --- /dev/null +++ b/obj/Debug/net8.0/staticwebassets.build.json @@ -0,0 +1,11 @@ +{ + "Version": 1, + "Hash": "/8Q34kmS+8VCFusGgof9wH/8eKQGq3WaaUYNad/1wwY=", + "Source": "Mt5Bridge", + "BasePath": "_content/Mt5Bridge", + "Mode": "Default", + "ManifestType": "Build", + "ReferencedProjectsConfiguration": [], + "DiscoveryPatterns": [], + "Assets": [] +} \ No newline at end of file diff --git a/obj/Debug/net8.0/staticwebassets/msbuild.build.Mt5Bridge.props b/obj/Debug/net8.0/staticwebassets/msbuild.build.Mt5Bridge.props new file mode 100644 index 0000000..5a6032a --- /dev/null +++ b/obj/Debug/net8.0/staticwebassets/msbuild.build.Mt5Bridge.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/obj/Debug/net8.0/staticwebassets/msbuild.buildMultiTargeting.Mt5Bridge.props b/obj/Debug/net8.0/staticwebassets/msbuild.buildMultiTargeting.Mt5Bridge.props new file mode 100644 index 0000000..cc89daa --- /dev/null +++ b/obj/Debug/net8.0/staticwebassets/msbuild.buildMultiTargeting.Mt5Bridge.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/obj/Debug/net8.0/staticwebassets/msbuild.buildTransitive.Mt5Bridge.props b/obj/Debug/net8.0/staticwebassets/msbuild.buildTransitive.Mt5Bridge.props new file mode 100644 index 0000000..d167811 --- /dev/null +++ b/obj/Debug/net8.0/staticwebassets/msbuild.buildTransitive.Mt5Bridge.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/obj/Mt5Bridge.csproj.nuget.dgspec.json b/obj/Mt5Bridge.csproj.nuget.dgspec.json new file mode 100644 index 0000000..bfd94a3 --- /dev/null +++ b/obj/Mt5Bridge.csproj.nuget.dgspec.json @@ -0,0 +1,69 @@ +{ + "format": 1, + "restore": { + "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj": {} + }, + "projects": { + "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj", + "projectName": "Mt5Bridge", + "projectPath": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj", + "packagesPath": "C:\\Users\\Administrator\\.nuget\\packages\\", + "outputPath": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\obj\\", + "projectStyle": "PackageReference", + "configFilePaths": [ + "C:\\Users\\Administrator\\AppData\\Roaming\\NuGet\\NuGet.Config" + ], + "originalTargetFrameworks": [ + "net8.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + } + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.422/PortableRuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/obj/Mt5Bridge.csproj.nuget.g.props b/obj/Mt5Bridge.csproj.nuget.g.props new file mode 100644 index 0000000..ed12545 --- /dev/null +++ b/obj/Mt5Bridge.csproj.nuget.g.props @@ -0,0 +1,15 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\Administrator\.nuget\packages\ + PackageReference + 6.11.2 + + + + + \ No newline at end of file diff --git a/obj/Mt5Bridge.csproj.nuget.g.targets b/obj/Mt5Bridge.csproj.nuget.g.targets new file mode 100644 index 0000000..3dc06ef --- /dev/null +++ b/obj/Mt5Bridge.csproj.nuget.g.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/obj/project.assets.json b/obj/project.assets.json new file mode 100644 index 0000000..51edec3 --- /dev/null +++ b/obj/project.assets.json @@ -0,0 +1,74 @@ +{ + "version": 3, + "targets": { + "net8.0": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + "net8.0": [] + }, + "packageFolders": { + "C:\\Users\\Administrator\\.nuget\\packages\\": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj", + "projectName": "Mt5Bridge", + "projectPath": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj", + "packagesPath": "C:\\Users\\Administrator\\.nuget\\packages\\", + "outputPath": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\obj\\", + "projectStyle": "PackageReference", + "configFilePaths": [ + "C:\\Users\\Administrator\\AppData\\Roaming\\NuGet\\NuGet.Config" + ], + "originalTargetFrameworks": [ + "net8.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + } + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.422/PortableRuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/obj/project.nuget.cache b/obj/project.nuget.cache new file mode 100644 index 0000000..efe1280 --- /dev/null +++ b/obj/project.nuget.cache @@ -0,0 +1,8 @@ +{ + "version": 2, + "dgSpecHash": "8pDiazJllfw=", + "success": true, + "projectFilePath": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj", + "expectedPackageFiles": [], + "logs": [] +} \ No newline at end of file