Skip to content

Commit

Permalink
Price calculation refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
simba77 committed Aug 22, 2024
1 parent 0dbd102 commit a7ab652
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 76 deletions.
103 changes: 27 additions & 76 deletions src/Services/Deals/DealData.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@

use App\Entity\Account;
use App\Entity\Deal;
use App\Services\Deals\Strategy\BondStrategy;
use App\Services\Deals\Strategy\DealStrategyInterface;
use App\Services\Deals\Strategy\FutureStrategy;
use App\Services\Deals\Strategy\ShareStrategy;
use App\Services\MarketData\Currencies\CurrencyService;
use App\Services\MarketData\Securities\SecurityTypeEnum;

class DealData
{
private DealStrategyInterface $strategy;

/** @param array{
* deal: Deal,
* shareName?: string,
Expand All @@ -35,6 +41,18 @@ public function __construct(
private readonly Account $account,
private readonly CurrencyService $currencyService,
) {
if ($this->deal['futureName']) {
$this->setStrategy(new FutureStrategy($this->deal, $this->account));
} elseif ($this->deal['bondName']) {
$this->setStrategy(new BondStrategy($this->deal, $this->account));
} else {
$this->setStrategy(new ShareStrategy($this->deal, $this->account));
}
}

public function setStrategy(DealStrategyInterface $strategy): void
{
$this->strategy = $strategy;
}

public function getId(): int
Expand All @@ -49,7 +67,7 @@ public function getAccountId(): int

public function getName(): string
{
return $this->deal['shareName'] ?? $this->deal['bondName'] ?? $this->deal['futureName'] ?? '';
return $this->strategy->getName();
}

public function getTicker(): string
Expand All @@ -59,32 +77,12 @@ public function getTicker(): string

public function getSecurityType(): SecurityTypeEnum
{
if ($this->deal['futureName']) {
return SecurityTypeEnum::Future;
}
if ($this->deal['bondName']) {
return SecurityTypeEnum::Bond;
}
return SecurityTypeEnum::Share;
return $this->strategy->getSecurityType();
}

public function getBuyPrice(): string
{
// Futures price
if ($this->deal['futureName']) {
if($this->deal['deal']->getBuyPrice() > $this->deal['futureLotSize']) {
return bcmul($this->deal['deal']->getBuyPrice(), $this->deal['futureStepPrice'], 4);
}

return bcmul(bcmul($this->deal['deal']->getBuyPrice(), $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

// Bond price
if ($this->deal['bondName']) {
return bcdiv(bcmul($this->deal['deal']->getBuyPrice(), $this->deal['bondLotSize'], 4), '100', 4);
}

return $this->deal['deal']->getBuyPrice();
return $this->strategy->getBuyPrice();
}

public function getQuantity(): int
Expand All @@ -99,20 +97,7 @@ public function getFullBuyPrice(): string

public function getSellPrice(): string
{
// Futures price
if ($this->deal['futureName']) {
if($this->deal['deal']->getSellPrice() > $this->deal['futureLotSize']) {
return bcmul($this->deal['deal']->getSellPrice(), $this->deal['futureLotSize'], 4);
}
return bcmul(bcmul($this->deal['deal']->getSellPrice(), $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

// Bond price
if ($this->deal['bondName']) {
return bcdiv(bcmul($this->deal['deal']->getSellPrice(), $this->deal['bondLotSize'], 4), '100', 4);
}

return $this->deal['deal']->getSellPrice();
return $this->strategy->getSellPrice();
}

public function getFullSellPrice(): string
Expand All @@ -122,35 +107,12 @@ public function getFullSellPrice(): string

public function getCurrentPrice(): string
{
if ($this->deal['futurePrice']) {
if ($this->deal['futurePrice'] > $this->deal['futureLotSize']) {
return bcmul($this->deal['futurePrice'], $this->deal['futureStepPrice'], 4);
}
return bcmul(bcmul($this->deal['futurePrice'], $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

if ($this->deal['bondPrice']) {
return bcdiv(bcmul($this->deal['bondPrice'], $this->deal['bondLotSize'], 4), '100', 4);
}

return $this->deal['sharePrice'] ?? $this->deal['bondPrice'] ?? '0';
return $this->strategy->getCurrentPrice();
}

public function getPrevPrice(): string
{
if ($this->deal['futurePrevPrice']) {
if ($this->deal['futurePrevPrice'] > $this->deal['futureLotSize']) {
return bcmul($this->deal['futurePrevPrice'], $this->deal['futureStepPrice'], 4);
}

return bcmul(bcmul($this->deal['futurePrevPrice'], $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

if ($this->deal['bondPrevPrice']) {
return bcdiv(bcmul($this->deal['bondPrevPrice'], $this->deal['bondLotSize'], 4), '100', 4);
}

return $this->deal['sharePrevPrice'] ?? $this->deal['bondPrevPrice'] ?? '0';
return $this->strategy->getPrevPrice();
}

public function getFullCurrentPrice(): string
Expand Down Expand Up @@ -193,16 +155,7 @@ public function getFullTargetPrice(): string

public function getCommission(): string
{
if (! empty($this->deal['futurePrice'])) {
// TODO: Change commission
return bcmul('5', (string) $this->getQuantity(), 4);
}
if (! empty($this->deal['bondPrice'])) {
// TODO: Change commission
return bcmul('0.5', (string) $this->getQuantity(), 4);
}

return bcmul($this->getFullCurrentPrice(), bcdiv($this->account->getCommission(), '100', 4), 4);
return $this->strategy->getCommission($this->getFullCurrentPrice(), (string) $this->getQuantity());
}

public function getProfit(): string
Expand Down Expand Up @@ -259,14 +212,12 @@ public function getTargetProfitPercent(): string

public function getCurrency(): string
{
return $this->deal['shareCurrency'] ?? $this->deal['bondCurrency'] ?? $this->deal['futureCurrency'] ?? 'RUB';
return $this->strategy->getCurrency();
}

public function getCurrencyName(): string
{
$currency = $this->deal['shareCurrency'] ?? $this->deal['bondCurrency'] ?? $this->deal['futureCurrency'] ?? 'RUB';

if ($currency === 'RUB') {
if ($this->getCurrency() === 'RUB') {
return '';
}
return '$';
Expand Down
55 changes: 55 additions & 0 deletions src/Services/Deals/Strategy/BondStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace App\Services\Deals\Strategy;

use App\Entity\Account;
use App\Services\MarketData\Securities\SecurityTypeEnum;

class BondStrategy implements DealStrategyInterface
{
public function __construct(private readonly array $deal, Account $account)
{
}

public function getName(): string
{
return $this->deal['bondName'];
}

public function getSecurityType(): SecurityTypeEnum
{
return SecurityTypeEnum::Bond;
}

public function getBuyPrice(): string
{
return bcdiv(bcmul($this->deal['deal']->getBuyPrice(), $this->deal['bondLotSize'], 4), '100', 4);
}

public function getSellPrice(): string
{
return bcdiv(bcmul($this->deal['deal']->getSellPrice(), $this->deal['bondLotSize'], 4), '100', 4);
}

public function getCurrentPrice(): string
{
return bcdiv(bcmul($this->deal['bondPrice'], $this->deal['bondLotSize'], 4), '100', 4);
}

public function getPrevPrice(): string
{
return bcdiv(bcmul($this->deal['bondPrevPrice'], $this->deal['bondLotSize'], 4), '100', 4);
}

public function getCommission(string $price, string $quantity): string
{
return bcmul('0.5', $quantity, 4);
}

public function getCurrency(): string
{
return $this->deal['bondCurrency'] ?? 'RUB';
}
}
49 changes: 49 additions & 0 deletions src/Services/Deals/Strategy/DealStrategyInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace App\Services\Deals\Strategy;

use App\Entity\Account;
use App\Entity\Deal;
use App\Services\MarketData\Securities\SecurityTypeEnum;

interface DealStrategyInterface
{
/** @param array{
* deal: Deal,
* shareName?: string,
* bondName?: string,
* futureName?: string,
* sharePrice?: string,
* sharePrevPrice?: string,
* bondPrice?: string,
* bondPrevPrice?: string,
* bondLotSize?: string,
* futurePrice?: string,
* futurePrevPrice?: string,
* futureStepPrice?: string,
* futureLotSize?: string,
* shareCurrency?: string,
* futureCurrency?: string,
* bondCurrency?: string,
* } $deal
*/
public function __construct(array $deal, Account $account);

public function getName(): string;

public function getSecurityType(): SecurityTypeEnum;

public function getBuyPrice(): string;

public function getSellPrice(): string;

public function getCurrentPrice(): string;

public function getPrevPrice(): string;

public function getCommission(string $price, string $quantity): string;

public function getCurrency(): string;
}
72 changes: 72 additions & 0 deletions src/Services/Deals/Strategy/FutureStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace App\Services\Deals\Strategy;

