Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmojiwat committed Oct 19, 2020
0 parents commit 86535f3
Show file tree
Hide file tree
Showing 73 changed files with 3,692 additions and 0 deletions.
432 changes: 432 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Bursa Position Calculator

Bursa Position Calculator helps you to find your position size based on your Entry Price and Stop Loss Price and Target Price.

This app only supports buying long and does not support selling short.

## Left Column

The left column has the usual input fields to help you calculate your position sizes.

## Right Column

You usually don't need to change any values in the right column input fields. But you can change the values to see how it affects values on the left columns.

The list below shows which left column input fields are affected when any right column input fields are changed.

Account Risk -> Risk

Lots -> Stop Loss Price

Stop Loss % -> Stop Loss Price

Stop Loss Ticks -> Stop Loss Price

Stop Loss % -> Target Price

Stop Loss Ticks -> Target Price

## Increment & Decrement Input Values

For Entry Price, Stop Loss Price and Target Price, you can use the <kbd>↑</kbd> and <kbd>↓</kbd> to increment the price based on tick size.

Tick size depends on the amount and is listed in Bursa Malaysia website.

## Visual Feedback

Any input field that changes will flash in blue.

Invalid inputs and erroneous values are shown in red.

## Navigation

<kbd>→</kbd> Next input field

<kbd>shift →</kbd> Previous input field

<kbd>alt [hotkey char]</kbd> Sets focus to the input field with underlined [hotkey char]

1 change: 1 addition & 0 deletions src/.idea/.idea.BursaCalculator/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/.idea/.idea.BursaCalculator/.idea/indexLayout.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/.idea/.idea.BursaCalculator/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions src/BursaCalculator.Core.Tests/BrokerageFeeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;
using static BursaCalculator.Core.BrokerageFeeExtensions;
using static BursaCalculator.Core.Infrastructure.PercentExtensions;

namespace BursaCalculator.Core.Tests
{
public class BrokerageFeeTest
{
[Theory]
[InlineData(500, 3.5)]
public void CalculateBrokerageFee_returns_expexted_result(decimal amount, decimal expectedResult)
{
var percentageRates = new List<BrokeragePercentageRate>
{
new BrokeragePercentageRate(0, Percent(0.7m)),
new BrokeragePercentageRate(100_000, Percent(0.5m)),
new BrokeragePercentageRate(500_000, Percent(0.4m)),
new BrokeragePercentageRate(1_000_000, Percent(0.3m)),
}
.OrderBy(r => r.AmountFrom);

var rate = new BrokerageFeeRate(percentageRates, Percent(0), 12, Percent(0));

var result = CalculateBrokerageFee(rate, amount);

result.Should().Be(expectedResult);
}
}
}
39 changes: 39 additions & 0 deletions src/BursaCalculator.Core.Tests/BursaCalculator.Core.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.14.0" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.14.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.14.0" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="FluentAssertions.Analyzers" Version="0.11.4" />
<PackageReference Include="LanguageExt.Core" Version="3.4.15" />
<PackageReference Include="LanguageExt.UnitTesting" Version="3.3.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="NSubstitute" Version="4.2.2" />
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.13" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BursaCalculator.Core\BursaCalculator.Core.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Remove="CalculatorTest.cs" />
</ItemGroup>

</Project>
163 changes: 163 additions & 0 deletions src/BursaCalculator.Core.Tests/CalculatorTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System;
using AutoFixture;
using AutoFixture.Xunit2;
using BursaCalculator.Core.Infrastructure;
using FluentAssertions;
using Xunit;
using static BursaCalculator.Core.Infrastructure.PercentExtensions;

namespace BursaCalculator.Core.Tests
{
public class CalculatorTest
{
[Theory, CalculatorAutoData]
public void Calculate_returns_expected_result(BrokerageFeeRate brokerageFeeRate,
ClearingFeeRate clearingFeeRate,
StampDutyRate stampDutyRate, SalesServiceTaxRate salesServiceTaxRate)
{
var sut = new Calculator(brokerageFeeRate, clearingFeeRate, stampDutyRate, salesServiceTaxRate);

var result = sut.Calculate(1, Lot(1), 1.5m);

result.Profit.Should().Be(50);
}


[Theory, CalculatorAutoData]
public void CalculateBrokerageFee_with_1000_returns_expected_result(BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions.CalculateBrokerageFee);

var result = sut(brokerageFeeRate, 10);

result.Should().Be(12m);
}

[Theory, CalculatorAutoData]
public void CalculateBrokerageFee_with_equal_100000_returns_expected_result(BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions.CalculateBrokerageFee);

var result = sut(brokerageFeeRate, 100_000);

result.Should().Be(420m);
}

