forked from d3fc/d3fc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added a weekly pattern discontinuity provider
* feat: initial skipWeeklyPattern provider * feat: split weeklyPattern into local and utc * chore: fixed jest config for d3 module imports * chore: split functions into own files * chore: name refactoring * chore: fixed formatting * chore: fixed bugs & added tests * chore: fixed build errors * chore: using timezone-mock in test * chore: removed timezone-mock * chore: removed timezone specific tests * chore: setting TZ in jest config + refinements * chore: fixed prettier issue, actioned PR comments * chore: fixed typo * chore: corrected check-box value * chore: fixed linting errors
- Loading branch information
1 parent
b535374
commit 79f2d1c
Showing
19 changed files
with
1,451 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Discontinuous Axis - Removing Weekly Pattern | ||
|
||
This is another example that demonstrates how to render a financial candlestick chart on a discontinuous scale that skips a predefined weekly pattern. Try clicking the checkbox to observe the difference, when checked, the time ranges, where no trading occurs, are removed from the chart. | ||
|
||
This example demonstrates how the D3FC discontinuous scale can be used to adapt a D3 time scale adding in discontinuity provider that skips predefined time ranges on any particular day. | ||
|
||
for a non-trading pattern: | ||
|
||
{ | ||
Monday: [["07:45", "08:30"], ["13:20", "19:00"]], | ||
Tuesday: [["07:45", "08:30"], ["13:20", "19:00"]], | ||
Wednesday: [["07:45", "08:30"], ["13:20", "19:00"]], | ||
Thursday: [["07:45", "08:30"], ["13:20", "19:00"]], | ||
Friday: [["07:45", "08:30"], ["13:20", "EOD"]], | ||
Saturday: [["SOD", "EOD"]], | ||
Sunday: [["SOD", "19:00"]] | ||
}; | ||
|
||
const skipWeeklyPatternScale = fc | ||
.scaleDiscontinuous(d3.scaleTime()) | ||
.discontinuityProvider(fc.discontinuitySkipWeeklyPattern(nonTradingHoursPattern)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
it('should match the image snapshot', async () => { | ||
await d3fc.loadExample(module); | ||
const image = await page.screenshot({ | ||
omitBackground: true | ||
}); | ||
expect(image).toMatchImageSnapshot(); | ||
await d3fc.saveScreenshot(module, image); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<script src="../../node_modules/seedrandom/seedrandom.js"></script> | ||
<script>Math.seedrandom('a22ebc7c488a3a47');</script> | ||
<script src="../../node_modules/mockdate/src/mockdate.js"></script> | ||
<script>MockDate.set('2000-01-01', 0);</script> | ||
<script src="../../node_modules/d3/dist/d3.js"></script> | ||
<script src="../../packages/d3fc/build/d3fc.js"></script> | ||
<script src="../index.js"></script> | ||
<link rel="stylesheet" href="style.css"> | ||
<link rel="stylesheet" href="../index.css"> | ||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo="> | ||
</head> | ||
|
||
<body> | ||
<label id="checkbox"><input type="checkbox" id="skip"/>skip non-trading periods</label> | ||
<div id="chart"></div> | ||
|
||
<script src="index.js"></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
const checkbox = document.getElementById('skip'); | ||
|
||
// define non-trading time ranges for any day of the week | ||
const nonTradingHoursPattern = { | ||
Monday: [ | ||
['07:45', '08:30'], | ||
['13:20', '19:00'] | ||
], | ||
Tuesday: [ | ||
['07:45', '08:30'], | ||
['13:20', '19:00'] | ||
], | ||
Wednesday: [ | ||
['07:45', '08:30'], | ||
['13:20', '19:00'] | ||
], | ||
Thursday: [ | ||
['07:45', '08:30'], | ||
['13:20', '19:00'] | ||
], | ||
Friday: [ | ||
['07:45', '08:30'], | ||
['13:20', 'EOD'] | ||
], | ||
Saturday: [['SOD', 'EOD']], | ||
Sunday: [['SOD', '19:00']] | ||
}; | ||
|
||
// create discontinous date range | ||
const dates = d3.timeMinute | ||
.range(new Date(2018, 0, 1), new Date(2018, 0, 8)) | ||
.filter(dt => { | ||
const dow = dt.getDay(); | ||
switch (dow) { | ||
case 1: | ||
case 2: | ||
case 3: | ||
case 4: | ||
case 5: | ||
if ( | ||
(dt.getHours() === 7 && dt.getMinutes() >= 45) || | ||
(dt.getHours() === 8 && dt.getMinutes() < 30) || | ||
(dt.getHours() === 13 && dt.getMinutes() >= 20) || | ||
(dt.getHours() >= 14 && dow !== 5 && dt.getHours() < 19) || | ||
(dt.getHours() >= 14 && dow === 5) | ||
) { | ||
return false; | ||
} | ||
return true; | ||
case 6: | ||
return false; | ||
case 0: | ||
return dt.getHours() >= 19; | ||
} | ||
}); | ||
|
||
// create some test data that skips weekends | ||
const data = fc.randomFinancial()(dates.length); | ||
|
||
for (let i = 0; i < dates.length; i++) { | ||
// console.log(`Changing: ${data[i].date} to ${dates[i]}`); | ||
data[i].date = dates[i]; | ||
} | ||
|
||
// use the date to determine the x extent, padding by one day at each end | ||
const xExtent = fc | ||
.extentDate() | ||
.accessors([d => d.date]) | ||
.padUnit('domain') | ||
.pad([60 * 1000, 60 * 1000]); | ||
|
||
// compute the y extent from the high / low values, padding by 10% | ||
const yExtent = fc | ||
.extentLinear() | ||
.accessors([d => d.high, d => d.low]) | ||
.pad([0.1, 0.1]); | ||
|
||
// Create the gridlines and series | ||
const gridlines = fc.annotationSvgGridline(); | ||
const candlestick = fc.seriesSvgCandlestick(); | ||
|
||
// add them to the chart via a multi-series | ||
const multi = fc.seriesSvgMulti().series([gridlines, candlestick]); | ||
|
||
// adapt the d3 time scale in a discontinuous scale that skips weekends | ||
const skipWeeklyPatternScale = fc | ||
.scaleDiscontinuous(d3.scaleTime()) | ||
.discontinuityProvider( | ||
fc.discontinuitySkipWeeklyPattern(nonTradingHoursPattern) | ||
); | ||
|
||
function renderChart() { | ||
// create a chart | ||
const chart = fc | ||
.chartCartesian( | ||
checkbox.checked ? skipWeeklyPatternScale : d3.scaleTime(), | ||
d3.scaleLinear() | ||
) | ||
.xDomain(xExtent(data)) | ||
.yDomain(yExtent(data)) | ||
.xTicks(30) | ||
.svgPlotArea(multi); | ||
|
||
// render the chart | ||
d3.select('#chart') | ||
.datum(data) | ||
.call(chart); | ||
} | ||
|
||
renderChart(); | ||
checkbox.addEventListener('click', renderChart); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#checkbox { | ||
position: absolute; | ||
top: 10px; | ||
right: 10px; | ||
font-size: 1.2em; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
13 changes: 13 additions & 0 deletions
13
packages/d3fc-discontinuous-scale/src/discontinuity/skipUtcWeeklyPattern.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { utcDay, utcMillisecond } from 'd3-time'; | ||
import { base } from './skipWeeklyPattern'; | ||
import { dateTimeUtility } from './skipWeeklyPattern/dateTimeUtility'; | ||
|
||
export const utcDateTimeUtility = dateTimeUtility( | ||
(date, hh, mm, ss, ms) => new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), hh, mm, ss, ms)), | ||
date => date.getUTCDay(), | ||
date => [date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds()], | ||
utcDay, | ||
utcMillisecond | ||
); | ||
|
||
export default (nonTradingUtcHoursPattern) => base(nonTradingUtcHoursPattern, utcDateTimeUtility); |
Oops, something went wrong.