use App\Entity\Account;
use App\Services\MarketData\Securities\SecurityTypeEnum;

class FutureStrategy implements DealStrategyInterface
{
/**
* @inheritDoc
*/
public function __construct(private readonly array $deal, Account $account)
{
}

public function getName(): string
{
return $this->deal['futureName'];
}

public function getSecurityType(): SecurityTypeEnum
{
return SecurityTypeEnum::Future;
}

public function getBuyPrice(): string
{
if ($this->deal['deal']->getBuyPrice() > $this->deal['futureLotSize']) {
return bcmul($this->deal['deal']->getBuyPrice(), $this->deal['futureStepPrice'], 4);
}

return bcmul(bcmul($this->deal['deal']->getBuyPrice(), $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

public function getSellPrice(): string
{
if ($this->deal['deal']->getSellPrice() > $this->deal['futureLotSize']) {
return bcmul($this->deal['deal']->getSellPrice(), $this->deal['futureLotSize'], 4);
}
return bcmul(bcmul($this->deal['deal']->getSellPrice(), $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

public function getCurrentPrice(): string
{
if ($this->deal['futurePrice'] > $this->deal['futureLotSize']) {
return bcmul($this->deal['futurePrice'], $this->deal['futureStepPrice'], 4);
}
return bcmul(bcmul($this->deal['futurePrice'], $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

public function getPrevPrice(): string
{
if ($this->deal['futurePrevPrice'] > $this->deal['futureLotSize']) {
return bcmul($this->deal['futurePrevPrice'], $this->deal['futureStepPrice'], 4);
}

return bcmul(bcmul($this->deal['futurePrevPrice'], $this->deal['futureStepPrice'], 4), $this->deal['futureLotSize'], 4);
}

public function getCommission(string $price, string $quantity): string
{
return bcmul('5', $quantity, 4);
}

public function getCurrency(): string
{
return $this->deal['futureCurrency'] ?? 'RUB';
}
}
Loading

0 comments on commit a7ab652

Please sign in to comment.