Skip to content

Commit 5324e0b

Browse files
Added the ability to get ask, bid, and mid.
1 parent 91c87af commit 5324e0b

1 file changed

Lines changed: 187 additions & 0 deletions

File tree

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<?php
2+
3+
namespace DPRMC\InteractiveData;
4+
5+
use DPRMC\CUSIP;
6+
use DPRMC\InteractiveData\RemotePlusClient\Exceptions\UnparsableDateSentToConstructor;
7+
8+
/**
9+
* Class ClientCustomPriceFixedIncome
10+
* @package DPRMC\InteractiveData
11+
*/
12+
class ClientCustomPriceFixedIncome extends RemotePlusClient {
13+
14+
/**
15+
* @var string YYYY-mm-dd The date you want pricing for.
16+
*/
17+
protected $date;
18+
19+
/**
20+
* @var array The list of CUSIP identifiers that you want daily pricing on.
21+
*/
22+
protected $cusips = [];
23+
24+
/**
25+
* @var array A list of all of the CUSIPs passed into the constructor that were not valid CUSIPs.
26+
*/
27+
protected $invalidCusips = [];
28+
29+
30+
protected $pricesRequested = [];
31+
32+
33+
34+
/**
35+
* ClientCustomPriceFixedIncome constructor.
36+
* @param $user
37+
* @param $pass
38+
* @param $date
39+
* @param $cusips
40+
* @param bool $debug
41+
* @throws \Exception
42+
*/
43+
public function __construct( $user, $pass, $date, $cusips, $debug = FALSE ) {
44+
parent::__construct( $user, $pass );
45+
$this->remotePlusDebug = $debug;
46+
$this->date = $this->formatDateForRemotePlus( $date );
47+
$this->cusips = $this->pruneInvalidCusips( $cusips );
48+
$this->generateBodyForRequest();
49+
}
50+
51+
/**
52+
* @return $this
53+
*/
54+
public function addBestPrice(){
55+
$this->pricesRequested[] = 'PRC'; // number 16.7
56+
return $this;
57+
}
58+
59+
/**
60+
* @return $this
61+
*/
62+
public function addBid() {
63+
$this->pricesRequested[] = 'BID'; // number 16.7
64+
return $this;
65+
}
66+
67+
/**
68+
* @return $this
69+
*/
70+
public function addMid() {
71+
$this->pricesRequested[] = 'MID'; // number 16.7
72+
return $this;
73+
}
74+
75+
/**
76+
* @return $this
77+
*/
78+
public function addAsk() {
79+
$this->pricesRequested[] = 'ASK'; // number 16.7
80+
return $this;
81+
}
82+
83+
84+
/**
85+
* The Remote Plus API is particular about how dates are formatted.
86+
*
87+
* @param string $date A string that can be parsed by PHP's strtotime() function.
88+
*
89+
* @return string A date formatted as YYYYMMDD that can be read by Remote Plus.
90+
* @throws \Exception Only thrown if the user passes some garbage into the constructor.
91+
*/
92+
protected function formatDateForRemotePlus( $date ) {
93+
$strTime = strtotime( $date );
94+
if ( $strTime === FALSE ):
95+
throw new UnparsableDateSentToConstructor( "We could not parse the date you sent to the constructor: [" . $date . "]" );
96+
endif;
97+
$date = date( 'Ymd', $strTime );
98+
99+
return $date;
100+
}
101+
102+
/**
103+
* We don't want to waste time (or money) getting prices on identifiers that are not valid cusips.
104+
* Prune out the invalid cusips and save those in the local $invalidCusips property.
105+
*
106+
* @param array $cusips A list of cusips passed in by the user in the constructor.
107+
*
108+
* @return array A list of cusips pruned of any values that aren't valid cusips.
109+
*/
110+
protected function pruneInvalidCusips( $cusips ) {
111+
$validCusips = [];
112+
foreach ( $cusips as $cusip ):
113+
if ( CUSIP::isCUSIP( $cusip ) ):
114+
$validCusips[] = $cusip;
115+
else:
116+
$this->invalidCusips[] = $cusip;
117+
endif;
118+
endforeach;
119+
120+
return $validCusips;
121+
}
122+
123+
/**
124+
* The Remote Plus API requires the request body to be formatted in a very specific way.
125+
* The following body is formatted to pull the prices for a list of CUSIPs from a specific date.
126+
*/
127+
protected function generateBodyForRequest() {
128+
$pricesRequested = $this->getPricesRequested();
129+
130+
$this->requestBody = 'Request=' . urlencode( "GET,(" . implode( ',', $this->cusips ) . "),(" . $pricesRequested . ")," . $this->date ) . "&Done=flag\n";
131+
}
132+
133+
/**
134+
* @return string
135+
* @throws \Exception
136+
*/
137+
protected function getPricesRequested() {
138+
if ( empty( $pricesRequested ) ):
139+
throw new \Exception( "You have to add at least one price for this request." );
140+
endif;
141+
142+
return implode( ',', $pricesRequested );
143+
}
144+
145+
/**
146+
* @return array
147+
*/
148+
protected function processResponse() {
149+
$body = $this->getBodyFromResponse();
150+
$prices = explode( "\n", $body );
151+
$prices = array_map( 'trim', $prices );
152+
$prices = array_filter( $prices );
153+
array_pop( $prices ); // Remove the CRC check.
154+
155+
$return = [];
156+
foreach ( $this->cusips as $i => $cusip ):
157+
$return[ $cusip ] = $this->formatValueReturnedFromInteractiveData( $prices[ $i ] );
158+
endforeach;
159+
160+
return $return;
161+
}
162+
163+
/**
164+
* Extracted this into it's own function so I can stub and test without
165+
* having to make a request to the IDC server.
166+
* @return string
167+
* @codeCoverageIgnore
168+
*/
169+
protected function getBodyFromResponse() {
170+
return (string)$this->response->getBody();
171+
}
172+
173+
/**
174+
* @param $value
175+
*
176+
* @return float
177+
*/
178+
protected function formatValueReturnedFromInteractiveData( $value ) {
179+
if ( is_numeric( $value ) ) {
180+
return (float)$value;
181+
}
182+
183+
// @codeCoverageIgnoreStart
184+
return (float)str_replace( '"', '', $value );
185+
// @codeCoverageIgnoreEnd
186+
}
187+
}

0 commit comments

Comments
 (0)