first commit
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="MtApi5">
|
||||
<HintPath>libs\MtApi5.dll</HintPath>
|
||||
<Private>true</Private>
|
||||
</Reference>
|
||||
<Reference Include="MtClient">
|
||||
<HintPath>libs\MtClient.dll</HintPath>
|
||||
<Private>true</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>libs\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>true</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+386
@@ -0,0 +1,386 @@
|
||||
using MtApi5;
|
||||
using System.Reflection;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.WebHost.UseUrls("http://localhost:8080");
|
||||
builder.Services.AddSingleton<MtApi5Client>(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<MtConnectionService>();
|
||||
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<MqlRates>();
|
||||
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<object>();
|
||||
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<object>();
|
||||
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<object>();
|
||||
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<MtConnectionService> _logger;
|
||||
|
||||
public MtConnectionService(MtApi5Client client, ILogger<MtConnectionService> logger)
|
||||
{
|
||||
_client = client;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
_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<bool>();
|
||||
_client.BeginConnect(8228);
|
||||
await tcs.Task;
|
||||
if (_client.ConnectionState == Mt5ConnectionState.Connected)
|
||||
_logger.LogInformation("MT5 reconnected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+413
@@ -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 文档。
|
||||
|
||||
@@ -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": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
|
||||
@@ -0,0 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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 类生成。
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
33186613575b28ec79f4f05d1201256e888df42aa2ca8bfeae92d758f37c4c84
|
||||
@@ -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 =
|
||||
@@ -0,0 +1,17 @@
|
||||
// <auto-generated/>
|
||||
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;
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
24217677bf38b3110e8f08546d3dc4465f97487641f8f2dc6cd22a663bb79f21
|
||||
@@ -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
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
d1ebbd23b71aef41cd0fc60ac0cb097334a2e9c856ee1cb44e91c163c704c5fc
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"Hash": "/8Q34kmS+8VCFusGgof9wH/8eKQGq3WaaUYNad/1wwY=",
|
||||
"Source": "Mt5Bridge",
|
||||
"BasePath": "_content/Mt5Bridge",
|
||||
"Mode": "Default",
|
||||
"ManifestType": "Build",
|
||||
"ReferencedProjectsConfiguration": [],
|
||||
"DiscoveryPatterns": [],
|
||||
"Assets": []
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<Project>
|
||||
<Import Project="Microsoft.AspNetCore.StaticWebAssets.props" />
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<Project>
|
||||
<Import Project="..\build\Mt5Bridge.props" />
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<Project>
|
||||
<Import Project="..\buildMultiTargeting\Mt5Bridge.props" />
|
||||
</Project>
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Administrator\.nuget\packages\</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.11.2</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\Administrator\.nuget\packages\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "8pDiazJllfw=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Users\\Administrator\\Desktop\\ares\\Mt5Bridge\\Mt5Bridge.csproj",
|
||||
"expectedPackageFiles": [],
|
||||
"logs": []
|
||||
}
|
||||
Reference in New Issue
Block a user