Passed
Push — master ( c50ccd...85bfe7 )
by Alec
03:31
created

VolumeCounter::trim()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 6
nc 5
nop 1
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 6
rs 9.2222
c 0
b 0
f 0
1
<?php
2
/**
3
 * User: alec
4
 * Date: 19.11.18
5
 * Time: 17:27
6
 */
7
declare(strict_types=1);
8
9
namespace AlecRabbit\Counters;
10
11
use AlecRabbit\Structures\Trade;
12
13
class VolumeCounter extends EventsCounter
14
{
15
    protected const DOMAINS = [
16
        STR_TOTAL,
17
        STR_SELL,
18
        STR_BUY,
19
        STR_VP_TOTAL,
20
        STR_VP_SELL,
21
        STR_VP_BUY,
22
        STR_P_SUM_TOTAL,
23
        STR_P_SUM_SELL,
24
        STR_P_SUM_BUY,
25
    ];
26
27
    /** @var array */
28
    protected $volumes = [];
29
30 3
    public function addTrade(Trade $trade): void
31
    {
32 3
        $baseTimes = $this->getBaseTimes($trade->timestamp);
33 3
        $volumePrice = $trade->amount * $trade->price;
34 3
        foreach ($baseTimes as $period => $timestamp) {
35 3
            $this->processPart(STR_TOTAL, $period, $timestamp, $volumePrice, $trade);
36 3
            $this->processPart(
37 3
                $trade->side === T_SELL ? STR_SELL : STR_BUY,
38 3
                $period,
39 3
                $timestamp,
40 3
                $volumePrice,
41 3
                $trade
42
            );
43 3
            $this->trim($period);
44
        }
45 3
    }
46
47
    /**
48
     * @param string $subdomain
49
     * @param int $period
50
     * @param int $timestamp
51
     * @param float $volumePrice
52
     * @param Trade $trade
53
     */
54 3
    protected function processPart(
55
        string $subdomain,
56
        int $period,
57
        int $timestamp,
58
        float $volumePrice,
59
        Trade $trade
60
    ): void {
61 3
        $this->volumes[STR_VP . $subdomain][$period][$timestamp] =
62 3
            $this->volumes[STR_VP . $subdomain][$period][$timestamp] ?? 0;
63 3
        $this->volumes[STR_VP . $subdomain][$period][$timestamp] += $volumePrice;
64
65 3
        $this->volumes[STR_P_SUM . $subdomain][$period][$timestamp] =
66 3
            $this->volumes[STR_P_SUM . $subdomain][$period][$timestamp] ?? 0;
67 3
        $this->volumes[STR_P_SUM . $subdomain][$period][$timestamp] += $trade->price;
68
69 3
        $this->volumes[$subdomain][$period][$timestamp] = $this->volumes[$subdomain][$period][$timestamp] ?? 0;
70 3
        $this->volumes[$subdomain][$period][$timestamp] += $trade->amount;
71
72 3
        $this->data[$subdomain][$period][$timestamp] = $this->data[$subdomain][$period][$timestamp] ?? 0;
73 3
        $this->data[$subdomain][$period][$timestamp]++;
74 3
    }
75
76
    /**
77
     * @param int $period
78
     */
79 3
    protected function trim(int $period): void
80
    {
81 3
        $threshold = $this->getThreshold($period);
82 3
        foreach (static::DOMAINS as $domain) {
83 3
            if (null !== ($key = array_key_first($this->data[$domain][$period] ?? [])) && ($key <= $threshold)) {
84 2
                unset($this->data[$domain][$period][$key]);
85
            }
86 3
            if (null !== ($key = array_key_first($this->volumes[$domain][$period] ?? [])) && ($key <= $threshold)) {
87 3
                unset($this->volumes[$domain][$period][$key]);
88
            }
89
        }
90 3
    }
91
92
    /**
93
     * @param bool|null $reset
94
     * @return array
95
     */
96 4
    public function getVolumeArray(?bool $reset = null): array
97
    {
98 4
        $volumes = [];
99 4
        foreach (static::DOMAINS as $domain) {
100 4
            foreach ($this->periods as $period => $groupBy) {
101 4
                if (0 < ($sum = array_sum($this->volumes[$domain][$period] ?? []))) {
102 4
                    $volumes[$domain][$period] = $sum;
103
                }
104
            }
105
        }
106 4
        $events = $this->getEventsArray();
107 4
        $averages = [];
108 4
        foreach ($this->periods as $period => $groupBy) {
109 4
            if (isset($volumes[STR_VP_TOTAL][$period], $volumes[STR_TOTAL][$period])) {
110 3
                $averages[STR_VWAP_TOTAL][$period] = $volumes[STR_VP_TOTAL][$period] / $volumes[STR_TOTAL][$period];
111
            }
112 4
            if (isset($volumes[STR_VP_SELL][$period], $volumes[STR_SELL][$period])) {
113 3
                $averages[STR_VWAP_SELL][$period] = $volumes[STR_VP_SELL][$period] / $volumes[STR_SELL][$period];
114
            }
115 4
            if (isset($volumes[STR_VP_BUY][$period], $volumes[STR_BUY][$period])) {
116 3
                $averages[STR_VWAP_BUY][$period] = $volumes[STR_VP_BUY][$period] / $volumes[STR_BUY][$period];
117
            }
118 4
            if (isset($volumes[STR_P_SUM_TOTAL][$period], $events[STR_TOTAL][$period])) {
119 3
                $averages[STR_AVG_PRICE_TOTAL][$period] =
120 3
                    $volumes[STR_P_SUM_TOTAL][$period] / $events[STR_TOTAL][$period];
121
            }
122 4
            if (isset($volumes[STR_P_SUM_SELL][$period], $events[STR_SELL][$period])) {
123 3
                $averages[STR_AVG_PRICE_SELL][$period] =
124 3
                    $volumes[STR_P_SUM_SELL][$period] / $events[STR_SELL][$period];
125
            }
126 4
            if (isset($volumes[STR_P_SUM_BUY][$period], $events[STR_BUY][$period])) {
127 3
                $averages[STR_AVG_PRICE_BUY][$period] =
128 4
                    $volumes[STR_P_SUM_BUY][$period] / $events[STR_BUY][$period];
129
            }
130
        }
131 4
        if ($reset) {
132 1
            $this->reset();
133
        }
134
        return [
135 4
            STR_VOLUMES => $volumes,
136 4
            STR_AVERAGES => $averages,
137 4
            STR_EVENTS => $events
138
        ];
139
    }
140
141
    /**
142
     * @inheritDoc
143
     */
144 4
    public function getEventsArray(?bool $reset = null): array
145
    {
146 4
        $events = [];
147 4
        foreach (static::DOMAINS as $domain) {
148 4
            foreach ($this->periods as $period => $groupBy) {
149 4
                if (0 < ($sum = array_sum($this->data[$domain][$period] ?? []))) {
150 4
                    $events[$domain][$period] = $sum;
151
                }
152
            }
153
        }
154 4
        if ($reset) {
155 1
            $this->reset();
156
        }
157 4
        return $events;
158
    }
159
160
    /**
161
     * @inheritDoc
162
     */
163 2
    protected function reset(): void
164
    {
165 2
        $this->data = [];
166 2
        $this->volumes = [];
167 2
    }
168
169
    /** @return array */
170 3
    public function getRawData(): array
171
    {
172
        return
173
            [
174 3
                STR_VOLUMES => $this->volumes,
175 3
                STR_EVENTS => parent::getRawData(),
176
            ];
177
    }
178
}
179