Skip to content

Commit 59a74fd

Browse files
authored
ramin/add_tick_classes (deriv-com#42)
* added tick & tick history classes and parsing test * some fixes * fix test compile errors
1 parent 9e7eab8 commit 59a74fd

File tree

12 files changed

+358
-3
lines changed

12 files changed

+358
-3
lines changed

lib/api/contracts/contracts_for/contracts_for_symbol.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'package:flutter_deriv_api/basic_api/generated/api.dart';
44
import 'package:flutter_deriv_api/services/connection/basic_binary_api.dart';
55
import 'package:flutter_deriv_api/services/dependency_injector/injector.dart';
66
import 'package:flutter_deriv_api/utils/helpers.dart';
7-
87
import 'exceptions/contract_for_symbol_exception.dart';
98

109
/// available contracts. Note: if the user is authenticated,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import 'package:flutter_deriv_api/api/exceptions/api_base_exception.dart';
2+
3+
/// Exception class for Tick calls
4+
class TickException extends APIBaseException {
5+
/// Initializes
6+
TickException({String message}) : super(message: message);
7+
}

lib/api/contracts/tick/tick.dart

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import 'package:flutter_deriv_api/api/models/tick_model.dart';
2+
import 'package:flutter_deriv_api/utils/helpers.dart';
3+
4+
/// Spot price updates for a given symbol
5+
class Tick extends TickModel {
6+
/// Initializes
7+
Tick({
8+
double ask,
9+
double bid,
10+
DateTime epoch,
11+
String id,
12+
int pipSize,
13+
double quote,
14+
String symbol,
15+
}) : super(
16+
ask: ask,
17+
bid: bid,
18+
epoch: epoch,
19+
id: id,
20+
pipSize: pipSize,
21+
quote: quote,
22+
symbol: symbol,
23+
);
24+
25+
/// From JSON
26+
factory Tick.fromJson(Map<String, dynamic> json) => Tick(
27+
ask: json['ask'],
28+
bid: json['bid'],
29+
epoch: json['epoch'] == null ? null : getDateTime(json['epoch']),
30+
id: json['id'],
31+
pipSize: json['pip_size'],
32+
quote: json['quote'],
33+
symbol: json['symbol'],
34+
);
35+
36+
/// Clone a new instance
37+
Tick copyWith({
38+
double ask,
39+
double bid,
40+
DateTime epoch,
41+
String id,
42+
int pipSize,
43+
double quote,
44+
String symbol,
45+
}) =>
46+
Tick(
47+
ask: ask ?? this.ask,
48+
bid: bid ?? this.bid,
49+
epoch: epoch ?? this.epoch,
50+
id: id ?? this.id,
51+
pipSize: pipSize ?? this.pipSize,
52+
quote: quote ?? this.quote,
53+
symbol: symbol ?? this.symbol,
54+
);
55+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import 'package:flutter_deriv_api/api/models/candle_model.dart';
2+
import 'package:flutter_deriv_api/api/models/history_model.dart';
3+
import 'package:flutter_deriv_api/api/models/tick_history_model.dart';
4+
5+
/// historic tick data for a given symbol.
6+
class TickHistory extends TickHistoryModel {
7+
/// Initializes
8+
TickHistory({
9+
List<CandleModel> candles,
10+
HistoryModel history,
11+
int pipSize,
12+
}) : super(
13+
candles,
14+
history,
15+
pipSize,
16+
);
17+
18+
/// From JSON
19+
factory TickHistory.fromJson(Map<String, dynamic> json) => TickHistory(
20+
candles: json['candles'] == null
21+
? null
22+
: json['candles']
23+
.map<CandleModel>(
24+
(dynamic entry) => CandleModel.fromJson(entry))
25+
.toList(),
26+
history: json['history'] == null
27+
? null
28+
: HistoryModel.fromJson(json['history']),
29+
pipSize: json['pip_size'],
30+
);
31+
32+
// TODO(ramin): Call for real API when its ready
33+
/// Gets TickHistory for the given [symbol]
34+
static Future<TickHistory> getTickHistory(
35+
String symbol, {
36+
int adjustStartTime,
37+
int count,
38+
DateTime end,
39+
int granularity,
40+
DateTime start,
41+
String style,
42+
}) async =>
43+
null;
44+
45+
/// Clone a new instance
46+
TickHistory copyWith({
47+
List<CandleModel> candles,
48+
HistoryModel history,
49+
int pipSize,
50+
}) =>
51+
TickHistory(
52+
candles: candles ?? this.candles,
53+
history: history ?? this.history,
54+
pipSize: pipSize ?? this.pipSize,
55+
);
56+
}

lib/api/models/candle_model.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
import 'package:flutter_deriv_api/utils/helpers.dart';
3+
4+
import 'base_model.dart';
5+
6+
/// price values for the given time (only for style=`candles`)
7+
class CandleModel extends BaseModel {
8+
/// Initializes
9+
CandleModel({
10+
this.close,
11+
this.epoch,
12+
this.high,
13+
this.low,
14+
this.open,
15+
});
16+
17+
/// From JSON
18+
factory CandleModel.fromJson(Map<String, dynamic> json) => CandleModel(
19+
close: json['close'],
20+
epoch: json['epoch'] == null ? null : getDateTime(json['epoch']),
21+
high: json['high'],
22+
low: json['low'],
23+
open: json['open'],
24+
);
25+
26+
/// It is the close price value for the given time
27+
final double close;
28+
29+
/// It is an epoch value
30+
final DateTime epoch;
31+
32+
/// It is the high price value for the given time
33+
final double high;
34+
35+
/// It is the low price value for the given time
36+
final double low;
37+
38+
/// It is the open price value for the given time
39+
final double open;
40+
41+
/// Clone a new instance
42+
CandleModel copyWith({
43+
double close,
44+
int epoch,
45+
double high,
46+
double low,
47+
double open,
48+
}) =>
49+
CandleModel(
50+
close: close ?? this.close,
51+
epoch: epoch ?? this.epoch,
52+
high: high ?? this.high,
53+
low: low ?? this.low,
54+
open: open ?? this.open,
55+
);
56+
}

lib/api/models/history_model.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:flutter_deriv_api/utils/helpers.dart';
2+
3+
import 'base_model.dart';
4+
5+
/// Historic tick data
6+
class HistoryModel extends BaseModel {
7+
/// Initializes
8+
HistoryModel({this.prices, this.times});
9+
10+
/// From JSON
11+
factory HistoryModel.fromJson(Map<String, dynamic> json) => HistoryModel(
12+
prices: json['prices'] == null
13+
? null
14+
: json['prices'].map<double>((dynamic entry) {
15+
final double price = entry.toDouble();
16+
return price;
17+
})?.toList(),
18+
times: json['times'] == null
19+
? null
20+
: json['times']
21+
.map<DateTime>((dynamic entry) => getDateTime(entry))
22+
?.toList(),
23+
);
24+
25+
/// Containing list of tick values for the
26+
/// corresponding epoch values in `times` array.
27+
final List<double> prices;
28+
29+
/// Containing list of epoch values for the
30+
/// corresponding tick values in `prices` array.
31+
final List<DateTime> times;
32+
33+
/// Clones a new instance
34+
HistoryModel copyWith({
35+
List<double> prices,
36+
List<DateTime> times,
37+
}) =>
38+
HistoryModel(
39+
prices: prices ?? this.prices,
40+
times: times ?? this.times,
41+
);
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'base_model.dart';
2+
import 'candle_model.dart';
3+
import 'history_model.dart';
4+
5+
/// Abstract class for TickHistory
6+
abstract class TickHistoryModel extends BaseModel {
7+
/// Initializes
8+
TickHistoryModel(
9+
this.candles,
10+
this.history,
11+
this.pipSize,
12+
);
13+
14+
/// Array of OHLC (open/high/low/close) price values for the given time.
15+
/// (only for style=`candles`)
16+
final List<CandleModel> candles;
17+
18+
/// Historic tick data for a given symbol. Note: this will always return the
19+
/// latest possible set of ticks with accordance to the parameters specified.
20+
final HistoryModel history;
21+
22+
/// Indicates the number of decimal points that
23+
/// the returned amounts must be displayed with
24+
final int pipSize;
25+
}

lib/api/models/tick_model.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import 'base_model.dart';
2+
3+
/// Spot price updates for a given symbol
4+
abstract class TickModel extends BaseModel {
5+
/// Initializes
6+
TickModel({
7+
this.ask,
8+
this.bid,
9+
this.epoch,
10+
this.id,
11+
this.pipSize,
12+
this.quote,
13+
this.symbol,
14+
});
15+
16+
/// Market ask at the epoch
17+
final double ask;
18+
19+
/// Market bid at the epoch
20+
final double bid;
21+
22+
/// Epoch time of the tick
23+
final DateTime epoch;
24+
25+
/// A stream ID that can be used to cancel this stream using
26+
/// the Forget request
27+
final String id;
28+
29+
/// Indicates the number of decimal points that
30+
/// the returned amounts must be displayed with
31+
final int pipSize;
32+
33+
/// Market value at the epoch
34+
final double quote;
35+
36+
/// Symbol
37+
final String symbol;
38+
}

test/api/models/server_time_test.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import 'dart:convert';
2+
import 'package:flutter_deriv_api/utils/helpers.dart';
23
import 'package:flutter_test/flutter_test.dart';
3-
44
import 'package:flutter_deriv_api/api/server_time/server_time.dart';
5-
import 'package:flutter_deriv_api/utils/helpers.dart';
65

76
import 'server_time_mock_date.dart';
87

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const String tickHistoryJSON = '''{
2+
"echo_req": {
3+
"adjust_start_time": 1,
4+
"count": 10,
5+
"end": "latest",
6+
"start": 1,
7+
"style": "ticks",
8+
"ticks_history": "R_50"
9+
},
10+
"history": {
11+
"prices": [
12+
218.6404,
13+
218.7205,
14+
218.7151,
15+
218.7124,
16+
218.7103,
17+
218.689
18+
],
19+
"times": [
20+
1587556946,
21+
1587556948,
22+
1587556950,
23+
1587556952,
24+
1587556954,
25+
1587556956
26+
]
27+
},
28+
"msg_type": "history",
29+
"pip_size": 4
30+
}''';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const String tickJSON = '''{
2+
"echo_req": {
3+
"ticks": "R_50"
4+
},
5+
"msg_type": "tick",
6+
"subscription": {
7+
"id": "b4d42748-0744-c46b-f59b-cb7dd936bafa"
8+
},
9+
"tick": {
10+
"ask": 218.1026,
11+
"bid": 218.0826,
12+
"epoch": 1587547610,
13+
"id": "b4d42748-0744-c46b-f59b-cb7dd936bafa",
14+
"pip_size": 4,
15+
"quote": 218.0926,
16+
"symbol": "R_50"
17+
}
18+
}''';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'dart:convert';
2+
import 'package:flutter_test/flutter_test.dart';
3+
4+
import 'package:flutter_deriv_api/api/contracts/tick/tick.dart';
5+
import 'package:flutter_deriv_api/api/contracts/tick/tick_history.dart';
6+
7+
import 'tick_history_mock_data.dart';
8+
import 'tick_mock_data.dart';
9+
10+
void main() {
11+
test('Tick stream JSON parsing', () {
12+
final Map<String, dynamic> tickMap = jsonDecode(tickJSON);
13+
final Tick tick = Tick.fromJson(tickMap['tick']);
14+
15+
expect(tick.ask, 218.1026);
16+
expect(tick.bid, 218.0826);
17+
expect(tick.id, 'b4d42748-0744-c46b-f59b-cb7dd936bafa');
18+
expect(tick.symbol, 'R_50');
19+
expect(tick.epoch.millisecondsSinceEpoch ~/ 1000, 1587547610);
20+
});
21+
22+
test('TickHistory JSON parsing', () {
23+
final Map<String, dynamic> tickHistoryMap = jsonDecode(tickHistoryJSON);
24+
final TickHistory tickHistory = TickHistory.fromJson(tickHistoryMap);
25+
26+
expect(tickHistory.history.prices.first, 218.6404);
27+
expect(tickHistory.history.times.first.millisecondsSinceEpoch ~/ 1000,
28+
1587556946);
29+
});
30+
}

0 commit comments

Comments
 (0)