[Theory, CalculatorAutoData]
public void CalculateBrokerageFee_with_equal_150000_returns_expected_result(BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions.CalculateBrokerageFee);

var result = sut(brokerageFeeRate, 150_000);

result.Should().Be(315m);
}

[Theory, CalculatorAutoData]
public void CalculateBrokeragePercentageFee_with_1000_returns_expected_result(BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions
.CalculateBrokeragePercentageFee);

var result = sut(brokerageFeeRate, 1_000);

result.Should().Be(4.2m);
}

[Theory, CalculatorAutoData]
public void CalculateBrokeragePercentageFee_with_100000_returns_expected_result(
BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions
.CalculateBrokeragePercentageFee);

var result = sut(brokerageFeeRate, 100_000);

result.Should().Be(420m);
}

[Theory, CalculatorAutoData]
public void CalculateBrokeragePercentageFee_with_150000_returns_expected_result(
BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions
.CalculateBrokeragePercentageFee);

var result = sut(brokerageFeeRate, 150_000);

result.Should().Be(315m);
}

[Theory, CalculatorAutoData]
public void CalculateOnlineTradingRebate_returns_expected_result(BrokerageFeeRate brokerageFeeRate)
{
var sut = new Func<BrokerageFeeRate, decimal, decimal>(BrokerageFeeExtensions.CalculateOnlineTradingRebate);

var result = sut(brokerageFeeRate, 10);

result.Should().Be(0);
}

[Theory, CalculatorAutoData]
public void CalculateStampDuty_with_1000_returns_expected_result(StampDutyRate stampDutyRate)
{
var sut = new Func<StampDutyRate, decimal, decimal>(StampDutyExtensions.CalculateStampDuty);

var result = sut(stampDutyRate, 1_000);

result.Should().Be(1);
}

[Theory, CalculatorAutoData]
public void CalculateStampDuty_with_1001_returns_expected_result(StampDutyRate stampDutyRate)
{
var sut = new Func<StampDutyRate, decimal, decimal>(StampDutyExtensions.CalculateStampDuty);

var result = sut(stampDutyRate, 1_001);

result.Should().Be(2);
}

[Theory, CalculatorAutoData]
public void CalculateStampDuty_with_500_returns_expected_result(StampDutyRate stampDutyRate)
{
var sut = new Func<StampDutyRate, decimal, decimal>(StampDutyExtensions.CalculateStampDuty);

var result = sut(stampDutyRate, 500);

result.Should().Be(1);
}

private class CalculatorAutoDataAttribute : AutoDataAttribute
{
public CalculatorAutoDataAttribute() : base(() => new Fixture().Customize(new Customization()))
{
}
}

private class Customization : ICustomization
{
public void Customize(IFixture fixture)
{
var brokerageFee = new BrokerageFeeRate(
Percent(0.42m),
new BrokeragePercentageRates(new[]
{
new BrokeragePercentageRate(100_000, Percent(0.21m))
}),
12, Percent(0), Percent(0.15m)
);
fixture.Register(() => brokerageFee);

var clearingFee = new ClearingFeeRate(new Percent(0.03m), 1_000);
fixture.Register(() => clearingFee);

var stampDuty = new StampDutyRate(1, 1_000, 200);
fixture.Register(() => stampDuty);

var salesServiceTax = new SalesServiceTaxRate(Percent(6), Percent(0), Percent(0));
fixture.Register(() => salesServiceTax);
}
}
}
}
21 changes: 21 additions & 0 deletions src/BursaCalculator.Core.Tests/ClearingFeeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using FluentAssertions;
using Xunit;
using static BursaCalculator.Core.Infrastructure.PercentExtensions;

namespace BursaCalculator.Core.Tests
{
public class ClearingFeeTest
{
[Theory]
[InlineData(500, 0.15)]
[InlineData(1_200, 0.36)]
public void CalculateClearingFee_returns_expexted_result(decimal amount, decimal expectedResult)
{
var rate = new ClearingFeeRate(Percent(0.03m), 1_000m);

var result = ClearingFeeExtensions.ClearingFee(rate, amount);

result.Should().Be(expectedResult);
}
}
}
Loading

0 comments on commit 86535f3

Please sign in to comment.