复杂形态钢结构设计培训班

首页 非解构-公众号 在GH里看基金?

在GH里看基金?

引子

为了在上班的过程中顺利关心工资未来增值的可能性,今天小编就来做一个在Grasshopper里看基金净值的小电池,大致就是实现一个“给定基金代码,通过网络API调用获取基金净值信息,并输出该基金的所有净值信息”。要实现这个功能,首先我们需要首先进行需求分析,然后确定实现的逻辑,最后进行代码编写和简单的测试。

本文主要内容有…

需求分析

电池内部逻辑实现

– 网络请求发送

– 返回Json字符串解析

– 数据传出

测试及总结

需求分析

“给定基金代码”

“输出该基金的所有净值”

“给定基金代码”

一般而言,基金代码都是整型数值,但是考虑到日常使用的时候,基金代码前可能会包含前置位的数字0,比如“002638”——这种带前置0的方式如果用整型来处理就会麻烦一些,故认为它会是整型或者是字符串。

不过,由于在 Grasshopper 里,字符串类型(GH_String)和整数类型(GH_Integer)会自动进行隐式转换,其实不需要担心到底会是整形还是字符串,只需确定我们代码最终接受的类型,GH会在输入参数中自动帮我们进行类型转换。

“输出该基金的所有净值信息”

基金净值是浮点型,但是由于需要获取所有净值信息,包含历史上基金存在时所有的值,所以对应每一个基金代码应该会附带一个列表的信息。

净值是浮点型。其实理论上来说,对于任何与金额相关的数据类型都应该使用 decimal 类型,否则就会出现精度误差,一个经典的例子就是 double 数据类型无法精确表示小数0.3,但是由于在这里我们的 Grasshopper 内建数据类型中没有 decimal,即便此处设置为 decimal,在输出时也会强行给转成 double,所以干脆就双精度浮点型 double 得了。

经过上述分析:

1. 电池的输入端需要一个参数,可以是整型或字符串,这个项目我们就直接采用整型;

2. 输出端需要一个参数,是浮点型;

3. 输入和输出直接的对应关系是一个整型输入对应一个浮点型列表,确定输入端的参数的Access属性为item,输出端的参数的Access属性为list。

此时可以开一个Visual Studio,新建一个Grasshopper电池项目,然后将我们的输入、输出端的参数相关代码放入了。

protectedoverridevoidRegisterInputParams

(GH_InputParamManagerpManager)

{

pManager.AddIntegerParameter(“Code”,

“C”,”基金代码”,GH_ParamAccess.item);

}

protectedoverridevoidRegisterOutputParams

(GH_OutputParamManagerpManager)

{

pManager.AddNumber(“DayValues”,

“v”,”净值”,GH_ParamAccess.list);

}

电池内部逻辑实现

这部分是整个电池项目中最耗时的部分,也就是在电池类的`SolveInstance`中处理输入的基金代码信息,并给出最终的净值浮点数列表。

首先获取基金的代码:

protectedoverridevoidSolveInstance(IGH_DataAccessDA)

{

//获取基金代码,检测获取是否成功,若不成功直接退出电池执行

intcode=int.MinValue;

boolSuccess=DA.GetData(0,refcode);

if(!Success)return;

}

然后就是对基金净值API的调用,这里调用的是 “小熊同学”网站的基金API。

