From e191b6606d81862e1754618122020cf0eec20bab Mon Sep 17 00:00:00 2001
From: shanj <18996038927@163.com>
Date: Sun, 15 May 2022 01:08:17 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E4=BA=A4=E6=98=93=E6=89=80?=
=?UTF-8?q?=E4=BA=A4=E6=98=93=E5=AF=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.editorconfig | 6 ++
.../Binance.TradeRobot.API.xml | 19 +++-
.../Controllers/ExchangeAccountController.cs | 31 +++++++
.../Controllers/SingalController.cs | 4 +-
.../Business/ExchangeBusiness.cs | 56 ++++++++++-
.../Business/RobotBusiness.cs | 92 ++++++++++---------
.../Business/SingalBusiness.cs | 2 +-
.../Http/RestAPIService.cs | 65 +++++++++----
.../Base/MappingProfiles.cs | 6 +-
.../Binance.TradeRobot.Model.xml | 10 ++
.../Db/Exchange/SymbolInfo.cs | 32 +++++++
Binance.TradeRobot.Model/Db/Robot/Robot.cs | 11 +++
.../Db/代码生成/__重新生成.bat | 2 +-
.../Response/Exchange/SymbolInfoResponse.cs | 8 ++
.../Dto/Response/Robot/RobotResponse.cs | 2 +
15 files changed, 275 insertions(+), 71 deletions(-)
create mode 100644 Binance.TradeRobot.Model/Db/Exchange/SymbolInfo.cs
create mode 100644 Binance.TradeRobot.Model/Dto/Response/Exchange/SymbolInfoResponse.cs
diff --git a/.editorconfig b/.editorconfig
index 9405a89..43784d5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -14,3 +14,9 @@ dotnet_diagnostic.CS8602.severity = none
# CS8603: 可能返回 null 引用。
dotnet_diagnostic.CS8603.severity = none
+
+# CS8600: 将 null 字面量或可能为 null 的值转换为非 null 类型。
+dotnet_diagnostic.CS8600.severity = none
+
+# CS8601: 引用类型赋值可能为 null。
+dotnet_diagnostic.CS8601.severity = none
diff --git a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml
index 4ea2d4d..6283bb2 100644
--- a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml
+++ b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml
@@ -4,6 +4,23 @@
Binance.TradeRobot.API
+
+
+ 同步币安交易对
+
+
+
+
+ 同步Gate.IO交易对
+
+
+
+
+ 获取交易对列表
+
+
+
+
添加交易所账号
@@ -61,7 +78,7 @@
-
+
D21杠杆/合约信号接口
diff --git a/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs b/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs
index 416783f..8caef1a 100644
--- a/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs
+++ b/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs
@@ -18,6 +18,37 @@ namespace Binance.TradeRobot.API.Controllers
this.exchangeBusiness = exchangeBusiness;
}
+ ///
+ /// 同步币安交易对
+ ///
+ [HttpPost]
+ [AllowAnonymous]
+ public void SyncBinanceSymbol()
+ {
+ exchangeBusiness.SyncBinanceSymbol();
+ }
+
+ ///
+ /// 同步Gate.IO交易对
+ ///
+ [HttpPost]
+ [AllowAnonymous]
+ public void SyncGateIOSymbol()
+ {
+ exchangeBusiness.SyncGateIOSymbol();
+ }
+
+ ///
+ /// 获取交易对列表
+ ///
+ ///
+ ///
+ [HttpGet("{exchange}")]
+ public IList GetSymbolList(Enums.Exchange exchange)
+ {
+ return exchangeBusiness.GetSymbolList(exchange);
+ }
+
///
/// 添加交易所账号
///
diff --git a/Binance.TradeRobot.API/Controllers/SingalController.cs b/Binance.TradeRobot.API/Controllers/SingalController.cs
index b0fd552..36b46a5 100644
--- a/Binance.TradeRobot.API/Controllers/SingalController.cs
+++ b/Binance.TradeRobot.API/Controllers/SingalController.cs
@@ -18,9 +18,9 @@ namespace Binance.TradeRobot.API.Controllers
///
///
[HttpPost]
- public void D21Singnal([FromBody] D21SingalRequest d21SingalRequest)
+ public void D21Singal([FromBody] D21SingalRequest d21SingalRequest)
{
- singalBusiness.D21Singnal(d21SingalRequest);
+ singalBusiness.D21Singal(d21SingalRequest);
}
}
}
diff --git a/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs b/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs
index b476e30..7360e7c 100644
--- a/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs
+++ b/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs
@@ -1,14 +1,17 @@
using Binance.TradeRobot.Business.Extensions;
using Binance.TradeRobot.Common.DI;
using Binance.TradeRobot.Common.Extensions;
+using Binance.TradeRobot.Common.Http;
using Binance.TradeRobot.Model.Base;
using Binance.TradeRobot.Model.Db;
using Binance.TradeRobot.Model.Dto;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Yitter.IdGenerator;
@@ -18,7 +21,58 @@ namespace Binance.TradeRobot.Business.Exchange
[BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Self)]
public class ExchangeBusiness : BaseBusiness
{
- public ExchangeBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IMemoryCache memoryCache) : base(fsql, logManager, idGenerator, memoryCache) { }
+ private RestApiService restApiService;
+
+ public ExchangeBusiness(IFreeSql fsql,
+ NLogManager logManager,
+ IIdGenerator idGenerator,
+ IMemoryCache memoryCache,
+ RestApiService restApiService) : base(fsql, logManager, idGenerator, memoryCache)
+ {
+ this.restApiService = restApiService;
+ }
+
+ public void SyncBinanceSymbol()
+ {
+ var apiResult = restApiService.SendRequest("https://api.binance.com/", "api/v3/exchangeInfo", null, null, HttpMethod.Get);
+ if (apiResult.StatusCode != System.Net.HttpStatusCode.OK)
+ throw new BusinessException($"同步币安交易对失败 StatusCode {apiResult.StatusCode} {apiResult.Content}");
+ var jobject = JObject.Parse(apiResult.Content);
+ var jarray_symbols = (JArray)jobject["symbols"];
+ var symbolList = new List();
+ foreach (JToken jtoken_symbol in jarray_symbols)
+ {
+ var symbol = jtoken_symbol.Value("symbol").ToUpper();
+ if (!symbol.EndsWith("USDT"))
+ continue;
+ var stepSize = jtoken_symbol["filters"]?.FirstOrDefault(jtoken_filters => jtoken_filters.Value("filterType") == "LOT_SIZE")?.Value("stepSize") ?? 0M;
+ var saleAccuracy = stepSize != 0 ? (1 / stepSize).ToString().Length - 1 : 0;
+ var symbolInfo = new SymbolInfo()
+ {
+ Id = idGenerator.NewLong(),
+ ExchangeId = Enums.Exchange.Binance,
+ CreateTime = DateTime.Now,
+ Symbol = symbol,
+ SaleQuantityAccuracy = saleAccuracy
+ };
+ symbolList.Add(symbolInfo);
+ }
+ fsql.Transaction(() =>
+ {
+ fsql.Delete().Where(s => s.ExchangeId == Enums.Exchange.Binance).ExecuteAffrows();
+ fsql.Insert(symbolList).ExecuteAffrows();
+ });
+ }
+
+ public void SyncGateIOSymbol()
+ {
+
+ }
+
+ public IList GetSymbolList(Enums.Exchange exchange)
+ {
+ return fsql.Select().Where(s => s.ExchangeId == exchange).ToList();
+ }
public void AddExchangeAccount(AddExchangeAccountRequest addExchangeAccountRequest)
{
diff --git a/Binance.TradeRobot.Business/Business/RobotBusiness.cs b/Binance.TradeRobot.Business/Business/RobotBusiness.cs
index 067809a..20ac87d 100644
--- a/Binance.TradeRobot.Business/Business/RobotBusiness.cs
+++ b/Binance.TradeRobot.Business/Business/RobotBusiness.cs
@@ -56,7 +56,7 @@ namespace Binance.TradeRobot.Business
//监听K线和订单
globalContext.SubscribeKLine(robot);
- }
+ }
public void StopRobot(long robotId)
{
@@ -199,52 +199,56 @@ namespace Binance.TradeRobot.Business
bool isLoadRecentTradeProfit = true,
bool isLoadAPIKey = false)
{
- var robotList = fsql.Select().InnerJoin((r, ra, d, e) => r.Id == ra.RobotId)
- .InnerJoin((r, ra, d, e) => r.Id == d.RobotId)
- .InnerJoin((r, ra, d, e) => r.Id == e.RobotId)
- .WhereIf(robotState != null, (r, ra, d, e) => r.State == robotState)
- .WhereIf(signalPeriod != null, (r, ra, d, e) => d.PeriodicSignal == signalPeriod)
- .WhereIf(!string.IsNullOrEmpty(symbol), (r, ra, d, e) => r.Symbol == symbol)
- .Where((r, ra, d, e) => r.TradePolicy == Enums.TradePolicy.D21)
- .ToList((r, ra, d, e) => new Robot()
- {
- Id = r.Id,
- BusinessType = r.BusinessType,
- ExchangeId = r.ExchangeId,
- Symbol = r.Symbol,
- State = r.State,
- RunningTime = r.RunningTime,
- CreateTime = r.CreateTime,
- TradePolicy = r.TradePolicy,
+ var robotList = fsql.Select().InnerJoin((r, s, ra, d, e) => r.Id == ra.RobotId)
+ .InnerJoin((r, s, ra, d, e) => r.Symbol == s.Symbol && r.ExchangeId == s.ExchangeId)
+ .InnerJoin((r, s, ra, d, e) => r.Id == d.RobotId)
+ .InnerJoin((r, s, ra, d, e) => r.Id == e.RobotId)
+ .WhereIf(robotState != null, (r, s, ra, d, e) => r.State == robotState)
+ .WhereIf(signalPeriod != null, (r, s, ra, d, e) => d.PeriodicSignal == signalPeriod)
+ .WhereIf(!string.IsNullOrEmpty(symbol), (r, s, ra, d, e) => r.Symbol == symbol)
+ .Where((r, s, ra, d, e) => r.TradePolicy == Enums.TradePolicy.D21)
+ .ToList((r, s, ra, d, e) => new Robot()
+ {
+ Id = r.Id,
+ BusinessType = r.BusinessType,
+ ExchangeId = r.ExchangeId,
+ Symbol = r.Symbol,
+ State = r.State,
+ RunningTime = r.RunningTime,
+ CreateTime = r.CreateTime,
+ TradePolicy = r.TradePolicy,
+
+ SymbolId = s.Id,
+ SymbolSaleQuantityAccuracy = s.SaleQuantityAccuracy,
- RobotAccountId = ra.Id,
- ClosePositionCount = ra.ClosePositionCount,
- WinCount = ra.WinCount,
- LoanAmount = ra.LoanAmount,
- SoptCurrentcyAmount = ra.SoptCurrentcyAmount,
- SpotCurrencyQuantity = ra.SpotCurrencyQuantity,
- TotalProfit = ra.TotalProfit,
+ RobotAccountId = ra.Id,
+ ClosePositionCount = ra.ClosePositionCount,
+ WinCount = ra.WinCount,
+ LoanAmount = ra.LoanAmount,
+ SoptCurrentcyAmount = ra.SoptCurrentcyAmount,
+ SpotCurrencyQuantity = ra.SpotCurrencyQuantity,
+ TotalProfit = ra.TotalProfit,
- ExchangeAccountId = e.AccountId,
- ExchangeAPIKey = e.APIKey,
- ExchangeSecretKey = e.SecretKey,
+ ExchangeAccountId = e.AccountId,
+ ExchangeAPIKey = e.APIKey,
+ ExchangeSecretKey = e.SecretKey,
- D21ExecutionMode = d.ExecutionMode,
- D21IsEnabledIncreasePurchase = d.IsEnabledIncreasePurchase,
- D21IsEnableRemedyForErrorCrossSignal = d.IsEnableRemedyForErrorCrossSignal,
- D21MaxFollowPurchaseRatio = d.MaxFollowPurchaseRatio,
- D21PeriodicSignal = d.PeriodicSignal,
- D21PolicyId = d.Id,
- D21Position = d.Position,
- D21Assets = d.Assets,
- D21Level1PositionStopLossRatio = d.Level1PositionStopLossRatio,
- D21Level1PriceStopLossRatio = d.Level1PriceStopLossRatio,
- D21Level2PositionStopLossRatio = d.Level2PositionStopLossRatio,
- D21Level2PriceStopLossRatio = d.Level2PriceStopLossRatio,
- D21MaxExchangeLoanRatio = d.MaxExchangeLoanRatio,
- D21MaxSystemLoanRatio = d.MaxSystemLoanRatio,
- D21CreateTime = d.CreateTime
- }).Map>();
+ D21ExecutionMode = d.ExecutionMode,
+ D21IsEnabledIncreasePurchase = d.IsEnabledIncreasePurchase,
+ D21IsEnableRemedyForErrorCrossSignal = d.IsEnableRemedyForErrorCrossSignal,
+ D21MaxFollowPurchaseRatio = d.MaxFollowPurchaseRatio,
+ D21PeriodicSignal = d.PeriodicSignal,
+ D21PolicyId = d.Id,
+ D21Position = d.Position,
+ D21Assets = d.Assets,
+ D21Level1PositionStopLossRatio = d.Level1PositionStopLossRatio,
+ D21Level1PriceStopLossRatio = d.Level1PriceStopLossRatio,
+ D21Level2PositionStopLossRatio = d.Level2PositionStopLossRatio,
+ D21Level2PriceStopLossRatio = d.Level2PriceStopLossRatio,
+ D21MaxExchangeLoanRatio = d.MaxExchangeLoanRatio,
+ D21MaxSystemLoanRatio = d.MaxSystemLoanRatio,
+ D21CreateTime = d.CreateTime
+ }).Map>();
if (isLoadRecentTradeProfit)
{
//统计近期订单利润
diff --git a/Binance.TradeRobot.Business/Business/SingalBusiness.cs b/Binance.TradeRobot.Business/Business/SingalBusiness.cs
index a0f0631..8c24e5e 100644
--- a/Binance.TradeRobot.Business/Business/SingalBusiness.cs
+++ b/Binance.TradeRobot.Business/Business/SingalBusiness.cs
@@ -27,7 +27,7 @@ namespace Binance.TradeRobot.Business.Business
this.tradeBusinessList = tradeBusinessList;
}
- public void D21Singnal(D21SingalRequest d21SingalRequest)
+ public void D21Singal(D21SingalRequest d21SingalRequest)
{
//logManager.GetLogger("D21").Info(JsonConvert.SerializeObject(d21SingalRequest));
var robotList = robotBusiness.GetD21PolicyRobotList(Enums.RobotState.Runing, d21SingalRequest.KLinePeriodic, d21SingalRequest.Symbol, false, true);
diff --git a/Binance.TradeRobot.Common/Http/RestAPIService.cs b/Binance.TradeRobot.Common/Http/RestAPIService.cs
index 9184d8a..8ee735e 100644
--- a/Binance.TradeRobot.Common/Http/RestAPIService.cs
+++ b/Binance.TradeRobot.Common/Http/RestAPIService.cs
@@ -2,7 +2,9 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
+using System.Net;
using System.Net.Http;
+using System.Net.Http.Headers;
using System.Text;
namespace Binance.TradeRobot.Common.Http
@@ -26,27 +28,34 @@ namespace Binance.TradeRobot.Common.Http
///
///
///
- ///
+ ///
///
///
///
- ///
+ ///
+ ///
+ ///
+ ///
///
- public string SendRequest(string apiHost,
- string apiPath,
- object param,
- IDictionary headers,
- HttpMethod httpMethod,
- string contentType = ContentType_Json,
- ParamPosition paramPosition = ParamPosition.Body,
- bool enableRandomTimeStamp = false)
+ public RestApiResult SendRequest(string apiHost,
+ string apiPath,
+ object param,
+ IDictionary requestHeaders,
+ HttpMethod httpMethod,
+ string contentType = ContentType_Json,
+ ParamPosition paramPosition = ParamPosition.Body,
+ bool useRandomTimeStamp = false,
+ bool getResponseHeader = false,
+ HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead,
+ string httpClientName = "")
{
//Get和Delete强制使用QueryString形式传参
if (httpMethod == HttpMethod.Get || httpMethod == HttpMethod.Delete)
paramPosition = ParamPosition.Query;
//拼接Url
- var url = $"{apiHost}{(apiHost.EndsWith("/") ? string.Empty : "/")}{(apiPath.StartsWith("/") ? apiPath.Substring(1) : apiPath)}";
+ var url = string.IsNullOrEmpty(apiPath) ? apiHost :
+ $"{apiHost.TrimEnd('/')}/{apiPath.TrimStart('/')}";
var isCombineParam = false;
if (paramPosition == ParamPosition.Query && param != null)
{
@@ -55,8 +64,8 @@ namespace Binance.TradeRobot.Common.Http
}
//使用时间戳绕过CDN
- if (enableRandomTimeStamp)
- url = $"{url}{(isCombineParam ? "&" : "?")}t={DateTime.Now.DateTimeToStamp()}";
+ if (useRandomTimeStamp)
+ url = $"{url}{(isCombineParam ? "&" : "?")}t={DateTime.Now.ToFileTime()}";
using (var httpClient = httpClientFactory.CreateClient())
@@ -64,22 +73,38 @@ namespace Binance.TradeRobot.Common.Http
httpClient.Timeout = TimeOut;
using (var request = new HttpRequestMessage(httpMethod, url))
{
- if (headers != null && headers.Count > 0)
- foreach (var key in headers.Keys)
- request.Headers.Add(key, headers[key]);
+ if (requestHeaders != null && requestHeaders.Count > 0)
+ foreach (var key in requestHeaders.Keys)
+ request.Headers.Add(key, requestHeaders[key]);
if (paramPosition == ParamPosition.Body && param != null)
request.Content = new StringContent(contentType == ContentType_Json ? JsonConvert.SerializeObject(param) : param.ToString(), Encoding.UTF8, contentType);
- using (var response = httpClient.SendAsync(request).Result)
+ using (var response = httpClient.SendAsync(request, httpCompletionOption).Result)
{
- if (!response.IsSuccessStatusCode)
- throw new Exception($"HttpCode {response.StatusCode}");
- return response.Content.ReadAsStringAsync().Result;
+ if (!response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.Redirect && response.StatusCode != HttpStatusCode.Moved)
+ throw new Exception($"Reuqest {url} HttpCode {response.StatusCode}");
+ return new RestApiResult()
+ {
+ StatusCode = response.StatusCode,
+ Content = httpCompletionOption == HttpCompletionOption.ResponseContentRead ? response.Content.ReadAsStringAsync().Result :
+ string.Empty,
+ Headers = getResponseHeader ? response.Headers : null
+ };
}
}
}
}
+
+ }
+
+ public class RestApiResult
+ {
+ public HttpStatusCode StatusCode { get; set; }
+
+ public string Content { get; set; }
+
+ public HttpResponseHeaders Headers { get; set; }
}
///
diff --git a/Binance.TradeRobot.Model/Base/MappingProfiles.cs b/Binance.TradeRobot.Model/Base/MappingProfiles.cs
index 97e3c2c..1167d20 100644
--- a/Binance.TradeRobot.Model/Base/MappingProfiles.cs
+++ b/Binance.TradeRobot.Model/Base/MappingProfiles.cs
@@ -26,7 +26,11 @@ namespace Binance.TradeRobot.Model.Base
.ForPath(t => t.RobotAccount.WinCount, opt => opt.MapFrom(f => f.WinCount))
.ForPath(t => t.ExchangeAPIKey.AccountId, opt => opt.MapFrom(f => f.ExchangeAccountId))
.ForPath(t => t.ExchangeAPIKey.APIKey, opt => opt.MapFrom(f => f.ExchangeAPIKey))
- .ForPath(t => t.ExchangeAPIKey.SecretKey, opt => opt.MapFrom(f => f.ExchangeSecretKey));
+ .ForPath(t => t.ExchangeAPIKey.SecretKey, opt => opt.MapFrom(f => f.ExchangeSecretKey))
+ .ForPath(t => t.SymbolInfo.Id, opt => opt.MapFrom(f => f.SymbolId))
+ .ForPath(t => t.SymbolInfo.Symbol, opt => opt.MapFrom(f => f.Symbol))
+ .ForPath(t => t.SymbolInfo.SaleQuantityAccuracy, opt => opt.MapFrom(f => f.SymbolSaleQuantityAccuracy))
+ .ForPath(t => t.SymbolInfo.ExchangeId, opt => opt.MapFrom(f => f.ExchangeId));
CreateMap().IncludeBase()
.ForPath(t => t.D21Policy.Id, opt => opt.MapFrom(f => f.D21PolicyId))
.ForPath(t => t.D21Policy.RobotId, opt => opt.MapFrom(f => f.Id))
diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml
index 4807a02..6904c88 100644
--- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml
+++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml
@@ -169,6 +169,11 @@
关联机器人Id
+
+
+ 基础币卖出数量精度
+
+
来源信号
@@ -339,6 +344,11 @@
运行时长(s)
+
+
+ 卖币精度
+
+
平仓次数
diff --git a/Binance.TradeRobot.Model/Db/Exchange/SymbolInfo.cs b/Binance.TradeRobot.Model/Db/Exchange/SymbolInfo.cs
new file mode 100644
index 0000000..22e25df
--- /dev/null
+++ b/Binance.TradeRobot.Model/Db/Exchange/SymbolInfo.cs
@@ -0,0 +1,32 @@
+using Binance.TradeRobot.Model.Base;
+using FreeSql.DataAnnotations;
+using System;
+
+namespace Binance.TradeRobot.Model.Db
+{
+
+ [Table(Name = "symbolinfo", DisableSyncStructure = true)]
+ public partial class SymbolInfo
+ {
+
+ [Column(DbType = "bigint", IsPrimary = true)]
+ public long Id { get; set; }
+
+ [Column(DbType = "datetime")]
+ public DateTime? CreateTime { get; set; }
+
+ [Column(DbType = "int", MapType = typeof(int))]
+ public Enums.Exchange ExchangeId { get; set; }
+
+ ///
+ /// 基础币卖出数量精度
+ ///
+ [Column(DbType = "int")]
+ public int SaleQuantityAccuracy { get; set; }
+
+ [Column(StringLength = 50)]
+ public string Symbol { get; set; }
+
+ }
+
+}
diff --git a/Binance.TradeRobot.Model/Db/Robot/Robot.cs b/Binance.TradeRobot.Model/Db/Robot/Robot.cs
index 53c8fbf..76cf1d8 100644
--- a/Binance.TradeRobot.Model/Db/Robot/Robot.cs
+++ b/Binance.TradeRobot.Model/Db/Robot/Robot.cs
@@ -36,6 +36,17 @@ namespace Binance.TradeRobot.Model.Db
[Column(MapType = typeof(int), DbType = "int")]
public Enums.Exchange ExchangeId { get; set; }
+ #region Symbol Extension
+ ///
+ /// 卖币精度
+ ///
+ [Column(IsIgnore = true)]
+ public long SymbolId { get; set; }
+
+ [Column(IsIgnore = true)]
+ public int SymbolSaleQuantityAccuracy { get; set; }
+ #endregion
+
#region RobotAccount Extension
[Column(IsIgnore = true)]
diff --git a/Binance.TradeRobot.Model/Db/代码生成/__重新生成.bat b/Binance.TradeRobot.Model/Db/代码生成/__重新生成.bat
index 90a629a..8bb4fc9 100644
--- a/Binance.TradeRobot.Model/Db/代码生成/__重新生成.bat
+++ b/Binance.TradeRobot.Model/Db/代码生成/__重新生成.bat
@@ -1 +1 @@
-FreeSql.Generator -Razor 1 -NameOptions 1,0,0,0 -NameSpace Binance.TradeRobot.Model.Db -DB "MySql,data source=47.245.58.112;port=3306;user id=sa;password=rYn6re2AKhcDWcBi;initial catalog=tradedb;charset=utf8;sslmode=none;max pool size=2" -FileName "{name}.cs"
+FreeSql.Generator -Razor 1 -NameOptions 1,0,0,0 -NameSpace Binance.TradeRobot.Model.Db -DB "MySql,data source=8.209.252.195;port=3306;user id=sa;password=rYn6re2AKhcDWcBi;initial catalog=tradedb;charset=utf8;sslmode=none;max pool size=2" -FileName "{name}.cs"
diff --git a/Binance.TradeRobot.Model/Dto/Response/Exchange/SymbolInfoResponse.cs b/Binance.TradeRobot.Model/Dto/Response/Exchange/SymbolInfoResponse.cs
new file mode 100644
index 0000000..3f4ac53
--- /dev/null
+++ b/Binance.TradeRobot.Model/Dto/Response/Exchange/SymbolInfoResponse.cs
@@ -0,0 +1,8 @@
+using Binance.TradeRobot.Model.Db;
+
+namespace Binance.TradeRobot.Model.Dto
+{
+ public class SymbolInfoResponse : SymbolInfo
+ {
+ }
+}
diff --git a/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs b/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs
index c80a86c..8611609 100644
--- a/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs
+++ b/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs
@@ -26,6 +26,8 @@ namespace Binance.TradeRobot.Model.Dto
public virtual string KLineKey { get { return $"KLine-{ExchangeId}-{Symbol}"; } }
+ public SymbolInfoResponse SymbolInfo { get; set; }
+
///
/// 机器人账户对象
///