从山证v2.3.0拷贝

This commit is contained in:
吴方海
2024-05-09 14:06:26 +08:00
parent 566ff33259
commit f9d8a256a6
4471 changed files with 1203456 additions and 9 deletions
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YLErp.Configuration;
using YLErp.Modules.EodModule.SettlementModule;
namespace YLErp.Modules.EodModule
{
[TestClass]
public class EodClientBalanceCalcBSTest
{
[TestMethod("客户买卖权结算")]
public void CalcTest()
{
var service = new EodClientBalanceCalcBS(OptUserInfo.UnitTestUser);
List<Client> clients = new List<Client>() { new Client() { id=131,Number= "SDX0010",Name= "山西分形供应链数据管理有限公司" } };
service.ClientBalanceByDay(DateTime.Parse("2021-11-15"), clients);
}
}
}
@@ -0,0 +1,28 @@
using YLErp.Configuration;
using YLErp.Modules.EodModule.SettlementModule;
namespace YLErp.Modules.EodModule
{
[TestClass]
public class EodClientBalanceCalcTest
{
[TestMethod("客户结算比较")]
public void CompareTest()
{
var request = new EodSettlementRequest(OptUserInfo.UnitTestUser)
{
UseClosePrice = true,
VolType = "持仓",
SettleDate = new DateTime(2022, 6, 1)
};
var settlementConfig = new SettlementConfig
{
};
var cancleSource = new CancellationTokenSource();
var context = new EodSettlementContextV2(request, settlementConfig, cancleSource.Token);
var service = new EodClientBalanceCalc(context);
service.ClientBalanceCalc();
}
}
}
@@ -0,0 +1,64 @@
namespace YLErp.Modules.EodModule
{
[TestClass]
public class EodCurrencyRateServiceTest
{
[TestMethod]
public void TestGetEodCurrencyRate()
{
using (var db = DbContextFactory.GetYLDbContext())
{
db.Database.ExecuteSqlRaw("delete from eod_currency_rate where ValueDate<='1971-01-01'");
var rate1 = new eod_currency_rate
{
ValueDate = new DateTime(1970, 12, 31),
BuyRate = 6.45,
ForeignCurrency = "USD",
LocalCurrency = "CNH",
OptDate = DateTime.Now,
OptId = 0,
OptName = "系统",
Rate = 6.45,
SellRate = 6.45
};
var rates = new eod_currency_rate[5];
rates[0] = rate1;
for (var i = 1; i < 5; i++)
{
var rate2 = rates[i - 1].Clone();
rate2.ValueDate = rate2.ValueDate.AddDays(-i * 2);
rate2.BuyRate = rate2.SellRate = rate2.Rate -= 0.1;
rates[i] = rate2;
}
db.eod_currency_rate.AddRange(rates);
db.SaveChanges();
}
var service = new EodCurrencyRateService(OptUserInfo.SystemUser);
var rate = service.GetEodCurrencyRate("USD", "CNH", new DateTime(1970, 12, 31));
Assert.IsTrue(rate != null && rate.Rate == 6.45);
service.GetEodCurrencyRate("USD", "CNH", new DateTime(1970, 12, 31), true);
Assert.IsTrue(rate != null && rate.Rate == 6.45);
rate = service.GetEodCurrencyRate("CNH", "USD", new DateTime(1970, 12, 31));
Assert.IsTrue(rate != null && rate.Rate == 1 / 6.45);
rate = service.GetEodCurrencyRate("CNH", "USD", new DateTime(1970, 12, 31), true);
Assert.IsTrue(rate != null && rate.Rate == 1 / 6.45);
rate = service.GetEodCurrencyRate("USD", "CNY", new DateTime(1970, 12, 31));
Assert.IsTrue(rate == null);
rate = service.GetEodCurrencyRate("USD", "CNY", new DateTime(1970, 12, 31), true);
Assert.IsTrue(rate == null);
rate = service.GetEodCurrencyRate("USD", "CNH", new DateTime(1970, 12, 1), true);
Assert.IsTrue(rate == null);
}
}
}
@@ -0,0 +1,184 @@
using YLErp.Configuration;
using YLErp.Modules.EodModule.SettlementModule;
using YLErp.Modules.TradeModule.DealModule;
namespace YLErp.Modules.EodModule
{
[TestClass]
public class EodSettlementTaskTest : UnitTestBase
{
[TestMethod]
public void TestEodTask()
{
var eodDate = new DateTime(2020, 9, 2);
var task = new EodTask
{
StartDate = eodDate,
EndDate = eodDate,
VolTypes = "持仓",//"持仓,开仓,对冲";
PriceType = EodSettlePriceType.ClosePrice
};
EodTaskRunner.ExecuteDebugAsync(task).Wait();
Assert.IsTrue(task.TaskState == EodTaskState.completed, task.TaskResult);
}
[TestMethod]
public void TestReadTrade()
{
var date = new DateTime(2020, 07, 01);
var eodArr = new YLContext().eod_trade.Where(O => O.ValueDate == date).ToArray();
var tradeArr = eodArr.Select(O => O.trade).ToArray();
}
/// <summary>
/// GetFixingString 测试
/// </summary>
[TestMethod]
public void GetFixingString()
{
var underlyingCode = "A00";
var settlementType = 1;
var futurePriceList = new YLContext().eod_commodity_future_price
.Where(e => e.UnderlyingCode == underlyingCode)
//.Where(e => e.ValueDate >= startDate)
//.Where(e => e.ValueDate >= exerciseDate)
.Select(e => new
{
e.ValueDate,
e.ClosePrice,
e.SettlePrice,
e.ReferencePrice
}).ToList();
var query = from e in futurePriceList
orderby e.ValueDate
select e.ValueDate + "," + GetPrice(settlementType, e.ClosePrice, e.SettlePrice, e.ReferencePrice);
var fixing = string.Join(";", query.ToArray());
}
/// <summary>
/// GetFixingString 测试
/// </summary>
[TestMethod]
public void ClientBalanceCalc()
{
var request = new EodSettlementRequest(GetOptUser())
{
VolType = null,
UseClosePrice = true,
ClientIds = null,
SettleDate = DateTime.Today
};
CancellationTokenSource cancellationTokenSource;
EodSettlementContextV2 _context;
cancellationTokenSource = new CancellationTokenSource();
var settlementConfig = new SettlementConfig
{
Version = "V1",
CalcPnlExplain = false,
PriceType = 3,
SupportPart = false,
VolTypes = "持仓,开仓,对冲,光证,BidAskVol"
};
_context = new EodSettlementContextV2(request, settlementConfig, cancellationTokenSource.Token);
new EodClientBalanceCalc(_context).ClientBalanceCalc();
}
private double GetPrice(int settlementType, double closePrice, double settlePrice, double? referencePrice)
{
var price = closePrice;
if (settlementType == (int)SettlementTypeEnum.SettlePrice)
{
price = settlePrice;
}
else if (settlementType == (int)SettlementTypeEnum.ReferencePrice)
{
price = referencePrice ?? closePrice;
}
return price;
}
public enum SettlementTypeEnum
{
ClosePrice = 0,
SettlePrice = 1,
ReferencePrice = 2,
}
[TestMethod]
public void TestDividend()
{
var service = new DividendService(OptUserInfo.UnitTestUser);
var info = new ex_dividend_info()
{
UnderlyingCode = "002043.SZ",
ExDividendDate = new DateTime(2020, 7, 6),
GiveCashAmount = 2.5,
GiveShareAmount = 0,
RationedSharesAmount = 0,
RationedSharesPrice = 0,
};
var price = service.GetPrice(8.8, info);
Assert.IsTrue((price - 8.6126) < 1e-4);
info = new ex_dividend_info()
{
UnderlyingCode = "600406.SH",
ExDividendDate = new DateTime(2020, 7, 8),
GiveCashAmount = 2.9,
GiveShareAmount = 0,
RationedSharesAmount = 0,
RationedSharesPrice = 0,
};
price = service.GetPrice(20.1893, info);
Assert.IsTrue((price - 19.9785) < 1e-4);
info = new ex_dividend_info()
{
UnderlyingCode = "600406.SH",
ExDividendDate = new DateTime(2020, 7, 8),
GiveCashAmount = 2.9,
GiveShareAmount = 0,
RationedSharesAmount = 0,
RationedSharesPrice = 0,
};
price = service.GetPrice(19.9454, info);
Assert.IsTrue((price - 19.7371) < 1e-4);
info = new ex_dividend_info()
{
UnderlyingCode = "601021.SH",
ExDividendDate = new DateTime(2020, 7, 8),
GiveCashAmount = 2.0006,
GiveShareAmount = 0,
RationedSharesAmount = 0,
RationedSharesPrice = 0,
};
price = service.GetPrice(37.13, info);
Assert.IsTrue((price - 36.9776) < 1e-4);
info = new ex_dividend_info()
{
UnderlyingCode = "300001.SZ",
ExDividendDate = new DateTime(2020, 7, 13),
GiveCashAmount = 0.2,
GiveShareAmount = 0,
RationedSharesAmount = 0,
RationedSharesPrice = 0,
};
price = service.GetPrice(20.381, info);
Assert.IsTrue((price - 20.3681) < 1e-4);
}
}
}
@@ -0,0 +1,115 @@
using Qdp.Pricing.Base.Implementations;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.EodModule.SettlementModule;
using YLErp.QdpModule;
namespace YLErp.Modules.EodModule
{
[TestClass]
public class EodSettlementTest : UnitTestBase
{
[TestMethod("收盘估值计算")]
public void TestCalcPv()
{
var settleDate = new DateTime(2021, 4, 27);
var predicate = PredicateBuilder.Create<trade>(t => t.TradeNumber == "CW20210016E0002");
var otcTrades = new EodSettleDataQueryService(GetOptUser())
.GetOtcTrades(settleDate, predicate, out var tradeCashProvider);
var td = otcTrades.FirstOrDefault();
if (td == null)
{
Console.WriteLine("没有找到交易");
return;
}
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider(settleDate);
var spotPrice = eodpriceProvider.GetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice);
var req = new OptionValueCalcRequest(td.NoRiskRate ?? 0)
{
correlations = null,//不计算彩虹等多标的期权暂时不需要
engineName = null,
preciseTimeMode = false, //日终一定是false
pricingRequest = QdpPricingRequest.BASIC_GREEKS,
spotPrices = new[] { spotPrice }
};
if (td.TradeType != ConsGlobal.TradeType.CashFlow)
{
var volProvider = EodVolProviderFactory.GetEodVolProvider(settleDate, "持仓");
var vol = volProvider.GetVol(td, spotPrice) ?? ConsGlobal.DefaultVol;
req.vols = new[] { vol };
}
var option = OptionCalculatorV2.GetOptionValueResult(settleDate, td, req, out var underlyings);
Console.WriteLine($"[{td.TradeType},{td.TradeNumber},{td.id}] pv:{option.Pv}, delta:{option.Delta}");
}
[TestMethod("测试盈亏分解--当天新开仓的交易")]
public void TestCalcPnlExplainV2_NewOtcTradeDeal()
{
var db = DbContextFactory.GetYLDbContext();
var td = db.trade.FirstOrDefault(n => n.TradeNumber == "CW20210016C0001");
YLErp.BLL.tradeBLL.SetFieldsByTradeType(td);
var pnl = new EodPnl();
double spot0 = 5910, spot1 = 5911, pv1 = 53796.37;
var pS0V1Q1T1 = CalcPnlExplainV2(td, new CalcField
{
spot = spot0,
vol = 0.28,
dividendRate = 0,
riskFreeRate = 0.03,
date = new DateTime(2021, 4, 27)
}, PricingRequest.Pv | PricingRequest.Delta, x =>
{
});
if (pS0V1Q1T1 != null)
{
pnl.PnLVega += NumberHelper.Normalize(pS0V1Q1T1.Pv - ((td.TradeSinglePrice ?? 0) * td.Notional));
pnl.PnLDelta += NumberHelper.Normalize(pS0V1Q1T1.Delta * (spot1 - spot0));
pnl.PnLGamma += NumberHelper.Normalize(pv1 - pS0V1Q1T1.Pv - pnl.PnLDelta);
Console.WriteLine($"pS0V1Q1T1 pv:{pS0V1Q1T1.Pv}, delta:{pS0V1Q1T1.Delta}");
}
Console.WriteLine("计算失败");
}
//计算pv和delta
private static TradeValueResult CalcPnlExplainV2(trade td, CalcField f, PricingRequest pricingRequest
, Action<OptionTradeParamBase> paramOverride = null)
{
td.NoRiskRate = f.riskFreeRate;
td.DividendRate = f.dividendRate;
var req = new OptionValueCalcRequest(f.riskFreeRate)
{
correlations = null,//不计算彩虹等多标的期权暂时不需要
engineName = null,
preciseTimeMode = false, //日终一定是false
pricingRequest = pricingRequest,
spotPrices = new[] { f.spot },
vols = new[] { f.vol },
ParamOverride = paramOverride
};
return OptionCalculatorV2.GetOptionValueResult(f.date, td, req, out _);
}
class CalcField
{
//public double pv;
public DateTime date;
public double vol;
public double dividendRate;
public double spot;
public double riskFreeRate;
}
}
}
@@ -0,0 +1,79 @@
using YLErp.Configuration;
using YLErp.Modules.EodModule.SettlementModule;
using YLErp.Modules.TradeDalModule;
namespace YLErp.Modules.EodModule
{
[TestClass]
public class ExDividendTest
{
[TestMethod("测试除权除息基础循环处理是否符合预期")]
public void Test1()
{
var startIndex = 0;
var priceDic = new Dictionary<DateTime, double> {
{new DateTime(2021,1,1),1d },
{new DateTime(2021,1,2),1d },
{new DateTime(2021,1,3),1d },
{new DateTime(2021,1,4),1d },
{new DateTime(2021,1,5),1d },
{new DateTime(2021,1,6),1d },
{new DateTime(2021,1,7),1d },
{new DateTime(2021,1,8),1d },
{new DateTime(2021,1,9),1d },
{new DateTime(2021,1,10),1d },
};
var exDividendInfos = new List<ex_dividend_info> {
new ex_dividend_info{ ExDividendDate = new DateTime(2021,1,2)},
new ex_dividend_info{ ExDividendDate = new DateTime(2021,1,6)},
new ex_dividend_info{ ExDividendDate = new DateTime(2021,1,8)},
};
//日终价格和除权除息信息都按照正序排列
//获取除权价格则使用大于日终价格日期的除权信息除权
//循环日终价格,如果一个除权日期小于价格日期则被排除掉
foreach (var kv in priceDic)
{
(var date, var price) = (kv.Key, kv.Value);
Console.WriteLine("===========" + date.ToString("yyyy-MM-dd") + "===========");
for (var i = startIndex; i < exDividendInfos.Count; i++)
{
var dividenInfo = exDividendInfos[i];
//除权日当天的收盘价也需要处理
if (date <= dividenInfo.ExDividendDate)
{
Console.WriteLine(dividenInfo.ExDividendDate.Value.ToString("yyyy-MM-dd"));
}
else
{
startIndex = i;
}
}
}
}
[TestMethod]
public void TestEodDividend()
{
var userInfo = OptUserInfo.UnitTestUser;
using var db = DbContextFactory.GetYLDbContext();
var eodDate = new DateTime(2021, 06, 04);
var trades = db.eod_trade.Where(et => et.ValueDate == eodDate && !ConsTrade.TradeCompleteStatus.Contains(et.TradeStatus))
.ToArray().Select(O => O.trade).ToList();
var tradeIds = trades.Select(O => O.id);
var parentTradeIds = trades.Where(O => O.ParentTradeId > 0 && !tradeIds.Contains(O.ParentTradeId)).Select(O => O.ParentTradeId).ToHashSet();
if (parentTradeIds.Any())
{
var parentTrades = new TradeDalService(userInfo).GetTradeOrEodTrade(parentTradeIds, eodDate);
trades.AddRange(parentTrades);
}
var request = new EodSettlementRequest(userInfo) { SettleDate = eodDate };
var context = new EodSettlementContextV2(request, new SettlementConfig { }, CancellationToken.None);
new EodDividenService(context).Execute(trades);
}
}
}
@@ -0,0 +1,52 @@
using Newtonsoft.Json;
using YLErp.BLL.EodSettlement;
namespace YLErp.Modules.EodModule.QueryModule
{
[TestClass]
public class TestEodTradePositionApiService
{
[TestMethod]
public void TestInfoAll()
{
var req = new EodSettleInfoRequest
{
ValueDate = new DateTime(2022, 1, 4)
};
var context = new EodSettleInfoQueryContext(OptUserInfo.SystemUser);
var positionResult = new EodTradePositionApiService(context).GetEodPositions(req);
var closeResult = new EodCloseInfoQueryService(context).GetEodCloseInfoList(req.ValueDate);
var clientIds = context.GetClientIds();
var balanceResult = ClientBalanceUtility.GetClientBanlances(
clientIdList: clientIds,
startDate: DateTime.MinValue,
endDate: req.ValueDate,
IsGetOuterMarginGap: false,
IsClientBalanceGap: false,
ParentFlag: false,
clientDataSource: context);
var result = new
{
positionResult.OptionPositions,
positionResult.SwapPositions,
positionResult.ForwardPositions,
CloseInfos = closeResult,
AccountInfos = balanceResult
};
//var result = new { d = 1.2222222255555555555 };
var serializeSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
serializeSettings.Converters ??= new List<JsonConverter>();
serializeSettings.Converters.Add(new DoubleJsonWriteConverter(2, 8));
var json = JsonConvert.SerializeObject(result, serializeSettings);
Assert.IsNotNull(json);
}
}
}