(https://www.doctorxiong.club/#/guide)

这个API的返回值是一个json字符串,里面包含基金的名称、代码、净值等信息,详细的API文档可在网站中找到。

现在的问题就聚焦到两个部分了,一个是如何发送网络请求,另一个是如何在返回的json字符串中提取我们需要的信息。

网络请求的发送

由于我们是在 Grasshopper 中实现该逻辑,所以运行环境是 .NETFramework4.5。在网络上找资料时也需要时刻注意运行环境。目前.NET生态已经布局到全平台,很多相关网络请求的资料找到的都是 .NETCore 或者 .NET 的,而 .NETFramework 与它们略有不同,依赖项可能会不一样。

.NETFramework框架下,网络请求的发送可以使用System.Net 命名空间里的 WebRequest 类实现。

(具体.NET/.NETCore/.NETFramework三者有什么区别和联系读者们也可以自行探索一下,相关历史介绍还是挺多的)

protectedoverridevoidSolveInstance(IGH_DataAccessDA)

{

//获取基金代码,检测获取是否成功,若不成功直接退出电池执行

//……….略

//建立请求

varreq=WebRequest.Create(@”https://api.doctorxiong.club/v1/fund/detail?code=”+code.ToString());

req.Method=”GET”;

req.Headers.Add(HttpRequestHeader.AcceptCharset,”utf-8″);

//发起请求,将请求返回保存至res中

varres=req.GetResponse();

}

解析Json字符串

接下来,

就需要对返回的json字符串进行解析了。考虑到现在网络编程的便利性,json字符串几乎已经成为网络编程中数据往来的标准格式,所以json字符串的解析就不需要手写了,.NET框架已经自带了json字符串解析的功能,可以自动将json字符串封装成一个 C#的object提供原生访问,十分方便。

但是,在.NET下很方便使用的json解析功能在 .NETFramework 中是不能使用的!所以我们需要用到它的前生Newtonsoft.Json。这个DLL需要手动添加,具体添加方法为:

1.在VisualStudio的项目管理器中找到引用(References)并右键单击,选择添加引用

2.弹出窗口左上角选择Assemblies->Extensions

3.找到并选择Json.NET,单击确定添加,此时引用中出现 Newtonsoft.Json

引用添加成功后我们可以在代码中加入命名空间

usingNewtonsoft.Json;

此时我们离解析成功仅差一步之遥了。

前面提到用使用Newtonsoft.Json可以自动把json字符串转换为一个可以操作的对象实例,其前提是,这个对象实例我们需要有这个对象的数据模型

想象json是一堆货物,Newtonsoft.Json可以帮忙装货,但是它需要知道每种货物需要被装在什么位置,我们需要指明数据会被装在什么对象的什么属性中。

数据模型其实就是一个类,我们需要依据json的格式去构建这个类的属性,下面就直接给出笔者建立的数据模型。笔者在这里使用的是 struct 结构体,读者也可以自行换成 class 关键字。

publicstructResponseData

{

publicHttpStatusCodeCode{get;set;}

publicstringMessage{get;set;}

publicFundData{get;set;}

publicstringMeta{get;set;}

publicstructFund

{

publicstringCode{get;set;}

publicstringName{get;set;}

publicstringType{get;set;}

publicfloatNetWorth{get;set;}

publicfloatExpectWorth{get;set;}

publicfloatTotalWorth{get;set;}

publicstringExpectGrowth{get;set;}

publicstringDayGrowth{get;set;}

publicstringLastWeekGrowth{get;set;}

publicstringLastMonthGrowth{get;set;}

publicstringLastThreeMonthsGrowth{get;set;}

publicstringLastSixMonthsGrowth{get;set;}

publicstringLastYearGrowth{get;set;}

publicstringBuyMin{get;set;}

publicstringBuySourceRate{get;set;}

publicstringBuyRate{get;set;}

publicstringManager{get;set;}

publicstringFundScale{get;set;}

publicstringNetWorthDate{get;set;}

publicstringExpectWorthDate{get;set;}

publicstring[][]NetWorthData{get;set;}

publicstring[][]TotalNetWorthData{get;set;}

}

}

有了这个数据模型,我们就可以直接对返回的json字符串进行解析,代码如下:

MemoryStream类需要用到命名空间System.IO

Encoding类需要用命名空间System.Text

protectedoverridevoidSolveInstance(IGH_DataAccessDA)

{

//获取基金代码,检测获取是否成功,若不成功直接退出电池执行

//建立请求

//发起请求,将请求返回保存至res中

//准备解析

stringjsonString;

//获取返回流

using(varresponseStream=res.GetResponseStream())

{

//在内存中创建临时存储用来存储返回流数据

using(varms=newMemoryStream())

{

//返回流数据复制至内存中

responseStream.CopyTo(ms);

//用UTF8解码返回流数据

jsonString=Encoding.UTF8.GetString(ms.ToArray());

//解析json字符串

varresData=JsonConvert.DeserializeObject<ResponseData>(jsonString);

}

}

}

最终我们获得了变量 resData 就是最终我们解析得到的数据,它是一个 ResponseData 结构体的实例,我们可以在后续传出数据时方便地通过该结构体获得数据。

数据传出

下面的事情

就又变得简单了起来。

由于我们的输出是对应一个数据列表,我们仅需从 resData 中提取到我们想要的基金净值数据,存储在一个 List<double> 中,然后借由 DA.SetDataList() 方法传出即可。

通过基金API可知,基金净值信息包含在 NetWorthData 中,每个NetWorthData包含4个数据,分别是“日期、净值、日涨跌、额外信息”。我们所需要的净值在该列表的第二项。

又因为所有的数据在数据模型中是以字符串形式给出,我们需要使用double.Parse来进行格式转换……等等……GH可以自动隐式转换,我们不如直接输出字符串试试看?

protectedoverridevoidSolveInstance(IGH_DataAccessDA)

{

//获取基金代码,检测获取是否成功,若不成功直接退出电池执行

//建立请求

//发起请求,将请求返回保存至res中

//准备解析

stringjsonString;

//获取返回流

using(varresponseStream=res.GetResponseStream())

{

//在内存中创建临时存储用来存储返回流数据

using(varms=newMemoryStream())

{

//返回流数据复制至内存中

//用UTF8解码返回流数据

//解析json字符串

//提取每天的净值信息,放入列表中

List<string>dayValues=newList<string>();

foreach(variteminresData.Data.NetWorthData)

dayValues.Add(item[1]);

//传出数据

DA.SetDataList(0,dayValues);

}

}

}

这样我们的电池就完工了!下面赶紧让我们来试试看把。文章最后有完整cs文件的代码可供参考

测试及总结

首先要做的是在Rhino中使用 GrasshopperDevelopSetting 命令加入我们电池的输出目录。具体细节可以参考我们公众号的Grasshopper基础教程,本文在此不再复述。设置完成后关闭Rhino。

点击运行,让我们测试一下自己的电池吧!

当然,硬是要输入一个不存在的基金代码,此时我们无法成功地解析服务器返回的json字符串,GH也能帮我们完成错误处理……

通过这个小电池,我们从如何收集数据、实现自己的逻辑,到最后传出数据,进行简单的测试。涉及到的点大致有下面几个内容

1.输入/输出参数的确定,以及它们的类型,相关的GH特有的隐式类型转换

2.对 WebAPI 发起一个网络请求

3.对返回的json字符串进行解析

4.简单的测试

其中,“json字符串解析 ”部分本文并没有详细展开,因为它本身就能做一个超级大的内容了,这里只给出了一个具体的应用。想要详细了解的读者可以自行搜索更多于json字符串解析的内容。

另外,“网络请求”相关的内容,读者在搜索额外资料时请注意适用环境,.NET/.NETCore 是一类环境,.NETFramework 与它们是有一些差别的。

最后,部分代码涉及到了 “流(Stream)”的概念,这是有关于I/O相关的内容。初步理解的话就是可以认为“流”是一系列函数,最后的数据会在所有的中间的流中过一遍,也就是实现了对整个数据流的依次处理。读者感兴趣的话可以自行继续深入学习。

电池代码部分详见

https://gitee.com/fodan/non-structure_-code_-share/blob/master/Grasshopper_GetFundDetails.cs

我们非解构一直关注建筑艺术与结构技术的有机融合。我们在做好设计的同时,一直关注数字化、智能化等前沿技术在建筑设计行业中的运用,这些年一直在坚持探索和实践。

非常欢迎优秀的你来加入我们,一起来跨界,做一名推动行业发展的斜杠青年。

非解构 | 跨界建筑师招募

非解构 | 跨界结构工程师招募

非解构 | 算法工程师招募

结构跨界实习生招募

这几年,对参数化设计感兴趣的朋友越来越多,我们的参数化设计交流群也已经发展到了5群,欢迎更多的朋友加入,相互交流学习。

添加我们“转自:非解构-公众号”微信,

加入参数化设计交流群。

不了解我们的可以来补课了

非解构 | 数字化技术助力探索结构设计新空间

非解构 | 参数化建筑设计技术路径探讨

非解构 | 对BIM工作流的深度思考

当结构设计遇到遗传算法

当建筑师甩给我一个Rhino模型(一)

当建筑师甩给我一个rhino模型(二)

盈建科,二次开发

PKPM, 二次开发

本文来自网络,不代表钢构人的立场,转载请注明出处。搜索工程类文章,就用钢构人网站。 https://www.ganggouren.com/2021/06/8e75b3037b/
上一篇
下一篇

作者: ganggouren

为您推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

联系我们

联系我们

17717621528

在线咨询: QQ交谈

邮箱: 1356745727@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部