从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
using BaseOUDAL;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YLErp.Helpers;
|
||||
using YLErp.Modules.SwapModule;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class AuthHelperTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestGenerateToken()
|
||||
{
|
||||
var identity = UserManager.CreateIdentity("1", "superA", Guid.NewGuid().ToString(""));
|
||||
var jwtToken2 = AuthHelper.CreateJwtToken2(identity);
|
||||
var jwtTokenHandler = new JwtSecurityTokenHandler();
|
||||
var token = jwtTokenHandler.ReadJwtToken(jwtToken2);
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using AutoMapper;
|
||||
|
||||
namespace YLErp.Basic
|
||||
{
|
||||
[TestClass]
|
||||
public class AutoMapperTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestDictionToObject()
|
||||
{
|
||||
var dic = new Dictionary<string, object> {
|
||||
{"AA","11" },
|
||||
{"BB","22" }
|
||||
};
|
||||
|
||||
var poco = new Mapper(new MapperConfiguration(cfg => { })).Map<TestPoco>(dic);
|
||||
|
||||
Assert.IsTrue(poco.AA == "11" && poco.BB == "22");
|
||||
|
||||
dic = new Dictionary<string, object> {
|
||||
{"AA","33" },
|
||||
{"BB","44" }
|
||||
};
|
||||
|
||||
new Mapper(new MapperConfiguration(cfg => { })).Map(dic, poco);
|
||||
|
||||
Assert.IsTrue(poco.AA == "33" && poco.BB == "44");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using YLErp.Modules.SwapModule;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class DataBaseTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestConnection()
|
||||
{
|
||||
var yldb = DbContextFactory.GetYLDbContext();
|
||||
var appconfigs = yldb.AppConfig.Take(10).ToArray();
|
||||
|
||||
var admindb = DbContextFactory.GetErpBaseContext();
|
||||
var sysusers = admindb.SystemUsers.Take(10).ToArray();
|
||||
|
||||
var clientdb = DbContextFactory.GetClientDbContext(OptUserInfo.SystemUser);
|
||||
var clients = clientdb.client.Take(10).ToArray();
|
||||
|
||||
Assert.IsTrue(appconfigs.Length > 0 && sysusers.Length > 0 && clients.Length > 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestDictionaries()
|
||||
{
|
||||
var admindb = DbContextFactory.GetErpBaseContext();
|
||||
var dictionaries = admindb.Dictionaries.ToArray();
|
||||
var sb = new StringBuilder();
|
||||
foreach(var d in dictionaries)
|
||||
{
|
||||
sb.AppendFormat(@"<dictionary name=""{0}"" catalog=""{1}"">",d.Name,d.Catalog)
|
||||
.Append("</dictionary>").AppendLine();
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine(sb.ToString());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestGenerateSwapTradeFromDb()
|
||||
{
|
||||
new SwapTradeAutoService(OptUserInfo.SystemUser).GenerateSwapTradeFromDb(DateTime.Now.Date, false);
|
||||
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using BaseOUDAL;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class EfQueryTest : UnitTestBase
|
||||
{
|
||||
[TestMethod("测试Linq ToDictionary是否支持函数处理")]
|
||||
public void Test1()
|
||||
{
|
||||
var db = DbContextFactory.GetYLDbContext();
|
||||
|
||||
var priceDic = db.eod_commodity_future_price.Where(e =>
|
||||
e.UnderlyingCode == "RB00" &&
|
||||
e.ValueDate >= new DateTime(2021, 1, 1) &&
|
||||
e.ValueDate <= new DateTime(2021, 12, 1)).OrderBy(e => e.ValueDate)
|
||||
.ToDictionary(e => e.ValueDate, e => e.GetPrice(SettlementTypeEnum.ReferencePrice));
|
||||
|
||||
Assert.IsNotNull(priceDic);
|
||||
}
|
||||
|
||||
[TestMethod("测试Char类型")]
|
||||
public void TestChar()
|
||||
{
|
||||
var db = new YLContext2();
|
||||
|
||||
var data = db.Set<ExchangeListOption2>().FirstOrDefault(e => e.ContractCode == "RB00-C-5000");
|
||||
|
||||
Assert.IsTrue(!string.IsNullOrEmpty(data.UpdateFlag) && data.UpdateFlag[0] == '0');
|
||||
|
||||
data = db.Set<ExchangeListOption2>().FirstOrDefault(e => e.ContractCode == "RB00-P-5000");
|
||||
|
||||
Assert.IsTrue(string.IsNullOrEmpty(data.UpdateFlag) || data.UpdateFlag[0] != '0');
|
||||
}
|
||||
|
||||
class YLContext2: DBContextBase
|
||||
{
|
||||
protected override string GetConnectionString() => AppManager.GetConnectionString("ylcms");
|
||||
|
||||
public DbSet<ExchangeListOption2> ExchangeListOption2 { get; set; }
|
||||
}
|
||||
|
||||
class ExchangeListOption2 : ExchangeListOption
|
||||
{
|
||||
public string UpdateFlag { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.Drawing;
|
||||
using static YLErp.Commons.ExcelHelper;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class ExcelHelperTests
|
||||
{
|
||||
class ExportTestModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public int Age { get; set; }
|
||||
|
||||
public string phone { get; set; }
|
||||
|
||||
public string Address { get; set; }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ListToExcelTest()
|
||||
{
|
||||
var list = new List<ExportTestModel>
|
||||
{
|
||||
new ExportTestModel() { Name = "大林", Age = 26, phone = "13824412561", Address = "云南省曲靖市少林东街32号甲" },
|
||||
new ExportTestModel() { Name = "东近", Age = 20, phone = "13725526482", Address = "云南省曲靖市少林东街32号丁" },
|
||||
new ExportTestModel() { Name = "春妮", Age = 25, phone = "13062405400" }
|
||||
};
|
||||
var columnList = new List<DataColumnModel>
|
||||
{
|
||||
new DataColumnModel("姓名", "Name") { Style = new ExcelStyle() { BorderColor = Color.Red, BackgroundColor = Color.Green, ForegroundColor = Color.Red } },
|
||||
new DataColumnModel("年龄", "Age", (cv, obj) =>
|
||||
{
|
||||
if (!(cv is int value))
|
||||
{
|
||||
return "未知";
|
||||
}
|
||||
if (value < 12)
|
||||
{
|
||||
return "儿童";
|
||||
}
|
||||
return "成人";
|
||||
})
|
||||
{ Style = new ExcelStyle() { BorderColor = Color.OrangeRed, BackgroundColor = Color.Green, ForegroundColor = Color.Yellow } },
|
||||
new DataColumnModel("联系电话", "phone", (cv, obj) =>
|
||||
{
|
||||
if (cv is string value)
|
||||
{
|
||||
cv = value.Remove(3, 4).Insert(3, "****");
|
||||
}
|
||||
return cv;
|
||||
})
|
||||
{ Style = new ExcelStyle() { BorderColor = Color.Orange, BackgroundColor = Color.Orange, ForegroundColor = Color.Red } },
|
||||
new DataColumnModel("详细地址", (obj) =>
|
||||
{
|
||||
if (!(obj is ExportTestModel value))
|
||||
{
|
||||
return "未知";
|
||||
}
|
||||
return string.IsNullOrWhiteSpace(value.Address) ? "地址不详" : "";
|
||||
})
|
||||
{ Style = new ExcelStyle() { BorderColor = Color.Red, BackgroundColor = Color.DarkOrange, ForegroundColor = Color.Orange } }
|
||||
};
|
||||
var helper = new Commons.ExcelHelper();
|
||||
|
||||
helper.ListToExcel<ExportTestModel>(
|
||||
columnList.ToArray(),
|
||||
list,
|
||||
"Sheet1",
|
||||
true,
|
||||
out var buffer,
|
||||
false,
|
||||
new DataGroupModel[] {
|
||||
new DataGroupModel {
|
||||
Caption = "组1",
|
||||
StartColumnIndex = 0,
|
||||
Length = 2 ,
|
||||
Style = new ExcelStyle(){
|
||||
BackgroundColor = Color.Orange,
|
||||
BorderColor = Color.Red,
|
||||
ForegroundColor = Color.Green
|
||||
}
|
||||
},
|
||||
new DataGroupModel {
|
||||
Caption = "组2",
|
||||
StartColumnIndex = 3,
|
||||
Length = 1 ,
|
||||
Style = new ExcelStyle(){
|
||||
BackgroundColor = Color.Green,
|
||||
BorderColor = Color.Red,
|
||||
ForegroundColor = Color.Orange
|
||||
}}
|
||||
});
|
||||
System.IO.File.WriteAllBytes(@"C:\Users\shiyi\Work\sss.xlsx", buffer);
|
||||
|
||||
//string fileName = @"C:\Users\shiyi\Work\sss.xls";
|
||||
//Commons.ExcelHelper helper1 = new Commons.ExcelHelper(Commons.ExcelHelper.GetVersion(fileName));
|
||||
|
||||
//helper1.ListToExcel<ExportTestModel>(columnList.ToArray(), list, "Sheet1", true, out var buffer1);
|
||||
//System.IO.File.WriteAllBytes(fileName, buffer1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using YLErp.Helpers;
|
||||
|
||||
namespace YLErp.Commons
|
||||
{
|
||||
[TestClass]
|
||||
public class FoundationTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void DataConvertToLetterTest()
|
||||
{
|
||||
var result = "";
|
||||
|
||||
result = DataHelper.ConvertToLetter(0);
|
||||
Assert.IsTrue(result == "A");
|
||||
result = DataHelper.ConvertToLetter(25);
|
||||
Assert.IsTrue(result == "Z");
|
||||
result = DataHelper.ConvertToLetter(26);
|
||||
Assert.IsTrue(result == "AA");
|
||||
result = DataHelper.ConvertToLetter(701);
|
||||
Assert.IsTrue(result == "ZZ");
|
||||
result = DataHelper.ConvertToLetter(702);
|
||||
Assert.IsTrue(result == "AAA");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestExceptionHelper()
|
||||
{
|
||||
var aex = new AggregateException(new[] {
|
||||
new Exception("hello1",new Exception("gogog")),
|
||||
new Exception("hello2",new NotSupportedException("not support")),
|
||||
new AggregateException(new []{
|
||||
new NotSupportedException("hello--1",new Exception("gogog--2")),
|
||||
new NotSupportedException("hello--1",new NotSupportedException("gogog--3",new Exception("bbb"))),
|
||||
new Exception("hello--2",new NotSupportedException("not support--2")),
|
||||
}),
|
||||
new InvalidOperationException("invalid operation"),
|
||||
});
|
||||
|
||||
var bas = ExceptionHelper.GetBaseExceptions(aex);
|
||||
Assert.AreEqual(bas[0].Message, "hello1");
|
||||
Assert.AreEqual(bas[1].Message, "hello2");
|
||||
Assert.AreEqual(bas[2].Message, "gogog--2");
|
||||
Assert.AreEqual(bas[3].Message, "hello--1");
|
||||
Assert.AreEqual(bas[4].Message, "hello--2");
|
||||
Assert.AreEqual(bas[5].Message, "invalid operation");
|
||||
|
||||
System.Diagnostics.Debug.WriteLine(aex.Messages());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestDataChangeHelper()
|
||||
{
|
||||
var sourceTrade = new trade
|
||||
{
|
||||
TradeType = "香草期权",
|
||||
TradeSinglePrice = 1.25,
|
||||
NumOfSmoothingDays = 5,
|
||||
TradeAmount = 3.24,
|
||||
TraderId = 15,
|
||||
Notional = 26.434,
|
||||
IsUsePremiumRate = true,//
|
||||
IsTradePricePayType = true,
|
||||
MarginType = DBModels.Enums.MarginTypeEnum.FLOAT,
|
||||
DividendDate = DateTime.Now,
|
||||
SettlementDate = DateTime.Now.AddDays(-1),
|
||||
get_trade_swap_details = new System.Collections.Generic.List<trade_swap_detail>
|
||||
{
|
||||
new trade_swap_detail
|
||||
{
|
||||
ExerciseDate = DateTime.Now,
|
||||
FinalPrice = 26.45
|
||||
}
|
||||
},
|
||||
MetaDic = new System.Collections.Generic.Dictionary<string, string>
|
||||
{
|
||||
["asd"] = "asdf",
|
||||
["3w4"] = "58"
|
||||
},
|
||||
trade_forward = new trade_forward
|
||||
{
|
||||
OpenCommission = 156.685,
|
||||
AnnualMarginRate = 354.438
|
||||
},
|
||||
trade_asian_option = null
|
||||
};
|
||||
var newTrade = new trade
|
||||
{
|
||||
TradeType = "香草期权",
|
||||
TradeSinglePrice = 1.25,
|
||||
NumOfSmoothingDays = 5,
|
||||
TradeAmount = 3.24,
|
||||
TraderId = 15,
|
||||
Notional = 26.434,
|
||||
IsUsePremiumRate = true,
|
||||
IsTradePricePayType = true,
|
||||
MarginType = DBModels.Enums.MarginTypeEnum.FLOAT,
|
||||
DividendDate = DateTime.Now,
|
||||
SettlementDate = DateTime.Now.AddDays(-1),
|
||||
get_trade_swap_details = new System.Collections.Generic.List<trade_swap_detail>
|
||||
{
|
||||
new trade_swap_detail
|
||||
{
|
||||
ExerciseDate = DateTime.Now,
|
||||
FinalPrice = 26.44
|
||||
}
|
||||
},
|
||||
MetaDic = new System.Collections.Generic.Dictionary<string, string>
|
||||
{
|
||||
["as1d"] = "asdf",
|
||||
["3w4"] = "58"
|
||||
},
|
||||
trade_forward = new trade_forward
|
||||
{
|
||||
OpenCommission = 156.685,
|
||||
AnnualMarginRate = 354.438
|
||||
},
|
||||
trade_asian_option = null
|
||||
};
|
||||
TradeHelper2.ReduceTradeExt(sourceTrade);
|
||||
TradeHelper2.ReduceTradeExt(newTrade);
|
||||
var list = DataChangeHelper.GetDataChanges(sourceTrade, newTrade);
|
||||
Assert.IsNotNull(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class JsonHelperTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestDateOnlyConverter()
|
||||
{
|
||||
var obj = new TestDateOnlyClass { AA = new YcDateOnly(DateTime.Now), CC = new DateTime(2022, 2, 2) };
|
||||
var json = JsonHelper.Serialize(obj, ignoreNullValue: false);
|
||||
Assert.AreEqual(json, "{\"AA\":\"" + obj.AA.ToString() + "\",\"BB\":null,\"CC\":\"2022-02-02\"}");
|
||||
|
||||
var t = JsonHelper.Deserialize<TestDateOnlyClass>(json);
|
||||
Assert.AreEqual(t.AA.Date, DateTime.Today);
|
||||
Assert.IsFalse(t.BB.HasValue);
|
||||
Assert.IsTrue(t.CC.HasValue);
|
||||
Assert.AreEqual(t.CC.Value.Date, new DateTime(2022, 2, 2));
|
||||
}
|
||||
|
||||
class TestDateOnlyClass
|
||||
{
|
||||
public YcDateOnly AA { get; set; }
|
||||
public YcDateOnly? BB { get; set; }
|
||||
public YcDateOnly? CC { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class LinqExpressionTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestAddAssign()
|
||||
{
|
||||
var data = new LinqData { N1 = 3 };
|
||||
|
||||
Expression<Func<LinqData, double>> propExp = n => n.N1;
|
||||
|
||||
var pinvoke = Expression.Invoke(propExp, propExp.Parameters);
|
||||
var addExp = Expression.Add(pinvoke, Expression.Constant(2d, typeof(double)));
|
||||
var assign = Expression.Assign(propExp.Body, addExp);
|
||||
var action = Expression.Lambda<Action<LinqData>>(assign, propExp.Parameters).Compile();
|
||||
action(data);
|
||||
|
||||
Assert.AreEqual(data.N1, 5);
|
||||
|
||||
var data2 = new LinqData { N1 = 3 };
|
||||
var assign2 = Expression.AddAssign(propExp.Body, Expression.Constant(3d, typeof(double)));
|
||||
var action2 = Expression.Lambda<Action<LinqData>>(assign2, propExp.Parameters).Compile();
|
||||
action2(data2);
|
||||
|
||||
Assert.AreEqual(data2.N1, 6);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestMultiplyAssign()
|
||||
{
|
||||
var data = new LinqData { N1 = 3 };
|
||||
|
||||
Expression<Func<LinqData, double>> propExp = n => n.N1;
|
||||
|
||||
var pinvoke = Expression.Invoke(propExp, propExp.Parameters);
|
||||
var multiply = Expression.Multiply(pinvoke, Expression.Constant(1 + 0.2, typeof(double)));
|
||||
var assign = Expression.Assign(propExp.Body, multiply);
|
||||
var action = Expression.Lambda<Action<LinqData>>(assign, propExp.Parameters).Compile();
|
||||
action(data);
|
||||
|
||||
Assert.AreEqual(data.N1, 3.6, 1e-4);
|
||||
|
||||
var data2 = new LinqData { N1 = 3 };
|
||||
var assign2 = Expression.MultiplyAssign(propExp.Body, Expression.Constant(1.5, typeof(double)));
|
||||
var action2 = Expression.Lambda<Action<LinqData>>(assign2, propExp.Parameters).Compile();
|
||||
action2(data2);
|
||||
|
||||
Assert.AreEqual(data2.N1, 4.5, 1e-4);
|
||||
}
|
||||
|
||||
class LinqData
|
||||
{
|
||||
public double N1 { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using YLErp.MailKit;
|
||||
|
||||
namespace YLErp.Commons
|
||||
{
|
||||
[TestClass]
|
||||
public class MailSendTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestMailSend()
|
||||
{
|
||||
var cfg = new SmtpConfig
|
||||
{
|
||||
Server = "smtp.mxhichina.com",
|
||||
EnableSsl = false,
|
||||
From = "jinjiang.liu@yieldchain.com",
|
||||
UserName = "jinjiang.liu@yieldchain.com",
|
||||
Password = "cheby@307",
|
||||
Port = 80
|
||||
};
|
||||
|
||||
MailSender.Send(cfg, new MailSendingOption
|
||||
{
|
||||
From = cfg.From,
|
||||
Body = "这封邮件用于测试Excel附件问题",
|
||||
MailTo = new string[] { "379002060@qq.com" },
|
||||
Subject = "这封邮件用于测试Excel附件问题",
|
||||
FilesToAttach = new[] { "D:\\_work\\repo-new\\1111\\持仓报告_20221206_20221206_成都供应链五部.xlsx" }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class NumberHelperTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestConvertToChinese()
|
||||
{
|
||||
var cn1 = NumberHelper.ConvertToChinese(154681.61, true);
|
||||
Assert.AreEqual(cn1, "人民币拾伍万肆仟陆佰捌拾壹圆陆角壹分");
|
||||
|
||||
var cn2 = NumberHelper.ConvertToChinese(154681.61, false);
|
||||
Assert.AreEqual(cn2, "十五万四千六百八十一点六一");
|
||||
|
||||
var cn3 = NumberHelper.CurrToChnInt(54681);
|
||||
Assert.AreEqual(cn3, "五万四千六百八十一");
|
||||
|
||||
var rmb = NumberHelper.CmycurD(154681.61);
|
||||
Assert.AreEqual(rmb, "壹拾伍万肆仟陆佰捌拾壹元陆角壹分");
|
||||
|
||||
rmb = NumberHelper.CmycurD(154308219.19);
|
||||
Assert.AreEqual(rmb, "壹亿伍仟肆佰叁拾万零捌仟贰佰壹拾玖元壹角玖分");
|
||||
|
||||
rmb = NumberHelper.CmycurD(1054308219.19);
|
||||
Assert.AreEqual(rmb, "壹拾亿零伍仟肆佰叁拾万零捌仟贰佰壹拾玖元壹角玖分");
|
||||
|
||||
rmb = NumberHelper.CmycurD(10554308219.19);
|
||||
Assert.AreEqual(rmb, "壹佰零伍亿伍仟肆佰叁拾万零捌仟贰佰壹拾玖元壹角玖分");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class OptionStrategyCodeParseTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestOneCode()
|
||||
{
|
||||
var optionCode = "RB1805C30D222.23";
|
||||
var parts = OptionStrategyCodeParser.ParseOptionStrategyCode(optionCode);
|
||||
Assert.AreEqual(1, parts.Length);
|
||||
Assert.AreEqual(1, parts[0].Notional);
|
||||
Assert.AreEqual("RB1805", parts[0].UnderlyingCode);
|
||||
Assert.AreEqual("Call", parts[0].OptionType);
|
||||
Assert.AreEqual("30D", parts[0].Maturity);
|
||||
Assert.AreEqual(222.23, parts[0].Strike, 1e-8);
|
||||
Assert.AreEqual(false, parts[0].IsSell);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestOneCodeWithSign()
|
||||
{
|
||||
var optionCode = "-CC185P1M222";
|
||||
var parts = OptionStrategyCodeParser.ParseOptionStrategyCode(optionCode);
|
||||
Assert.AreEqual(1, parts.Length);
|
||||
Assert.AreEqual(1, parts[0].Notional);
|
||||
Assert.AreEqual("CC185", parts[0].UnderlyingCode);
|
||||
Assert.AreEqual("Put", parts[0].OptionType);
|
||||
Assert.AreEqual("1M", parts[0].Maturity);
|
||||
Assert.AreEqual(222.0, parts[0].Strike, 1e-8);
|
||||
Assert.AreEqual(true, parts[0].IsSell);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestBullSpread()
|
||||
{
|
||||
var optionCode = "-RB1806C1M3700+RB1806C1M3400";
|
||||
var parts = OptionStrategyCodeParser.ParseOptionStrategyCode(optionCode);
|
||||
Assert.AreEqual(2, parts.Length);
|
||||
Assert.AreEqual(1, parts[0].Notional);
|
||||
Assert.AreEqual("RB1806", parts[0].UnderlyingCode);
|
||||
Assert.AreEqual("Call", parts[0].OptionType);
|
||||
Assert.AreEqual("1M", parts[0].Maturity);
|
||||
Assert.AreEqual(3700.0, parts[0].Strike, 1e-8);
|
||||
Assert.AreEqual(true, parts[0].IsSell);
|
||||
|
||||
Assert.AreEqual(1, parts[1].Notional);
|
||||
Assert.AreEqual("RB1806", parts[1].UnderlyingCode);
|
||||
Assert.AreEqual("Call", parts[1].OptionType);
|
||||
Assert.AreEqual("1M", parts[1].Maturity);
|
||||
Assert.AreEqual(3400.0, parts[1].Strike, 1e-8);
|
||||
Assert.AreEqual(false, parts[1].IsSell);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestButterfly()
|
||||
{
|
||||
var optionCode = "RB1806C1M3700-2*RB1806C1M3400+RB1806C1M3100";
|
||||
var parts = OptionStrategyCodeParser.ParseOptionStrategyCode(optionCode);
|
||||
Assert.AreEqual(3, parts.Length);
|
||||
Assert.AreEqual(1, parts[0].Notional);
|
||||
Assert.AreEqual("RB1806", parts[0].UnderlyingCode);
|
||||
Assert.AreEqual("Call", parts[0].OptionType);
|
||||
Assert.AreEqual("1M", parts[0].Maturity);
|
||||
Assert.AreEqual(3700.0, parts[0].Strike, 1e-8);
|
||||
Assert.AreEqual(false, parts[0].IsSell);
|
||||
|
||||
Assert.AreEqual(2, parts[1].Notional);
|
||||
Assert.AreEqual("RB1806", parts[1].UnderlyingCode);
|
||||
Assert.AreEqual("Call", parts[1].OptionType);
|
||||
Assert.AreEqual("1M", parts[1].Maturity);
|
||||
Assert.AreEqual(3400.0, parts[1].Strike, 1e-8);
|
||||
Assert.AreEqual(true, parts[1].IsSell);
|
||||
|
||||
Assert.AreEqual(1, parts[2].Notional);
|
||||
Assert.AreEqual("RB1806", parts[2].UnderlyingCode);
|
||||
Assert.AreEqual("Call", parts[2].OptionType);
|
||||
Assert.AreEqual("1M", parts[2].Maturity);
|
||||
Assert.AreEqual(3100.0, parts[2].Strike, 1e-8);
|
||||
Assert.AreEqual(false, parts[2].IsSell);
|
||||
}
|
||||
|
||||
public class OptionStrategyCodeParser
|
||||
{
|
||||
private static readonly Regex codePattern = new(@"(?<sign>[\+-]?)\s*((?<notional>\d+)\*)?(?<underlying>[a-zA-Z]{1,2}[0-9]{3,4})(?<optionType>C|P)(?<maturity>\d+[DMWY]{1})(?<strike>[0-9]+(?:\.[0-9]*)?)");
|
||||
public static OptionStrategyCodeParts[] ParseOptionStrategyCode(string code)
|
||||
{
|
||||
var mc = codePattern.Matches(code);
|
||||
if (mc.Count == 0)
|
||||
{
|
||||
throw new ArgumentException(string.Format("不合法的策略代码:{0}", code));
|
||||
}
|
||||
return mc.Cast<Match>().Select(m => ParseOneMatch(m)).ToArray();
|
||||
}
|
||||
|
||||
private static OptionStrategyCodeParts ParseOneMatch(Match m)
|
||||
{
|
||||
var parts = new OptionStrategyCodeParts();
|
||||
var groups = m.Groups;
|
||||
parts.UnderlyingCode = groups["underlying"].Value;
|
||||
parts.Strike = double.Parse(groups["strike"].Value);
|
||||
parts.Maturity = groups["maturity"].Value;
|
||||
var optionType = groups["optionType"].Value;
|
||||
if (optionType == "C")
|
||||
{
|
||||
parts.OptionType = "Call";
|
||||
}
|
||||
else if (optionType == "P")
|
||||
{
|
||||
parts.OptionType = "Put";
|
||||
}
|
||||
else
|
||||
{ // Shouldn't come to here, the regex ensured only C|P is matched
|
||||
throw new ArgumentException(string.Format("不合法的期权类型{0}. 合法值为[CP]", optionType));
|
||||
}
|
||||
if (groups["notional"].Length > 0)
|
||||
{
|
||||
parts.Notional = int.Parse(groups["notional"].Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
parts.Notional = 1;
|
||||
}
|
||||
if (groups["sign"].Length > 0)
|
||||
{
|
||||
if (groups["sign"].Value == "-")
|
||||
{
|
||||
parts.IsSell = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
parts.IsSell = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parts.IsSell = false;
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionStrategyCodeParts
|
||||
{
|
||||
public int Notional { get; set; }
|
||||
public string UnderlyingCode { get; set; }
|
||||
public string OptionType { get; set; }
|
||||
public string Maturity { get; set; }
|
||||
public double Strike { get; set; }
|
||||
public bool IsSell { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"{0}{1}{2}{3}{4}{5}",
|
||||
IsSell ? "-" : "",
|
||||
Notional == 1 ? "" : string.Format("{0}*", Notional),
|
||||
UnderlyingCode,
|
||||
"Call".Equals(OptionType) ? "C" : "P",
|
||||
Maturity,
|
||||
Strike);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
using YLErp.Commons;
|
||||
using static YLErp.Models.OtcFormatModel;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class OtcFormatTest
|
||||
{
|
||||
[TestMethod("OtcFormatOption")]
|
||||
public void TestOtcFormatOption()
|
||||
{
|
||||
const double d1 = 2221585d;
|
||||
const double d2 = 2221585.99665655;
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
var option = new OtcFormatOption { };
|
||||
Assert.AreEqual(option.GetFormat(), "0");
|
||||
Assert.AreEqual(option.Format(d1), "2221585");
|
||||
Assert.AreEqual(option.Format(d2), "2221586");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { grouping = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0");
|
||||
Assert.AreEqual(option.Format(d1), "2,221,585");
|
||||
Assert.AreEqual(option.Format(d2), "2,221,586");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { rounded = false };
|
||||
Assert.AreEqual(option.GetFormat(), "0");
|
||||
Assert.AreEqual(option.Format(d1), "2221585");
|
||||
Assert.AreEqual(option.Format(d2), "2221585");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { percent = true };
|
||||
Assert.AreEqual(option.GetFormat(), "0%");
|
||||
Assert.AreEqual(option.Format(d1), "222158500%");
|
||||
Assert.AreEqual(option.Format(d2), "222158600%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { grouping = true, rounded = false };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0");
|
||||
Assert.AreEqual(option.Format(d1), "2,221,585");
|
||||
Assert.AreEqual(option.Format(d2), "2,221,585");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { grouping = true, percent = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0%");
|
||||
Assert.AreEqual(option.Format(d1), "222,158,500%");
|
||||
Assert.AreEqual(option.Format(d2), "222,158,600%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { grouping = true, percent = true, rounded = false };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0%");
|
||||
Assert.AreEqual(option.Format(d1), "222,158,500%");
|
||||
Assert.AreEqual(option.Format(d2), "222,158,599%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2 };
|
||||
Assert.AreEqual(option.GetFormat(), "0.00");
|
||||
Assert.AreEqual(option.Format(d1), "2221585.00");
|
||||
Assert.AreEqual(option.Format(d2), "2221586.00");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 0, maxDecimals = 4 };
|
||||
Assert.AreEqual(option.GetFormat(), "0.####");
|
||||
Assert.AreEqual(option.Format(d1), "2221585");
|
||||
Assert.AreEqual(option.Format(d2), "2221585.9967");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 0, maxDecimals = 4, rounded = false };
|
||||
Assert.AreEqual(option.GetFormat(), "0.####");
|
||||
Assert.AreEqual(option.Format(d1), "2221585");
|
||||
Assert.AreEqual(option.Format(d2), "2221585.9966");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 0, maxDecimals = 4, grouping = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0.####");
|
||||
Assert.AreEqual(option.Format(d1), "2,221,585");
|
||||
Assert.AreEqual(option.Format(d2), "2,221,585.9967");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 0, maxDecimals = 4, grouping = true, percent = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0.####%");
|
||||
Assert.AreEqual(option.Format(d1), "222,158,500%");
|
||||
Assert.AreEqual(option.Format(d2), "222,158,599.6657%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 0, maxDecimals = 4, grouping = true, percent = true, rounded = false };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0.####%");
|
||||
Assert.AreEqual(option.Format(d1), "222,158,500%");
|
||||
Assert.AreEqual(option.Format(d2), "222,158,599.6656%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2, maxDecimals = 4 };
|
||||
Assert.AreEqual(option.GetFormat(), "0.00##");
|
||||
Assert.AreEqual(option.Format(d1), "2221585.00");
|
||||
Assert.AreEqual(option.Format(d2), "2221585.9967");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2, maxDecimals = 4, rounded = false };
|
||||
Assert.AreEqual(option.GetFormat(), "0.00##");
|
||||
Assert.AreEqual(option.Format(d1), "2221585.00");
|
||||
Assert.AreEqual(option.Format(d2), "2221585.9966");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2, maxDecimals = 4, rounded = false, percent = true };
|
||||
Assert.AreEqual(option.GetFormat(), "0.00##%");
|
||||
Assert.AreEqual(option.Format(d1), "222158500.00%");
|
||||
Assert.AreEqual(option.Format(d2), "222158599.6656%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2, maxDecimals = 4, rounded = false, grouping = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0.00##");
|
||||
Assert.AreEqual(option.Format(d1), "2,221,585.00");
|
||||
Assert.AreEqual(option.Format(d2), "2,221,585.9966");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2, maxDecimals = 4, rounded = true, grouping = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0.00##");
|
||||
Assert.AreEqual(option.Format(d1), "2,221,585.00");
|
||||
Assert.AreEqual(option.Format(d2), "2,221,585.9967");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
option = new OtcFormatOption { minDecimals = 2, maxDecimals = 4, rounded = true, grouping = true, percent = true };
|
||||
Assert.AreEqual(option.GetFormat(), "#,##0.00##%");
|
||||
Assert.AreEqual(option.Format(d1), "222,158,500.00%");
|
||||
Assert.AreEqual(option.Format(d2), "222,158,599.6657%");
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
Assert.AreEqual(10d.OtcFormatFlex(0, 10), "10");
|
||||
Assert.AreEqual(10.1d.OtcFormatFlex(0, 10), "10.1");
|
||||
Assert.AreEqual(10.11d.OtcFormatFlex(0, 10), "10.11");
|
||||
Assert.AreEqual(10.123d.OtcFormatFlex(0, 10), "10.123");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OtcFormatTest1()
|
||||
{
|
||||
var model = new OtcFormatModel
|
||||
{
|
||||
trading = new TradingFormat
|
||||
{
|
||||
premiumRateP = new OtcFormatOptionPercent { minDecimals = 2, maxDecimals = 4 }
|
||||
}
|
||||
};
|
||||
OtcFormatHelper.Initialize(JsonHelper.Serialize(model));
|
||||
Assert.AreEqual(OtcFormatExtensions.OtcFormat(0.22556677, OtcFormatFlag.premiumRate), "0.225567");
|
||||
Assert.AreEqual(OtcFormatExtensions.OtcFormat(0.22556677, OtcFormatFlag.premiumRateP), "22.5567%");
|
||||
|
||||
Assert.AreEqual(OtcFormatExtensions.OtcFormatMoney(2255.667788, grouping: true), "2,255.67");
|
||||
Assert.AreEqual(OtcFormatExtensions.OtcFormatMoney(2255.667788, grouping: false), "2255.67");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OtcFormatTest2()
|
||||
{
|
||||
var d = 0.223;
|
||||
var a1 = d.ToString(GetUmPriceFormat() + "%");
|
||||
var a2 = d.OtcFormatUmPrice(true);
|
||||
Assert.AreEqual(a1, "22.3000%");
|
||||
Assert.AreEqual(a2, "22.30%");
|
||||
|
||||
var PremiumRate = 0.225566778899;
|
||||
var fmt = GetPremiumRateFormat() + "%";
|
||||
var str1 = PremiumRate.ToString(fmt);
|
||||
Assert.AreEqual(str1, "22.5567%");
|
||||
Assert.AreEqual(str1, PremiumRate.OtcFormat(OtcFormatFlag.premiumRateP));
|
||||
}
|
||||
|
||||
[TestMethod("OtcFormatPercent")]
|
||||
public void TestOtcFormatPercent()
|
||||
{
|
||||
var dnan = double.NaN;
|
||||
Assert.AreEqual(dnan.OtcFormatPercent(5), "");
|
||||
dnan = double.NegativeInfinity;
|
||||
Assert.AreEqual(dnan.OtcFormatPercent(5), "");
|
||||
|
||||
var d = 0.2233445566778899;
|
||||
Assert.AreEqual(d.OtcFormatPercent(0), "22%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(1), "22.3%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(2), "22.33%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(3), "22.334%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(4), "22.3345%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(5), "22.33446%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(6), "22.334456%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(7), "22.3344557%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(8), "22.33445567%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(9), "22.334455668%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(10), "22.3344556678%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(11), "22.33445566779%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(12), "22.334455667789%");
|
||||
|
||||
d = 22.5566778899;
|
||||
Assert.AreEqual(d.OtcFormatPercent(0), "2256%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(1), "2255.7%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(2), "2255.67%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(3), "2255.668%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(4), "2255.6678%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(5), "2255.66779%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(6), "2255.667789%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(7), "2255.6677890%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(8), "2255.66778899%");
|
||||
|
||||
Assert.AreEqual(d.OtcFormatPercent(0, grouping: true), "2,256%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(1, grouping: true), "2,255.7%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(2, grouping: true), "2,255.67%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(3, grouping: true), "2,255.668%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(4, grouping: true), "2,255.6678%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(5, grouping: true), "2,255.66779%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(6, grouping: true), "2,255.667789%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(7, grouping: true), "2,255.6677890%");
|
||||
Assert.AreEqual(d.OtcFormatPercent(8, grouping: true), "2,255.66778899%");
|
||||
|
||||
double? d2 = default;
|
||||
Assert.AreEqual(d2.OtcFormatPercent(0), "");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(1), "");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(2), "");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(3), "");
|
||||
|
||||
d2 = 22.5566778899;
|
||||
Assert.AreEqual(d2.OtcFormatPercent(0), "2256%");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(1), "2255.7%");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(2), "2255.67%");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(3), "2255.668%");
|
||||
Assert.AreEqual(d2.OtcFormatPercent(4), "2255.6678%");
|
||||
}
|
||||
|
||||
[TestMethod("OtcFormatFlex")]
|
||||
public void TestOtcFormatFlex()
|
||||
{
|
||||
var dnan = double.NaN;
|
||||
Assert.AreEqual(dnan.OtcFormatFlex(5), "");
|
||||
dnan = double.NegativeInfinity;
|
||||
Assert.AreEqual(dnan.OtcFormatFlex(5), "");
|
||||
|
||||
var d1 = 22.55;
|
||||
Assert.AreEqual(d1.OtcFormatFlex(0), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(0, maxDecimals: 4), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(0, rounded: false), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(0, maxDecimals: 4, rounded: false), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(2), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(2, maxDecimals: 4), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(2, rounded: false), "22.55");
|
||||
Assert.AreEqual(d1.OtcFormatFlex(2, maxDecimals: 4, rounded: false), "22.55");
|
||||
|
||||
var d = 22.5566778899;
|
||||
Assert.AreEqual(d.OtcFormatFlex(0), "22.556678");
|
||||
Assert.AreEqual(d.OtcFormatFlex(0, maxDecimals: 4), "22.5567");
|
||||
Assert.AreEqual(d.OtcFormatFlex(0, rounded: false), "22.556677");
|
||||
Assert.AreEqual(d.OtcFormatFlex(0, maxDecimals: 4, rounded: false), "22.5566");
|
||||
Assert.AreEqual(d.OtcFormatFlex(2), "22.556678");
|
||||
Assert.AreEqual(d.OtcFormatFlex(2, maxDecimals: 4), "22.5567");
|
||||
Assert.AreEqual(d.OtcFormatFlex(2, rounded: false), "22.556677");
|
||||
Assert.AreEqual(d.OtcFormatFlex(2, maxDecimals: 4, rounded: false), "22.5566");
|
||||
|
||||
Assert.AreEqual(d.OtcFormatFlex(0, 0, percent: true), "2256%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(1, 1, percent: true), "2255.7%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(2, 2, percent: true), "2255.67%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(3, 3, percent: true), "2255.668%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(4, 4, percent: true), "2255.6678%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(5, 5, percent: true), "2255.66779%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(6, 6, percent: true), "2255.667789%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(7, 7, percent: true), "2255.6677890%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(8, 8, percent: true), "2255.66778899%");
|
||||
|
||||
Assert.AreEqual(d.OtcFormatFlex(0, 0, rounded: false, percent: true), "2255%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(1, 1, rounded: false, percent: true), "2255.6%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(2, 2, rounded: false, percent: true), "2255.66%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(3, 3, rounded: false, percent: true), "2255.667%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(4, 4, rounded: false, percent: true), "2255.6677%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(5, 5, rounded: false, percent: true), "2255.66778%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(6, 6, rounded: false, percent: true), "2255.667788%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(7, 7, rounded: false, percent: true), "2255.6677889%");
|
||||
Assert.AreEqual(d.OtcFormatFlex(8, 8, rounded: false, percent: true), "2255.66778899%");
|
||||
|
||||
double? dnan2 = double.NaN;
|
||||
Assert.AreEqual(dnan2.OtcFormatFlex(5), "");
|
||||
dnan2 = double.NegativeInfinity;
|
||||
Assert.AreEqual(dnan2.OtcFormatFlex(5), "");
|
||||
|
||||
double? d2 = default;
|
||||
Assert.AreEqual(d2.OtcFormatFlex(0, 0, percent: true), "");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(1, 1, percent: true), "");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(2, 2, percent: true), "");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(3, 3, percent: true), "");
|
||||
|
||||
d2 = 22.5566778899;
|
||||
Assert.AreEqual(d2.OtcFormatFlex(0, 0, percent: true), "2256%");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(1, 1, percent: true), "2255.7%");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(2, 2, percent: true), "2255.67%");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(3, 3, percent: true), "2255.668%");
|
||||
Assert.AreEqual(d2.OtcFormatFlex(4, 4, percent: true), "2255.6678%");
|
||||
}
|
||||
|
||||
private static TradingFormat trading => OtcFormatHelper.FormatModel.trading;
|
||||
|
||||
/// <summary>
|
||||
/// 获取标的价格显示格式
|
||||
/// </summary>
|
||||
public static string GetUmPriceFormat()
|
||||
{
|
||||
if (trading.umprice.precision <= 0)
|
||||
{
|
||||
trading.umprice.precision = 4;
|
||||
}
|
||||
return "0.".PadRight(trading.umprice.precision + 2, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取期权费单价显示格式
|
||||
/// </summary>
|
||||
public static string GetTradeSinglePriceFormat()
|
||||
{
|
||||
if (trading.tradeSinglePrice.precision <= 0)
|
||||
{
|
||||
trading.tradeSinglePrice.precision = 3;
|
||||
}
|
||||
return "0.".PadRight(trading.tradeSinglePrice.precision + 2, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取名义本金显示格式
|
||||
/// </summary>
|
||||
public static string GetStockEqvNotionalFormat()
|
||||
{
|
||||
if (trading.StockEqvNotional.precision <= 0)
|
||||
{
|
||||
trading.StockEqvNotional.precision = 2;
|
||||
}
|
||||
return "0.".PadRight(trading.StockEqvNotional.precision + 2, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取期权费总额显示格式
|
||||
/// </summary>
|
||||
public static string GetTradePriceFormat()
|
||||
{
|
||||
return "0.00";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取期权费率显示格式(percentFmt为true时返回P格式)
|
||||
/// </summary>
|
||||
public static string GetPremiumRateFormat(bool percentFmt = false)
|
||||
{
|
||||
if (percentFmt)
|
||||
{
|
||||
return trading.premiumRateP.precision < 1 ? "P4" : "P" + trading.premiumRateP;
|
||||
}
|
||||
if (trading.premiumRateP.precision <= 0)
|
||||
{
|
||||
trading.premiumRateP.precision = 4;
|
||||
}
|
||||
return "0.".PadRight(trading.premiumRateP.precision + 2, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取希腊值显示格式
|
||||
/// </summary>
|
||||
public static string GetGreekFormat()
|
||||
{
|
||||
if (trading.greek.precision <= 0)
|
||||
{
|
||||
trading.greek.precision = 3;
|
||||
}
|
||||
return "0.".PadRight(trading.greek.precision + 2, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数量显示格式
|
||||
/// </summary>
|
||||
public static string GetNotional()
|
||||
{
|
||||
if (trading.notional.precision <= 0)
|
||||
{
|
||||
trading.notional.precision = 2;
|
||||
}
|
||||
return "0.".PadRight(trading.notional.precision + 2, '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using Qdp.Pricing.Base.Implementations;
|
||||
using YLErp.Modules.VolatilityModule;
|
||||
using YLErp.QdpModule;
|
||||
|
||||
namespace YLErp.BasicTests
|
||||
{
|
||||
[TestClass]
|
||||
public class QdpExtensionTest : UnitTestBase
|
||||
{
|
||||
[TestMethod]
|
||||
public void TTMTest()
|
||||
{
|
||||
var maturityDate = new DateTime(2019, 7, 16);
|
||||
var dateT = new DateTime(2019, 7, 12);
|
||||
var dateTPlus = new DateTime(2019, 7, 15);
|
||||
var dateTMinus = new DateTime(2019, 7, 11);
|
||||
var dayCount = new Bus244();
|
||||
|
||||
//1. 报价日期不等于系统日期,所有精确时间模式都无效
|
||||
var ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTMinus, dateT, dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTMinus, dateT, dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTMinus, dateT, dayCount, true, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTMinus, dateT, dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTPlus, dateT, dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTPlus, dateT, dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTPlus, dateT, dayCount, true, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateTPlus, dateT, dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
|
||||
//2. 报价期日等于系统日期
|
||||
//2.1 系统日期等于服务器日期,交易日的日盘
|
||||
//2.1.1 精确到半天
|
||||
//2.1.1.1 有夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 00, 01, 0), dayCount, true, false);
|
||||
Assert.AreEqual(2.66, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 9, 31, 0), dayCount, true, false);
|
||||
Assert.AreEqual(2.66, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 11, 31, 0), dayCount, true, false);
|
||||
Assert.AreEqual(2.66, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 01, 0), dayCount, true, false);
|
||||
Assert.AreEqual(2.33, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 31, 0), dayCount, true, false);
|
||||
Assert.AreEqual(2.33, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 15, 01, 0), dayCount, true, false);
|
||||
Assert.AreEqual(2, ttm, 1e-10);
|
||||
//2.1.1.2 无夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 00, 01, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 9, 31, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 11, 31, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 01, 0), dayCount, false, false);
|
||||
Assert.AreEqual(2.5, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 31, 0), dayCount, false, false);
|
||||
Assert.AreEqual(2.5, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 15, 01, 0), dayCount, false, false);
|
||||
Assert.AreEqual(2, ttm, 1e-10);
|
||||
|
||||
//2.1.2 精确到分钟
|
||||
//2.1.2.1 有夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 00, 15, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.6666666666666665, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 9, 55, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.5138888888888888, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 11, 27, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.2583333333333333, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 08, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.25, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 36, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.2333333333333334, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 15, 01, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2, ttm, 1e-10);
|
||||
//2.1.2.2 无夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 00, 15, 0), dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 9, 55, 0), dayCount, false, true);
|
||||
Assert.AreEqual(2.7708333333333335, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 11, 27, 0), dayCount, false, true);
|
||||
Assert.AreEqual(2.3875, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 08, 0), dayCount, false, true);
|
||||
Assert.AreEqual(2.375, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 13, 36, 0), dayCount, false, true);
|
||||
Assert.AreEqual(2.35, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 12, 15, 01, 0), dayCount, false, true);
|
||||
Assert.AreEqual(2, ttm, 1e-10);
|
||||
|
||||
//2.2 系统日期大于服务器日期,交易日的夜盘
|
||||
//2.2.1 精确到半天
|
||||
//2.2.1.1 有夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 15, 01, 0), dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 20, 31, 0), dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 21, 01, 0), dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 23, 59, 0), dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
//2.2.1.2 无夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 15, 01, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 20, 31, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 21, 01, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 23, 59, 0), dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
|
||||
//2.2.2 精确到分钟
|
||||
//2.2.2.1 有夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 15, 01, 0), dayCount, true, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 20, 31, 0), dayCount, true, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 21, 13, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.963888888888889, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 23, 59, 0), dayCount, true, true);
|
||||
Assert.AreEqual(2.6666666666666665, ttm, 1e-10);
|
||||
//2.2.2.2 无夜盘
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 15, 01, 0), dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 20, 31, 0), dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 21, 13, 0), dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, new DateTime(2019, 7, 11, 23, 59, 0), dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
|
||||
//2.3 系统日期小于服务器日期,所有精确时间模式都无效
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, dateTPlus, dayCount, true, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, dateTPlus, dayCount, false, false);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, dateTPlus, dayCount, true, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
ttm = QdpHelper.CalculateTTMDays(dateT, maturityDate, dateT, dateTPlus, dayCount, false, true);
|
||||
Assert.AreEqual(3, ttm, 1e-10);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestGetTradeVol()
|
||||
{
|
||||
var vol1 = VolatilityHelper.GetTradeVol(valueDate: new DateTime(2022, 3, 10)
|
||||
, valueStartDate: new DateTime(2022, 3, 10)
|
||||
, exerciseDate: new DateTime(2022, 3, 20)
|
||||
, openVol: 0.3
|
||||
, closeVol: 0.1
|
||||
, mumOfSmoothingDays: 3, includeStartDate: true);
|
||||
|
||||
var vol2 = VolatilityHelper.GetTradeVol(valueDate: new DateTime(2022, 3, 10)
|
||||
, valueStartDate: new DateTime(2022, 3, 10)
|
||||
, exerciseDate: new DateTime(2022, 3, 17)
|
||||
, openVol: 0.7
|
||||
, closeVol: 0.1
|
||||
, mumOfSmoothingDays: 7, includeStartDate: true);
|
||||
Assert.AreEqual(vol2, 0.3, 0.001);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user