Skip to content

Commit

Permalink
Adds minor refactorings
Browse files Browse the repository at this point in the history
  • Loading branch information
jensscherbl committed Aug 9, 2024
1 parent ee7e62f commit 8d96a6f
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 133 deletions.
12 changes: 6 additions & 6 deletions src/Candle/Candle.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,32 @@ public function __construct(
) {
if ($open->isNegative()) {
throw new DomainException(
'Invalid open price. Open price must not be negative.'
message: 'Invalid open price. Open price must not be negative.'
);
}
if ($high->isNegative()) {
throw new DomainException(
'Invalid high price. High price must not be negative.'
message: 'Invalid high price. High price must not be negative.'
);
}
if ($low->isNegative()) {
throw new DomainException(
'Invalid low price. Low price must not be negative.'
message: 'Invalid low price. Low price must not be negative.'
);
}
if ($high->isLessThan($low)) {
throw new DomainException(
'Invalid high- and low price. High price must not be lower than low price.'
message: 'Invalid high- and low price. High price must not be lower than low price.'
);
}
if ($close->isNegative()) {
throw new DomainException(
'Invalid close price. Close price must not be negative.'
message: 'Invalid close price. Close price must not be negative.'
);
}
if ($volume->isNegative()) {
throw new DomainException(
'Invalid volume. Volume must not be negative.'
message: 'Invalid volume. Volume must not be negative.'
);
}
}
Expand Down
48 changes: 24 additions & 24 deletions src/Candle/CandleFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,57 @@ public static function create(
string $volume,
Candle|null $previous,
): Candle {
$open = new Number($open);
$high = new Number($high);
$low = new Number($low);
$close = new Number($close);
$volume = new Number($volume);
$highLow = $high->minus($low);
$open = new Number(value: $open);
$high = new Number(value: $high);
$low = new Number(value: $low);
$close = new Number(value: $close);
$volume = new Number(value: $volume);
$highLow = $high->minus(value: $low);
$TR = $highLow;
$DMp = new Number(0);
$DMm = new Number(0);
$DMp = new Number(value: 0);
$DMm = new Number(value: 0);

if ($previous !== null) {

/*
* Calculates true range (TR).
*/

$highClose = $high->minus($previous->close);
$highClose = $high->minus(value: $previous->close);
$absHighClose = $highClose->abs();
$lowClose = $low->minus($previous->close);
$lowClose = $low->minus(value: $previous->close);
$absLowClose = $lowClose->abs();

if ($absHighClose->isGreaterThan($TR)) {
if ($absHighClose->isGreaterThan(value: $TR)) {
$TR = $absHighClose;
}
if ($absLowClose->isGreaterThan($TR)) {
if ($absLowClose->isGreaterThan(value: $TR)) {
$TR = $absLowClose;
}

/*
* Calculates directional movements (+DM & -DM).
*/

$upMove = $high->minus($previous->high);
$downMove = $previous->low->minus($low);
$upMove = $high->minus(value: $previous->high);
$downMove = $previous->low->minus(value: $low);

if ($upMove->isPositive() && $upMove->isGreaterThan($downMove)) {
if ($upMove->isPositive() && $upMove->isGreaterThan(value: $downMove)) {
$DMp = $upMove;
}
if ($downMove->isPositive() && $downMove->isGreaterThan($upMove)) {
if ($downMove->isPositive() && $downMove->isGreaterThan(value: $upMove)) {
$DMm = $downMove;
}
}
return new Candle(
$open,
$high,
$low,
$close,
$volume,
$TR,
$DMp,
$DMm,
open: $open,
high: $high,
low: $low,
close: $close,
volume: $volume,
TR: $TR,
DMp: $DMp,
DMm: $DMm,
);
}
}
74 changes: 37 additions & 37 deletions src/Chart/Chart.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

final readonly class Chart implements ChartInterface
{
private const SCALE = 4;
private const int SCALE = 4;

/**
* @param array<string, Candle> $candles
Expand All @@ -27,66 +27,66 @@ public function __construct(

public function getSMA(int $period): array
{
$SMA = $this->SMAFactory::create($period);
$SMA = $this->SMAFactory::create(period: $period);
$result = [];

foreach ($this->candles as $date => $candle) {
$close = $candle->close;
$SMAResult = $SMA->calculate($close);
$result[$date] = $SMAResult?->round(self::SCALE);
$SMAResult = $SMA->calculate(value: $close);
$result[$date] = $SMAResult?->round(scale: self::SCALE);
}
return $result;
}

public function getEMA(int $period): array
{
$EMA = $this->EMAFactory::create($period);
$EMA = $this->EMAFactory::create(period: $period);
$result = [];

foreach ($this->candles as $date => $candle) {
$close = $candle->close;
$EMAResult = $EMA->calculate($close);
$result[$date] = $EMAResult?->round(self::SCALE);
$EMAResult = $EMA->calculate(value: $close);
$result[$date] = $EMAResult?->round(scale: self::SCALE);
}
return $result;
}

public function getDI(int $period): array
{
$DI = $this->DIFactory::create($period);
$DI = $this->DIFactory::create(period: $period);
$result = [];

foreach ($this->candles as $date => $candle) {
$DMp = $candle->DMp;
$DMm = $candle->DMm;
$TR = $candle->TR;
$DIResult = $DI->calculate($DMp, $DMm, $TR);
$DIResult = $DI->calculate(DMp: $DMp, DMm: $DMm, TR: $TR);
$DIpResult = $DIResult->DIp;
$DIpRounded = $DIpResult?->round(self::SCALE);
$DIpRounded = $DIpResult?->round(scale: self::SCALE);
$DImResult = $DIResult->DIm;
$DImRounded = $DImResult?->round(self::SCALE);
$result[$date] = new DI($DIpRounded, $DImRounded);
$DImRounded = $DImResult?->round(scale: self::SCALE);
$result[$date] = new DI(DIp: $DIpRounded, DIm: $DImRounded);
}
return $result;
}

public function getADX(int $period): array
{
$DI = $this->DIFactory::create($period);
$ADX = $this->ADXFactory::create($period);
$DI = $this->DIFactory::create(period: $period);
$ADX = $this->ADXFactory::create(period: $period);
$result = [];

foreach ($this->candles as $date => $candle) {
$DMp = $candle->DMp;
$DMm = $candle->DMm;
$TR = $candle->TR;
$DIResult = $DI->calculate($DMp, $DMm, $TR);
$DIResult = $DI->calculate(DMp: $DMp, DMm: $DMm, TR: $TR);
$DIpResult = $DIResult->DIp;
$DImResult = $DIResult->DIm;

if ($DIpResult !== null && $DImResult !== null) {
$ADXResult = $ADX->calculate($DIpResult, $DImResult);
$result[$date] = $ADXResult?->round(self::SCALE);
$ADXResult = $ADX->calculate(DIp: $DIpResult, DIm: $DImResult);
$result[$date] = $ADXResult?->round(scale: self::SCALE);
} else {
$result[$date] = null;
}
Expand All @@ -96,41 +96,41 @@ public function getADX(int $period): array

public function getTrend(int $SMAPeriod, int $EMAPeriod): array
{
$SMA = $this->SMAFactory::create($SMAPeriod);
$EMA = $this->EMAFactory::create($EMAPeriod);
$DI = $this->DIFactory::create($EMAPeriod);
$ADX = $this->ADXFactory::create($EMAPeriod);
$SMA = $this->SMAFactory::create(period: $SMAPeriod);
$EMA = $this->EMAFactory::create(period: $EMAPeriod);
$DI = $this->DIFactory::create(period: $EMAPeriod);
$ADX = $this->ADXFactory::create(period: $EMAPeriod);
$result = [];

foreach ($this->candles as $date => $candle) {
$close = $candle->close;
$closeRounded = $close->round(self::SCALE);
$SMAResult = $SMA->calculate($close);
$SMARounded = $SMAResult?->round(self::SCALE);
$EMAResult = $EMA->calculate($close);
$EMARounded = $EMAResult?->round(self::SCALE);
$closeRounded = $close->round(scale: self::SCALE);
$SMAResult = $SMA->calculate(value: $close);
$SMARounded = $SMAResult?->round(scale: self::SCALE);
$EMAResult = $EMA->calculate(value: $close);
$EMARounded = $EMAResult?->round(scale: self::SCALE);
$DMp = $candle->DMp;
$DMm = $candle->DMm;
$TR = $candle->TR;
$DIResult = $DI->calculate($DMp, $DMm, $TR);
$DIResult = $DI->calculate(DMp: $DMp, DMm: $DMm, TR: $TR);
$DIpResult = $DIResult->DIp;
$DIpRounded = $DIpResult?->round(self::SCALE);
$DIpRounded = $DIpResult?->round(scale: self::SCALE);
$DImResult = $DIResult->DIm;
$DImRounded = $DImResult?->round(self::SCALE);
$DImRounded = $DImResult?->round(scale: self::SCALE);
$ADXRounded = null;

if ($DIpResult !== null && $DImResult !== null) {
$ADXResult = $ADX->calculate($DIpResult, $DImResult);
$ADXRounded = $ADXResult?->round(self::SCALE);
$ADXResult = $ADX->calculate(DIp: $DIpResult, DIm: $DImResult);
$ADXRounded = $ADXResult?->round(scale: self::SCALE);
}

$result[$date] = new Trend(
$closeRounded,
$SMARounded,
$EMARounded,
$DIpRounded,
$DImRounded,
$ADXRounded,
close: $closeRounded,
SMA: $SMARounded,
EMA: $EMARounded,
DIp: $DIpRounded,
DIm: $DImRounded,
ADX: $ADXRounded,
);
}
return $result;
Expand Down
24 changes: 12 additions & 12 deletions src/Chart/ChartFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
public static function bootstrap(array $data): Chart
{
return (new ChartFactory(
new CandleFactory,
new SMAFactory,
new EMAFactory,
new DIFactory,
new ADXFactory,
))->create($data);
candleFactory: new CandleFactory(),
SMAFactory: new SMAFactory(),
EMAFactory: new EMAFactory(),
DIFactory: new DIFactory(),
ADXFactory: new ADXFactory(),
))->create(data: $data);
}

public function __construct(
Expand All @@ -46,15 +46,15 @@ public function create(array $data): Chart
'close' => $close,
'volume' => $volume,
]) {
$candles[$date] = $this->candleFactory::create($open, $high, $low, $close, $volume, $previous);
$candles[$date] = $this->candleFactory::create(open: $open, high: $high, low: $low, close: $close, volume: $volume, previous: $previous);
$previous = $candles[$date];
}
return new Chart(
$candles,
$this->SMAFactory,
$this->EMAFactory,
$this->DIFactory,
$this->ADXFactory,
candles: $candles,
SMAFactory: $this->SMAFactory,
EMAFactory: $this->EMAFactory,
DIFactory: $this->DIFactory,
ADXFactory: $this->ADXFactory,
);
}
}
10 changes: 5 additions & 5 deletions src/Indicator/ADX/ADX.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ public function calculate(Number $DIp, Number $DIm): Number|null
* Calculates the directional movement index (DI).
*/

$numerator = $DIp->minus($DIm)->abs();
$denominator = $DIp->plus($DIm);
$numerator = $DIp->minus(value: $DIm)->abs();
$denominator = $DIp->plus(value: $DIm);

if ($denominator->isZero()) {
$DX = new Number(0);
$DX = new Number(value: 0);
} else {
$DX = $numerator->dividedBy($denominator)->multipliedBy(100);
$DX = $numerator->dividedBy(value: $denominator)->multipliedBy(value: 100);
}

/*
* Calculates the average directional movement index (ADX).
*/

return $this->WSMA->calculate($DX);
return $this->WSMA->calculate(value: $DX);
}
}
6 changes: 3 additions & 3 deletions src/Indicator/ADX/ADXFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
{
public static function create(int $period): ADXInterface
{
return new ADX(
new WSMA($period),
);
$WSMA = new WSMA(period: $period);

return new ADX(WSMA: $WSMA);
}
}
19 changes: 8 additions & 11 deletions src/Indicator/DI/DI.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ public function calculate(Number $DMp, Number $DMm, Number $TR): DIResult
* of directional movements (+DM & -DM).
*/

$DMpSMA = $this->DMpSMA->calculate($DMp);
$DMmSMA = $this->DMmSMA->calculate($DMm);
$DMpSMA = $this->DMpSMA->calculate(value: $DMp);
$DMmSMA = $this->DMmSMA->calculate(value: $DMm);

/*
* Calculates the average true range (ATR).
*/

$ATR = $this->ATR->calculate($TR);
$ATR = $this->ATR->calculate(value: $TR);
$DIp = null;
$DIm = null;

Expand All @@ -38,16 +38,13 @@ public function calculate(Number $DMp, Number $DMm, Number $TR): DIResult
*/

if ($ATR->isZero()) {
$DIp = new Number(0);
$DIm = new Number(0);
$DIp = new Number(value: 0);
$DIm = new Number(value: 0);
} else {
$DIp = $DMpSMA->dividedBy($ATR)->multipliedBy(100);
$DIm = $DMmSMA->dividedBy($ATR)->multipliedBy(100);
$DIp = $DMpSMA->dividedBy(value: $ATR)->multipliedBy(value: 100);
$DIm = $DMmSMA->dividedBy(value: $ATR)->multipliedBy(value: 100);
}
}
return new DIResult(
$DIp,
$DIm,
);
return new DIResult(DIp: $DIp, DIm: $DIm);
}
}
Loading

0 comments on commit 8d96a6f

Please sign in to comment.