-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 86535f3
Showing
73 changed files
with
3,692 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
6 changes: 6 additions & 0 deletions
6
src/.idea/.idea.BursaCalculator/.idea/projectSettingsUpdater.xml
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
39
src/BursaCalculator.Core.Tests/BursaCalculator.Core.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
Oops, something went wrong.