.NET中实现金融股票的一些简单算法(精简处理)(波动率,收益率,年化,夏普比率等算法简化)
最近接手一个关于股票的系统,显示端需要显示一些庞大且可分析性的比率数据,其中就用到了一些简单且实用的算法(标题中的各个公式,不论是书上还是其他朋友总结出来总会有一些出入,这里只参考工作日情况**非自然日算式方式 **)
这个算法普伦是夏普或者波动都和不同的场景有一些出入,根据个人的实际情况,可以进行适当修改
首先,公式中有用到西格玛(∑,σ)前者大写,后者小写,和sqrt
不了解西格玛的同学可以先了解一下这个的基本知识
σ:小写σ是希腊字母,英文表达sigma,汉语译音为“西格玛”。术语σ用来描述任一过zhi程参数的平均值的分布dao或离散程度;σ(n)表示整数n的所有正因数的和。
对商务或制造过程而言,σ值可以测量过程完成无缺陷作业的能力,是指示过程作业状况良好程度的标尺。σ值越低,则过程状况越好
∑:大写∑用于数学上的总和符号du,比如:∑Pi,其中i=1,2,…,T,即为求P1 + P2 + … + PT的和。zhi
求和符号∑是希腊dao字母西格玛的大写,表示将它右边的所有数,这里是1/n2,加在一起。∑下面的“n=1”表示我们从n=1开始加起,而根据惯例,n是依次增加的正整数。
项目中用到的正是∑的含义:动态上下标和access数值的迭代产生的结果;通俗理解(有限迭代算法)
下面展示用到的原公式(我把公式拆成一个个小部分来封装,更便于理解和阅读,其实是存在嵌套关系的):
年化利率(工作日为基准)
最大回撤率
夏普比率(与波动率紧连)
波动率
下面展示本人封装的方法和简化后的计算方法(实际数据测试ed)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pro_Tools
{
public class Data_Algorithm
{
public int Round { get; set; }
public Data_Algorithm()
{
Round = 0;
}
/// <summary>
/// 声明一个∑西格玛计算委托
/// </summary>
/// <param name="up">上标</param>
/// <param name="down">下标</param>
/// <param name="access">待处理的基数</param>
/// <returns></returns>
public delegate decimal DoMath(int up, int down, decimal access);
/// <summary>
/// 声明一等待执行委托
/// </summary>
/// <param name="function">方法名称</param>
/// <param name="up">上标</param>
/// <param name="down">下标</param>
/// <param name="access">待处理的基数</param>
/// <returns></returns>
public decimal DoMaths(DoMath function, int up, int down, decimal access) => function(up, down, access);
/// <summary>
/// 计算收益
/// </summary>
/// <param name="SellUnitPrice">卖出单价</param>
/// <param name="SellCount">卖出数量</param>
/// <param name="BuyUnitPrice">买入单价</param>
/// <param name="BuyCount">买入数量</param>
/// <returns></returns>
public decimal Profit(decimal SellUnitPrice, decimal SellCount, decimal BuyUnitPrice, decimal BuyCount)
{
decimal end = SellUnitPrice * SellCount;//最终总价值
decimal start = BuyCount * BuyUnitPrice;//最初总价值
decimal result = end - start;
return result;
}
/// <summary>
/// 计算收益率
/// </summary>
/// <param name="SellUnitPrice">卖出单价</param>
/// <param name="SellCount">卖出数量</param>
/// <param name="BuyUnitPrice">买入单价</param>
/// <param name="BuyCount">买入数量</param>
/// <returns></returns>
public decimal Yield(decimal SellUnitPrice, decimal SellCount, decimal BuyUnitPrice, decimal BuyCount)
{
decimal end = SellUnitPrice * SellCount;//最终总价值
decimal start = BuyCount * BuyUnitPrice;//最初总价值
decimal result = (end - start) / start;//做出收益率
return result;
}
/// <summary>
/// 年化收益
/// </summary>
/// <param name="P">收益率</param>
/// <param name="EntDays">执行天数</param>
/// <returns></returns>
public decimal AnnualizedIncome(decimal P, int EntDays)
{
decimal TheFla = (1 + P);
try
{
decimal AnnualizedIncomes = Convert.ToInt32(Math.Pow(Convert.ToDouble(TheFla), 250 / EntDays) - 1);///该处可能损失浮点,但是不会导致异常或报错!!!
return AnnualizedIncomes;
}
catch (Exception ex)
{
return 0m;///表示异常,溢出
throw;
}
}
/// <summary>
/// 计算夏普比率
/// </summary>
/// <param name="Rp">收益率</param>
/// <param name="Rf">无风险利率(有默认值)</param>
/// <param name="σp">策略收益波动率</param>
/// <returns></returns>
public decimal Sharpe_Ratio(decimal Rp, decimal σp, decimal Rf = 0.04m)
{
decimal result = (Rp - Rf) / σp;
return Math.Round(result,2);
}
/// <summary>
/// 计算策略收益波动率 σp
/// </summary>
/// <param name="Rp">收益率</param>
/// <param name="Rpav">策略收益率的平均值</param>
/// <param name="EnterDays">执行天数</param>
/// <returns></returns>
public decimal Volatility(decimal Rp, decimal Rpav, int EnterDays)
{
decimal FirstData = Convert.ToDecimal(Math.Pow(Convert.ToDouble((Rp - Rpav)), 2));///该处计算可能算是浮点,但是不会报错或抛出异常!!!
//decimal SecondData = SigmaAddition(EnterDays, 1, FirstData);///迭代算式1
decimal SecondData = DoMaths(SigmaAddition, EnterDays, 1, FirstData);///迭代算式2
decimal ThirdData = SecondData * (250 / EnterDays - 1);
decimal result = Convert.ToDecimal(Math.Sqrt(Convert.ToDouble(ThirdData)));///该处可能丢失浮点,但是不会报错或者抛出异常!!!
return result;
}
/// <summary>
/// 策略收益率的平均值(包含数乘性)
/// </summary>
/// <param name="SubScript">∑西格玛下标(公式里的i,这里改为动态下标)</param>
/// <param name="Rp">收益率</param>
/// <param name="EnterDays">执行天数(∑上标)</param>
/// <returns></returns>
public decimal The_Average_Daily_Return_Of_The_Strategy(int SubScript, decimal Rp, int EnterDays)
{
Data_Algorithm Da = new Data_Algorithm();
decimal result = 0;
//for (int i = SubScript; i <= EnterDays; i++)
//{
// result += Rp * i;
//}///∑西格玛运算
result += DoMaths(SigmaMultiplication, SubScript, EnterDays, Rp);///迭代计算
result = result * (1 / EnterDays);//平均值
return result;
}
/// <summary>
/// 最大回撤率
/// </summary>
/// <param name="Px">过去式(策略某日股票和现金总价值)</param>
/// <param name="Py">现在或将来(策略某日股票和现金总价值)</param>
/// <returns></returns>
public decimal Max_DrowDown(decimal Px, decimal Py) => (Px - Py) / Px;
/// <summary>
/// 西格玛连加计算(不含数乘)
/// </summary>
/// <param name="up">上标</param>
/// <param name="down">下标</param>
/// <param name="access">待处理的基数</param>
/// <returns></returns>
private decimal SigmaAddition(int up, int down, decimal access)
{
decimal result = 0;
for (int i = down; i <= up; i++)
{
result += access;
}
return result;
}
/// <summary>
/// 西格玛加乘混合计算
/// </summary>
/// <param name="up">上标</param>
/// <param name="down">下标</param>
/// <param name="access">待处理的基数</param>
/// <returns></returns>
private decimal SigmaMultiplication(int up, int down, decimal access)
{
decimal result = 0;
for (int i = down; i < up; i++)
{
result += access * i;
}
return result;
}
/// <summary>
/// 胜率
/// </summary>
/// <param name="Number_Of_Profitable_Transactions">盈利交易次数</param>
/// <param name="Number_Of_Transactions">总交易次数</param>
/// <returns></returns>
public decimal Winning_Probability(int Number_Of_Profitable_Transactions, int Number_Of_Transactions) => Number_Of_Profitable_Transactions / Number_Of_Transactions;
}
}
好,以上就是最简单的几个基本算法和代码逻辑的部分实现过程,作为本人算法的进步记录和经验分享
如有不足请同志积极指正,共同学习!