WPF:股票收益计算器

开发环境:

功能说明:

  1. 精确计算沪深A股收益
  2. 具有简单记账功能

更新历史:

2013年09月20日

  • 修正过户费计算错误

2013年07月31日

  • 在配置文件中增加设置记账用的字符集编码选项

2013年07月30日

  • 记账中股票价格精确到厘

2013年07月28日

  • 修正了过户费的计算
  • 修正了大额交易时数据溢出的问题
  • 增加了多次买入同一股票时,直接通过买入成本来核算收益

2013年07月23日

  • 完成股票收益计算器

软件下载:

StockReturn.zip

源代码下载:

StockReturnSource.zip

软件界面:

股票收益计算器

源代码:
MainWindow.xaml

<Window x:Class="Splash.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
        Title="股票收益计算器" Height="600" Width="500" Icon="balance.ico" ResizeMode="CanMinimize" SizeToContent="Height" WindowStartupLocation="CenterScreen" Closing="Window_Closing" Loaded="Window_Loaded" FontFamily="Microsoft YaHei" KeyDown="Window_KeyDown" MouseRightButtonDown="Window_MouseRightButtonDown">
    <Grid Margin="8">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <GroupBox Grid.Row="0">
            <GroupBox.Header>
                <Label Content="证券交易所" />
            </GroupBox.Header>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>

                <RadioButton Grid.Column="0" Name="radioButtonSHA" Content="沪市A股" VerticalAlignment="Center" Margin="8" IsChecked="True" Click="radioButtonSHA_Click" TabIndex="1" />
                <RadioButton Grid.Column="1" Name="radioButtonSZA" Content="深市A股" VerticalAlignment="Center" Margin="8" Click="radioButtonSZA_Click" TabIndex="2" />
            </Grid>
        </GroupBox>

        <GroupBox Grid.Row="1">
            <GroupBox.Header>
                <Label Content="交易税率" />
            </GroupBox.Header>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>

                <Grid Grid.Row="0">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="60" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <Label Grid.Row="0" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="券商佣金比率" />
                    <Label Grid.Row="1" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="印花税税率" />

                    <TextBox Name="textBoxCommissionRate" Grid.Row="0" Grid.Column="1" Margin="0,4" Text="0.075" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" TabIndex="3" />
                    <TextBox Name="textBoxStampDutyRate" Grid.Row="1" Grid.Column="1" Margin="0,4" Text="0.1" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" TabIndex="4" />

                    <Label Grid.Row="0" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="%(不足5元按5元收取)" />
                    <Label Grid.Row="1" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="%(仅在卖出时征收)" />
                </Grid>

                <Grid Grid.Row="1" Name="gridTransferFee">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="60" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <Label Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="过户费费率" />
                    <TextBox Name="textBoxTransferFeeRate" Grid.Column="1" Margin="0,4" Text="0.6" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" TabIndex="5" />
                    <Label Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元/千股(最低收取1元)" />
                </Grid>
            </Grid>
        </GroupBox>

        <GroupBox Name="groupBoxStockTradeVolume" Grid.Row="2">
            <GroupBox.Header>
                <Label Content="交易量" />
            </GroupBox.Header>

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="60" />
                    <ColumnDefinition Width="60" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <Label Grid.Row="0" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="股票买入数量" />
                <Label Grid.Row="1" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="股票买入价" />
                <Label Grid.Row="2" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="股票卖出数量" />
                <Label Grid.Row="3" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="股票卖出价" />

                <TextBox Name="textBoxNumberOfSharesBought" Grid.Row="0" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" TabIndex="7" LostFocus="textBoxNumberOfSharesBought_LostFocus" TextChanged="textBoxTradeVolumeState_TextChanged" />
                <TextBox Name="textBoxStockPurchasePrice" Grid.Row="1" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" TabIndex="8" TextChanged="textBoxTradeVolumeState_TextChanged" />
                <TextBox Name="textBoxStockAskSize" Grid.Row="2" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" IsReadOnly="True" TabIndex="9" TextChanged="textBoxTradeVolumeState_TextChanged" />
                <TextBox Name="textBoxStockAskingPrice" Grid.Row="3" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" TabIndex="10" TextChanged="textBoxTradeVolumeState_TextChanged" />

                <Label Grid.Row="0" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="股" />
                <Label Grid.Row="1" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元/股" />
                <Label Grid.Row="2" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="股" />
                <Label Grid.Row="3" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元/股" />

                <Grid Grid.Row="0" Grid.RowSpan="2" Grid.Column="3">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>

                    <Label Grid.Row="0" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="股票代号" Padding="0,5,5,5" />
                    <TextBox Name="textBoxStockCode" Grid.Row="0" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" input:InputMethod.IsInputMethodEnabled="False" MaxLength="6" TabIndex="13" />
                    <Button Name="buttonAccounting" Grid.Row="0" Grid.Column="2" Margin="8,4" MinWidth="80" Content="记账" TabIndex="15" Click="buttonAccounting_Click" />

                    <Label Grid.Row="1" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="股票名称" Padding="0,5,5,5" />
                    <TextBox Name="textBoxStockName" Grid.Row="1" Grid.Column="1" Margin="0,4" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" TabIndex="14" />
                    <Button Name="buttonView" Grid.Row="1" Grid.Column="2" Margin="8,4" MinWidth="80" Content="查看" TabIndex="16" Click="buttonView_Click"/>
                </Grid>

                <CheckBox Name="checkBoxSame" Grid.Row="2" Grid.Column="3" Margin="0,4" VerticalContentAlignment="Center" IsChecked="True" Content="同买入数量" TabIndex="12" Click="checkBoxSame_Click" />

                <Grid Grid.Row="3" Grid.Column="3" Margin="0,4">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                    <Button Name="buttonCalculate" Grid.Column="0" Margin="8,0" MaxWidth="80" Content="计算" Click="buttonCalculate_Click" TabIndex="11" />
                    <Button Name="buttonReset" Grid.Column="1" Margin="8,0" MaxWidth="80" Content="重置" Click="buttonReset_Click" TabIndex="12" />
                </Grid>
            </Grid>
        </GroupBox>

        <GroupBox Name="groupBoxOutput" Grid.Row="3">
            <GroupBox.Header>
                <Label Content="计算结果" />
            </GroupBox.Header>

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="8" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>

                <CheckBox Name="checkBoxStockPurchaseCost" Grid.Row="0" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="买入成本" Click="checkBoxStockPurchaseCost_Click" />
                <Label Grid.Row="1" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="过户费" />
                <Label Grid.Row="2" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="券商佣金" />
                <Label Grid.Row="3" Grid.Column="0" Margin="0,4" VerticalContentAlignment="Center" Content="总体投资收益" />

                <TextBox Name="textBoxStockPurchaseCost" Grid.Row="0" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" ToolTip="{Binding Text, RelativeSource={RelativeSource Self}}" TextChanged="textBoxStockPurchaseCost_TextChanged" />
                <TextBox Name="textBoxStockTransferFee" Grid.Row="1" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" />
                <TextBox Name="textBoxStockBrokerageCommission" Grid.Row="2" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" />
                <TextBox Name="textBoxTotalInvestmentIncome" Grid.Row="3" Grid.Column="1" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" Foreground="Red" Background="LightGray" FontSize="24" FontWeight="Bold" ToolTip="{Binding Text, RelativeSource={RelativeSource Self}}" />

                <Label Grid.Row="0" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元" />
                <Label Grid.Row="1" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元" />
                <Label Grid.Row="2" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元" />
                <Label Grid.Row="3" Grid.Column="2" Margin="0,4" VerticalContentAlignment="Center" Content="元" />

                <Label Grid.Row="0" Grid.Column="4" Margin="0,4" VerticalContentAlignment="Center" Content="卖出收入" />
                <Label Grid.Row="1" Grid.Column="4" Margin="0,4" VerticalContentAlignment="Center" Content="印花税" />
                <Label Grid.Row="2" Grid.Column="4" Margin="0,4" VerticalContentAlignment="Center" Content="税费合计" />
                <Label Grid.Row="3" Grid.Column="4" Margin="0,4" VerticalContentAlignment="Center" Content="总体盈亏比例" />

                <TextBox Name="textBoxStockSellRevenue" Grid.Row="0" Grid.Column="5" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" ToolTip="{Binding Text, RelativeSource={RelativeSource Self}}" />
                <TextBox Name="textBoxStockStampDuty" Grid.Row="1" Grid.Column="5" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" />
                <TextBox Name="textBoxStockTotalTaxes" Grid.Row="2" Grid.Column="5" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" />
                <TextBox Name="textBoxTotalProfitAndLossRatio" Grid.Row="3" Grid.Column="5" Margin="0,4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="True" Background="LightGray" FontSize="24" FontWeight="Bold" ToolTip="{Binding Text, RelativeSource={RelativeSource Self}}" />

                <Label Grid.Row="0" Grid.Column="6" Margin="0,4" VerticalContentAlignment="Center" Content="元" />
                <Label Grid.Row="1" Grid.Column="6" Margin="0,4" VerticalContentAlignment="Center" Content="元" />
                <Label Grid.Row="2" Grid.Column="6" Margin="0,4" VerticalContentAlignment="Center" Content="元" />
                <Label Grid.Row="3" Grid.Column="6" Margin="0,4" VerticalContentAlignment="Center" Content="%" />
            </Grid>
        </GroupBox>
    </Grid>
</Window>


MainWindow.xaml.cs

/* ----------------------------------------------------------
 * 文件名称:MainWindow.xaml.cs
 *
 * 作者:秦建辉
 *
 * QQ:36748897
 *
 * 博客:http://www.firstsolver.com/wordpress/
 *
 * 开发环境:
 *      Visual Studio V2012
 *      .NET Framework 4 Client Profile
 *
 * 版本历史:
 *      V1.4	2013年09月20日
 *              修正过户费计算错误
 *
 *      V1.3	2013年07月31日
 *              在配置文件中增加设置记账用的字符集编码选项
 *
 *      V1.2	2013年07月30日
 *              记账中股票价格精确到厘
 *
 *      V1.1	2013年07月28日
 *              修正了过户费的计算
 *              修正了大额交易时数据溢出的问题
 *              增加了多次买入同一股票时,直接通过买入成本来核算收益
 *
 *      V1.0	2013年07月23日
 *              完成股票收益计算器
 * 注意事项:
 *      Math.Round为4舍6入,如果为5,则看前一位,奇进偶不进,不符合现实情况中的4舍5入要求
------------------------------------------------------------ */
using Splash.Linq;
using Splash.Windows;
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Splash
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// 配置文件信息
        /// </summary>
        private StockReturnConfig Config = new StockReturnConfig();

        /// <summary>
        /// 配置文件路径
        /// </summary>
        private String iniFilePath = AppDomain.CurrentDomain.BaseDirectory + "\\" + "StockReturn.ini";

        /// <summary>
        /// 记账文件存储目录
        /// </summary>
        private static readonly String csvToFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Splash\\StockReturn\\";

        /// <summary>
        /// 记账文件存储路径
        /// </summary>
        private static readonly String csvFilePath = csvToFolder + "StockReturn.csv";

        /// <summary>
        /// 是否已有计算输出结果
        /// </summary>
        private Boolean isHasOutput = false;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void radioButtonSHA_Click(object sender, RoutedEventArgs e)
        {   // 沪市A股,显示过户费
            if ((Boolean)radioButtonSHA.IsChecked) gridTransferFee.Visibility = System.Windows.Visibility.Visible;
        }

        private void radioButtonSZA_Click(object sender, RoutedEventArgs e)
        {   // 深市A股,隐藏过户费
            if ((Boolean)radioButtonSZA.IsChecked) gridTransferFee.Visibility = System.Windows.Visibility.Collapsed;
        }

        private void checkBoxSame_Click(object sender, RoutedEventArgs e)
        {
            textBoxStockAskSize.IsReadOnly = (Boolean)checkBoxSame.IsChecked;
            if ((Boolean)checkBoxSame.IsChecked)
            {   // 卖出数量等同于买入数量
                textBoxStockAskSize.Text = textBoxNumberOfSharesBought.Text;
            }
            else
            {
                textBoxStockAskSize.Clear();
                textBoxStockAskSize.Focus();
            }
        }

        private void textBoxNumberOfSharesBought_LostFocus(object sender, RoutedEventArgs e)
        {
            if ((Boolean)checkBoxSame.IsChecked)
            {
                textBoxStockAskSize.Text = textBoxNumberOfSharesBought.Text;
            }
        }

        // 计算
        private void buttonCalculate_Click(object sender, RoutedEventArgs e)
        {
            // 券商佣金比率
            Double CommissionRate;
            if (!Double.TryParse(textBoxCommissionRate.Text, out CommissionRate))
            {
                MessageBoxPlus.Show(this, "不正确的券商佣金比率!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxCommissionRate.Focus();
                return;
            }
            if (CommissionRate != Config.CommissionRate)
            {
                Config.CommissionRate = CommissionRate;
                Config.isUpdateNeeded = true;
            }

            // 印花税税率
            Double StampDutyRate;
            if (!Double.TryParse(textBoxStampDutyRate.Text, out StampDutyRate))
            {
                MessageBoxPlus.Show(this, "不正确的印花税税率!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxStampDutyRate.Focus();
                return;
            }
            if (StampDutyRate != Config.StampDutyRate)
            {
                Config.StampDutyRate = StampDutyRate;
                Config.isUpdateNeeded = true;
            }

            // 过户费费率
            Double TransferFeeRate;
            if (!Double.TryParse(textBoxTransferFeeRate.Text, out TransferFeeRate))
            {
                MessageBoxPlus.Show(this, "不正确的过户费费率!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxTransferFeeRate.Focus();
                return;
            }
            if (TransferFeeRate != Config.TransferFeeRate)
            {
                Config.TransferFeeRate = TransferFeeRate;
                Config.isUpdateNeeded = true;
            }

            Int32 NumberOfSharesBought = 0;     // 股票买入数量
            Double StockPurchasePrice = 0.0;    // 股票买入价格
            if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
            {
                if (!Int32.TryParse(textBoxNumberOfSharesBought.Text, out NumberOfSharesBought))
                {
                    MessageBoxPlus.Show(this, "不正确的股票买入数量!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                    textBoxNumberOfSharesBought.Focus();
                    return;
                }

                if (!Double.TryParse(textBoxStockPurchasePrice.Text, out StockPurchasePrice))
                {
                    MessageBoxPlus.Show(this, "不正确的股票买入价格!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                    textBoxStockPurchasePrice.Focus();
                    return;
                }
            }

            // 股票卖出数量
            Int32 StockAskSize;
            if (!Int32.TryParse(textBoxStockAskSize.Text, out StockAskSize))
            {
                MessageBoxPlus.Show(this, "不正确的股票卖出数量!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxStockAskSize.Focus();
                return;
            }

            // 股票卖出价格
            Double StockAskingPrice;
            if (!Double.TryParse(textBoxStockAskingPrice.Text, out StockAskingPrice))
            {
                MessageBoxPlus.Show(this, "不正确的股票卖出价格!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxStockAskingPrice.Focus();
                return;
            }

            // 计算过户费
            Double BuyingTransferFee = 0.0;
            Double SellingTransferFee = 0.0;
            if ((Boolean)radioButtonSHA.IsChecked)
            {   // 沪市A股
                const Int32 Base = 1000;
                if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
                {
                    BuyingTransferFee = NumberOfSharesBought * TransferFeeRate / Base;
                    BuyingTransferFee = ((Int64)(BuyingTransferFee * 1000 + 5)) / 10 * 0.01;     // 圆整到小数点后2位
                    if (BuyingTransferFee < 1.0) BuyingTransferFee = 1.0;   // 不足1元时按1元收取
                }

                SellingTransferFee = StockAskSize * TransferFeeRate / Base;
                SellingTransferFee = ((Int64)(SellingTransferFee * 1000 + 5)) / 10 * 0.01;
                if (SellingTransferFee < 1.0) SellingTransferFee = 1.0;     // 不足1元时按1元收取
            }
            Double TransferFee = BuyingTransferFee + SellingTransferFee;
            textBoxStockTransferFee.Text = TransferFee.ToString("F2");

            // 计算印花税
            Double StampDuty = StockAskSize * StockAskingPrice * StampDutyRate * 0.01;
            StampDuty = ((Int64)(StampDuty * 1000 + 5)) / 10 * 0.01;
            textBoxStockStampDuty.Text = StampDuty.ToString("F2");

            // 计算券商佣金
            Double BuyingCommission = 0.0;
            if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
            {
                BuyingCommission = NumberOfSharesBought * StockPurchasePrice * CommissionRate * 0.01;
                BuyingCommission = ((Int64)(BuyingCommission * 1000 + 5)) / 10 * 0.01;
                if (BuyingCommission < 5.0) BuyingCommission = 5.0;             // 买入佣金
            }            

            Double SellingCommission = StockAskSize * StockAskingPrice * CommissionRate * 0.01;
            SellingCommission = ((Int64)(SellingCommission * 1000 + 5)) / 10 * 0.01;
            if (SellingCommission < 5.0) SellingCommission = 5.0;           // 卖出佣金

            Double BrokerCommission = BuyingCommission + SellingCommission; // 总的佣金
            textBoxStockBrokerageCommission.Text = BrokerCommission.ToString("F2");

            // 计算税费合计:过户费 + 印花税 + 券商佣金
            Double StockTotalTaxes = TransferFee + StampDuty + BrokerCommission;
            textBoxStockTotalTaxes.Text = StockTotalTaxes.ToString("F2");

            // 计算买入成本
            Double StockPurchaseCost = 0.0;
            if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
            {
                StockPurchaseCost = BuyingTransferFee + BuyingCommission + NumberOfSharesBought * StockPurchasePrice;
                StockPurchaseCost = ((Int64)(StockPurchaseCost * 1000 + 5)) / 10 * 0.01;
            }
            else
            {
                if (!Double.TryParse(textBoxStockPurchaseCost.Text, out StockPurchaseCost))
                {
                    MessageBoxPlus.Show(this, "不正确的买入成本!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                    textBoxStockPurchaseCost.Focus();
                    return;
                }
            }
            if (StockPurchaseCost < 1.0)    // 1手100股
            {
                MessageBoxPlus.Show(this, "不正确的买入成本!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxStockPurchaseCost.Focus();
                return;
            }

            textBoxStockPurchaseCost.Text = StockPurchaseCost.ToString("F2");

            // 计算卖出收入
            Double StockSellRevenue = StockAskSize * StockAskingPrice - SellingTransferFee - StampDuty - SellingCommission;
            StockSellRevenue = ((Int64)(StockSellRevenue * 1000 + 5)) / 10 * 0.01;
            textBoxStockSellRevenue.Text = StockSellRevenue.ToString("F2");

            // 计算总体投资收益
            Double TotalInvestmentIncome = StockSellRevenue - StockPurchaseCost;
            textBoxTotalInvestmentIncome.Text = TotalInvestmentIncome.ToString("F2");

            // 计算总体盈亏比例
            Double TotalProfitAndLossRatio = TotalInvestmentIncome / StockPurchaseCost * 100;
            TotalProfitAndLossRatio = ((Int64)(TotalProfitAndLossRatio * 1000 + 5)) / 10 * 0.01;
            textBoxTotalProfitAndLossRatio.Text = TotalProfitAndLossRatio.ToString("F2");

            // 设置颜色
            switch (Math.Sign(TotalInvestmentIncome))
            {
                case 1:
                    textBoxTotalInvestmentIncome.Foreground = textBoxTotalProfitAndLossRatio.Foreground = new SolidColorBrush(Colors.Red);
                    break;

                case 0:
                    textBoxTotalInvestmentIncome.Foreground = textBoxTotalProfitAndLossRatio.Foreground = new SolidColorBrush(Colors.White);
                    break;

                case -1:
                    textBoxTotalInvestmentIncome.Foreground = textBoxTotalProfitAndLossRatio.Foreground = new SolidColorBrush(Colors.Green);
                    break;
            }

            isHasOutput = true; // 已生成计算结果
        }

        // 重置
        private void buttonReset_Click(object sender, RoutedEventArgs e)
        {   // 交易量组合框
            ClearTextBoxInPanel(groupBoxStockTradeVolume.Content as Panel);

            // 计算结果组合框
            ClearTextBoxInPanel(groupBoxOutput.Content as Panel);
        }

        // 记账
        private void buttonAccounting_Click(object sender, RoutedEventArgs e)
        {
            if (String.IsNullOrEmpty(textBoxStockCode.Text))
            {
                MessageBoxPlus.Show(this, "股票代码不能为空!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxStockCode.Focus();
                return;
            }

            if (String.IsNullOrEmpty(textBoxStockName.Text))
            {
                MessageBoxPlus.Show(this, "股票名称不能为空!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                textBoxStockName.Focus();
                return;
            }

            if (!isHasOutput)
            {
                MessageBoxPlus.Show(this, "请先获取计算结果!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            // 判断文件是否存在
            if (!System.IO.File.Exists(csvFilePath))
            {   // 如果目标文件夹不存在则自动创建
                if (!System.IO.Directory.Exists(csvToFolder))
                {
                    System.IO.Directory.CreateDirectory(csvToFolder);
                }

                using (StreamWriter sw = new StreamWriter(csvFilePath, true, System.Text.Encoding.GetEncoding(Config.CodePage)))
                {   // 写入列标题
                    sw.WriteLine("\"股票代码\",\"股票名称\",\"买入数量\",\"卖出数量\",\"买入价格\",\"卖出价格\",\"买入成本\",\"卖出收入\",\"税费合计\",\"投资收益\",\"盈亏比例\"");
                }
            }

            try
            {
                using (StreamWriter sw = new StreamWriter(csvFilePath, true, System.Text.Encoding.GetEncoding(Config.CodePage)))
                {
                    // 股票代码
                    sw.Write("\"" + textBoxStockCode.Text + "\",");

                    // 股票名称
                    sw.Write("\"" + textBoxStockName.Text + "\",");

                    // 股票买入数量
                    if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
                    {
                        sw.Write("\"" + textBoxNumberOfSharesBought.Text + "\",");
                    }
                    else
                    {
                        sw.Write("\"\",");
                    }

                    // 股票卖出数量
                    sw.Write("\"" + textBoxStockAskSize.Text + "\",");

                    // 股票买入价格
                    if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
                    {
                        Double StockPurchasePrice = Double.Parse(textBoxStockPurchasePrice.Text);
                        sw.Write("\"" + StockPurchasePrice.ToString("F3") + "\",");
                    }
                    else
                    {
                        sw.Write("\"\",");
                    }

                    // 股票卖出价格
                    Double StockAskingPrice = Double.Parse(textBoxStockAskingPrice.Text);
                    sw.Write("\"" + StockAskingPrice.ToString("F3") + "\",");

                    // 买入成本
                    sw.Write("\"" + textBoxStockPurchaseCost.Text + "\",");

                    // 卖出收入
                    sw.Write("\"" + textBoxStockSellRevenue.Text + "\",");

                    // 税费合计
                    if (!(Boolean)checkBoxStockPurchaseCost.IsChecked)
                    {
                        sw.Write("\"" + textBoxStockTotalTaxes.Text + "\",");
                    }
                    else
                    {
                        sw.Write("\"\",");
                    }

                    // 总体投资收益
                    sw.Write("\"" + textBoxTotalInvestmentIncome.Text + "\",");

                    // 总体盈亏比例
                    sw.WriteLine("\"" + textBoxTotalProfitAndLossRatio.Text + "\"");

                    // 显示成功信息
                    MessageBoxPlus.Show(this, "记账成功!", "祝贺", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBoxPlus.Show(this, ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // 查看
        private void buttonView_Click(object sender, RoutedEventArgs e)
        {
            if (System.IO.File.Exists(csvFilePath)) Splash.Diagnostics.Process.ShellExecute(csvFilePath);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {   // 读取配置文件信息
            if (Config.Read(iniFilePath))
            {
                textBoxCommissionRate.Text = Config.CommissionRate.ToString();  // 券商佣金比率
                textBoxStampDutyRate.Text = Config.StampDutyRate.ToString();    // 印花税税率
                textBoxTransferFeeRate.Text = Config.TransferFeeRate.ToString();            // 过户费费率
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {   // 保存到配置文件
            Config.Save(iniFilePath);
        }

        // 清空Panel容器内所有的TextBox控件
        private static void ClearTextBoxInPanel(Panel panel)
        {
            foreach (UIElement item in panel.Children)
            {
                if (item is TextBox)
                {
                    (item as TextBox).Clear();
                }
                else if (item is Panel)
                {
                    ClearTextBoxInPanel(item as Panel);
                }
            }
        }

        private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {   // 按“ESC”进入最小化状态
            if (e.Key.Equals(System.Windows.Input.Key.Escape)) this.WindowState = System.Windows.WindowState.Minimized;
        }

        private void Window_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {   // 按鼠标右键进入最小化状态
            if (e.RightButton == System.Windows.Input.MouseButtonState.Pressed) this.WindowState = System.Windows.WindowState.Minimized;
        }

        private void textBoxTradeVolumeState_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (isHasOutput)
            {
                String StockPurchaseCost = String.Empty;
                if ((Boolean)checkBoxStockPurchaseCost.IsChecked)
                {   // 备份股票买入成本
                    StockPurchaseCost = textBoxStockPurchaseCost.Text;
                }

                ClearTextBoxInPanel(groupBoxOutput.Content as Panel);   // 清空计算结果组合框内的文本框
                textBoxStockCode.Clear();   // 清空股票代码文本框
                textBoxStockName.Clear();   // 清空股票名称文本框
                isHasOutput = false;

                if ((Boolean)checkBoxStockPurchaseCost.IsChecked)
                {   // 恢复股票买入成本
                    textBoxStockPurchaseCost.Text = StockPurchaseCost;
                }
            }
        }

        private void checkBoxStockPurchaseCost_Click(object sender, RoutedEventArgs e)
        {
            isHasOutput = false;    // 未生成计算结果

            // 清空文本框内容
            ClearTextBoxInPanel(groupBoxStockTradeVolume.Content as Panel);
            ClearTextBoxInPanel(groupBoxOutput.Content as Panel);

            if ((Boolean)checkBoxStockPurchaseCost.IsChecked)
            {   // 股票买入数量文本框失效,禁止用户输入
                textBoxNumberOfSharesBought.IsEnabled = false;
                textBoxNumberOfSharesBought.Background = new SolidColorBrush(Colors.Black);

                // 股票买入价格文本框失效,禁止用户输入
                textBoxStockPurchasePrice.IsEnabled = false;
                textBoxStockPurchasePrice.Background = new SolidColorBrush(Colors.Black);

                // 同买入数量检测框失效
                checkBoxSame.IsEnabled = false;

                // 股票卖出数量文本框允许用户输入
                textBoxStockAskSize.IsReadOnly = false;

                // 买入成本文本框允许用户输入
                textBoxStockPurchaseCost.IsReadOnly = false;
                textBoxStockPurchaseCost.Focus();
            }
            else
            {   // 股票买入数量文本框生效,允许用户输入
                textBoxNumberOfSharesBought.IsEnabled = true;
                textBoxNumberOfSharesBought.Background = new SolidColorBrush(Colors.White);
                textBoxNumberOfSharesBought.Focus();

                // 股票买入价格文本框生效,允许用户输入
                textBoxStockPurchasePrice.IsEnabled = true;
                textBoxStockPurchasePrice.Background = new SolidColorBrush(Colors.White);

                // 同买入数量检测框生效
                checkBoxSame.IsEnabled = true;
                if((Boolean)checkBoxSame.IsChecked)
                    textBoxStockAskSize.IsReadOnly = true;
                else
                    textBoxStockAskSize.IsReadOnly = false;

                // 买入成本文本框失效,禁止用户输入
                textBoxStockPurchaseCost.IsReadOnly = true;
            }
        }

        private void textBoxStockPurchaseCost_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (isHasOutput) isHasOutput = false;
        }
    }

    /// <summary>
    /// 配置文件
    /// </summary>
    public class StockReturnConfig
    {
        /// <summary>
        /// LINQ 读写 ini 文件
        /// </summary>
        internal LINQToINI iniFile;

        /// <summary>
        /// 券商佣金比率
        /// </summary>
        public Double CommissionRate = 0.075;

        /// <summary>
        /// 印花税税率
        /// </summary>
        public Double StampDutyRate = 0.1;

        /// <summary>
        /// 过户费费率
        /// </summary>
        public Double TransferFeeRate = 0.6;

        /// <summary>
        /// 记账字符集编码,默认为UTF-8
        /// </summary>
        public Int32 CodePage = 65001;

        /// <summary>
        /// 是否需要更新配置文件
        /// </summary>
        public Boolean isUpdateNeeded = false;

        // 读取配置文件
        public Boolean Read(String iniFileName)
        {
            iniFile = new LINQToINI();
            if (!iniFile.Load(iniFileName))
            {
                isUpdateNeeded = true;  // 需要恢复配置文件
                return false;
            }

            // 券商佣金比率
            String[] ResultSet = iniFile.GetProfileString("TAX", "CommissionRate");
            if (ResultSet != null && ResultSet.Length == 1) Double.TryParse(ResultSet[0], out CommissionRate);

            // 印花税税率
            ResultSet = iniFile.GetProfileString("TAX", "StampDutyRate");
            if (ResultSet != null && ResultSet.Length == 1) Double.TryParse(ResultSet[0], out StampDutyRate);

            // 过户费费率
            ResultSet = iniFile.GetProfileString("TAX", "TransferFeeRate");
            if (ResultSet != null && ResultSet.Length == 1) Double.TryParse(ResultSet[0], out TransferFeeRate);

            // 记账字符集编码,默认采用UTF-8
            CodePage = iniFile.GetProfileInt("ACCOUNT", "CodePage", 65001);

            return true;
        }

        // 更新配置文件
        public Boolean Save(String iniFileName)
        {
            if (!isUpdateNeeded) return true;

            iniFile.WriteProfileString("TAX", "CommissionRate", CommissionRate.ToString());
            iniFile.WriteProfileString("TAX", "StampDutyRate", StampDutyRate.ToString());
            iniFile.WriteProfileString("TAX", "TransferFeeRate", TransferFeeRate.ToString());
            return iniFile.Save(iniFileName);
        }
    }
}


Comments are closed.