用matplotlib制作的比较满意的蜡烛图

2D图形制作包, 功能强大, 习练了很久, 终于搞定了一个比较满意的脚本.

特点:

  1. 使用方面要非常简单
  2. 绘制出来的图要非常的满意, 具有如下的特点
    1. 时间和空间的比例尺需要固定, 就是说图件的大小需要依据数据的长度和价格的变动幅度自动调整, 至少时间轴上应该如此.
    2. 时间轴的刻度: 对于日线图而言, 年/月/日/星期几 都应该一目了然.
    3. Y轴: 对数刻度, 10%等比刻度线, 刻度值的标签应该能反应绝对的股价, 支持双Y轴(右侧的Y轴度量大盘的变化)
    4. 蜡烛非白即黑, 只要两种颜色(包括边界线)
    5. 分辨率要足够高, 至少300DPI, 方便原样(无伸缩)打印
    6. 应该支持非常方便地抽取子集, 然后制图

版本持续升级:

2017.12 的备忘录

在以前的函数式代码的基础上, OOP方式重构代码, 方便以后扩展功能, 也让程序运行得更健硕

结果展示

主块代码

绘图模块的代码

结果展示:

png file from my github:

https://github.com/duanqingshan/learngit/blob/master/均胜电子_20171230_182515__468000.png

gif file from my cnblogs:

https://files.cnblogs.com/files/duan-qs/均胜电子_20171226_220616__255000.gif

主代码块:


  1. # -*- coding: utf-8 -*-
  2. u''' 研究K线形态: 从单个K线做起, 然后K线组合, 然后K线形态
  3. # 1. 定义两个实例
  4. # 2. 加载数据
  5. # 3. 前复权处理
  6. # 4. 计算指标
  7. # 5. 形态研究之: 提取与显示
  8. # 6. 绘图 主图+成交量图
  9. '''
  10. import amipy as ami
  11. import plotter as pl
  12. import pattern as pa
  13. reload(pa)
  14. reload(ami)
  15. context = ami.Context('600699.SH') # 000911
  16. #context = ami.Context('002242.SZ') # 000911
  17. stk = ami.Stock(context)
  18. stk.grab_data_tdxlday(context, num_days=None)
  19. stk.load_tdx_qx()
  20. stk.qfq()
  21. stk.ma20 = ami.TTR.sma(stk.ohlc.close, 20)
  22. stk.cyc61 = ami.TTR.sma(stk.ohlc.close, 120)
  23. pattern = pa.Pattern(stk)
  24. pattern.study_csyx(roc1=0.3/100)
  25. #subset = slice(-250*3, None) # '2017-07' '2017'
  26. subset = slice(-120,None) # '2017-07' '2017'
  27. plotter = pl.Plotter(context,stk,subset,quanxi=None)
  28. # plotter.plot_candle_vol()
  29. #plotter.plot_candle_vol(savefig=True)
  30. #plotter.plot_timing(timing=pattern.csyx)
  31. #plotter.plot_timing(timing=pattern.szx)
  32. plotter.plot_timing(timing=pattern.upgap, savefig=True)
  33. #plotter.plot_timing(timing=pattern.dngap)

绘图代码:


  1. # -*- coding: utf-8 -*-
  2. #import sys
  3. import numpy as np
  4. import pandas as pd
  5. import datetime
  6. import matplotlib
  7. import matplotlib.pyplot as plt
  8. from matplotlib.ticker import (
  9. FixedLocator,
  10. #MultipleLocator,
  11. #LogLocator,
  12. #NullFormatter,
  13. FuncFormatter,
  14. #LogFormatter
  15. )
  16. from matplotlib.font_manager import FontProperties
  17. from matplotlib.text import Text
  18. myfont = FontProperties(fname=r"c:\windows\fonts\msyh.ttf") #size可不用指定
  19. matplotlib.rcParams['axes.unicode_minus'] = False
  20. #import amipy as ami
  21. import ttr as TTR
  22. #==============================================================================
  23. # Python中的作用域及global用法 - Summer_cool - 博客园
  24. # https://www.cnblogs.com/summer-cool/p/3884595.html
  25. #
  26. # 函数定义了本地作用域,而模块定义的是全局作用域。
  27. # 如果想要在函数内定义全局作用域,需要加上global修饰符。
  28. #
  29. # 变量名解析:LEGB原则
  30. # 当在函数中使用未认证的变量名时,Python搜索4个作用域:
  31. # [本地作用域(L-local)(函数内部声明但没有使用global的变量),
  32. # 之后是上一层结构def或者lambda的本地作用域(E-enclosure),
  33. # 之后是全局作用域(G-global)(函数中使用global声明的变量或在模块层声明的变量),
  34. # 最后是内置作用域(B)(即python的内置类和函数等)]
  35. # 并且在第一处能够找到这个变量名的地方停下来。
  36. # 如果变量名在整个的搜索过程中都没有找到,Python就会报错。
  37. #
  38. # 补:上面的变量规则只适用于简单对象,当出现引用对象的属性时,则有另一套搜索规则:
  39. # 属性引用搜索一个或多个对象,而不是作用域,并且有可能涉及到所谓的"继承"
  40. # 补2:global修饰符在python里的一个独特现象:
  41. # 在模块层面定义的变量(无需global修饰),
  42. # 如果在函数中没有再定义同名变量,可以在函数中当做全局变量使用.
  43. # 如果在函数中要对它重新赋值的话, 则必须在本函数中事先声明为全局变量, 否则会抛出异常.
  44. #
  45. # #先声明全局本函数里用到的全局变量: 图表, 上下文, 股票对象
  46. # #使用global语句可以清楚地表明变量是在外面的块定义的, 而且在本函数内
  47. # #可以使用或者修改这些变量(前提是必须先声明为全局变量, 以便告诉python
  48. # #解释器这些变量是全局的(主块和函数块共有的)已经是在外部--主代码块里--定义好了的,
  49. # # 或者是本代码块要传递到主代码块里的变量).
  50. #==============================================================================
  51. class Plotter(object):
  52. u'''
  53. Plotter class to make picture of stock's ohlcv data
  54. '''
  55. # define class var
  56. ptype_dict={
  57. 'lday':u'',
  58. 'lc5':u'五分钟'} # 这里声明的变量, 不用加global修饰符, 也是全局变量
  59. def __init__(self, context, stk, subset, quanxi=None):
  60. self.context = context
  61. self.stk = stk
  62. self.subset = subset
  63. self.quanxi = quanxi
  64. self.fig = None
  65. self.ax1 = self.ax2 = self.ax3 = None
  66. self.candle_colors = None
  67. self.length = None
  68. self.x = None
  69. def plot_candle_only(self, savefig=False):
  70. u'''仅绘制主图
  71. '''
  72. self.layout(volume_bars=False)
  73. self.candles()
  74. self.primary_curves()
  75. self.savfig(savefig)
  76. #fig #在ipython console里显示整个图表
  77. def plot_candle_vol(self, savefig=False):
  78. u'''主图+成交量图
  79. '''
  80. self.layout(volume_bars=True)
  81. self.candles()
  82. self.primary_curves()
  83. self.vol_bars()
  84. self.savfig(savefig)
  85. pass
  86. def plot_timing(self, timing=None, savefig=False):
  87. u'''画图: timingK线性形态
  88. candles + (MA20, MA120) + 形态标注
  89. volume bar
  90. para:
  91. timing: Series,
  92. note: str, {'csyx', 'szx', etc}, 长上影线, 十字星等
  93. '''
  94. self.layout(volume_bars=True)
  95. self.candles()
  96. self.primary_curves()
  97. self.vol_bars()
  98. self.annotate(timing)
  99. self.savfig(savefig)
  100. def layout(self, volume_bars=True):
  101. u'''
  102. '''
  103. if volume_bars:
  104. self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1, sharex=True, gridspec_kw={'height_ratios': [3,1]} )
  105. else:
  106. self.fig,self.ax1 = plt.subplots(1,1)
  107. #res = fig, ax1
  108. #return res
  109. def candles(self,
  110. col_func=None):
  111. u'''
  112. subset:
  113. slice object, slice(start,stop,step)
  114. that is:
  115. slice(100)
  116. slice(-100,None)
  117. slice(100,200)
  118. slice(-200,-100,2)
  119. '2011-09'
  120. '2017'
  121. '''
  122. def default_col_func(index, open1, close, low, high):
  123. return 'black' if open1[index] > close[index] else 'white' # r g b cyan black white
  124. subset=self.subset
  125. col_func= col_func or default_col_func
  126. ohlc = self.stk.ohlc[subset] if self.subset else self.stk.ohlc
  127. open1,high,low,close = ohlc.open, ohlc.high, ohlc.low, ohlc.close
  128. self.length = length = len(close)
  129. self.x = x = np.arange(length)
  130. candle_colors = [col_func(i, open1, close, low, high) for i in x]
  131. self.candle_colors = candle_colors
  132. # 计算出 每日的开盘价/收盘价里的最大值和最小值
  133. oc_min = pd.concat([open1, close], axis=1).min(axis=1)
  134. oc_max = pd.concat([open1, close], axis=1).max(axis=1)
  135. #candles = ax1.bar(x, oc_max-oc_min, bottom=oc_min, color=candle_colors, linewidth=0)
  136. #lines = ax1.vlines(x + 0.4, low, high, color=candle_colors, linewidth=1)
  137. candles = self.ax1.bar(x-0.4, oc_max-oc_min, bottom=oc_min, color=candle_colors, linewidth=0.2, edgecolor='black')
  138. shadlines_up = self.ax1.vlines(x, oc_max, high, color=['black']* length, linewidth=0.3)
  139. shadlines_dn = self.ax1.vlines(x, low, oc_min, color=['black']* length, linewidth=0.3)
  140. #print candles.__class__, shadlines_up.__class__, shadlines_dn.__class__
  141. isinstance(candles, matplotlib.container.BarContainer) == True
  142. isinstance(shadlines_dn, matplotlib.collections.LineCollection)
  143. isinstance(shadlines_up, matplotlib.collections.LineCollection)
  144. self.custom_figure()
  145. self.custom_yaxis()
  146. pass
  147. def primary_curves(self): #subset=None):
  148. #ohlc = stk.ohlc[subset] if subset else stk.ohlc
  149. #close = ohlc.close
  150. subset = self.subset
  151. if (isinstance(self.stk.ma20, pd.Series) and isinstance(self.stk.cyc61, pd.Series)):
  152. ma20 = self.stk.ma20[subset] if subset else self.stk.ma20
  153. cyc61 = self.stk.cyc61[subset] if subset else self.stk.cyc61
  154. indicators = [ma20, cyc61]
  155. x=self.x
  156. for ind in indicators:
  157. self.ax1.plot(x, ind, 'o-', lw=0.1, markersize=0.7, markeredgewidth=0.1, label=ind.name) #带圆圈标记的实线
  158. self.ax1.legend()
  159. self.custom_xaxis(ax=self.ax1)
  160. def secondary_curves(self, ax):
  161. # ohlc = stk.ohlc[subset] if subset else stk.ohlc
  162. pass
  163. def vol_bars(self):
  164. u'''
  165. '''
  166. subset = self.subset
  167. ohlc = self.stk.ohlc[subset] if subset else self.stk.ohlc
  168. volume = ohlc['volume']
  169. #open1,high,low,close = ohlc.open, ohlc.high, ohlc.low, ohlc.close
  170. x = self.x
  171. volume_scale = None
  172. scaled_volume = volume
  173. if volume.max() > 1000*1000:
  174. volume_scale = u'百万股' #'M'
  175. scaled_volume = volume / 1000.0/1000.0
  176. elif volume.max() > 1000:
  177. volume_scale = u'千股'
  178. scaled_volume = volume / 1000.0
  179. self.ax2.bar(x-0.4, scaled_volume, color=self.candle_colors, linewidth=0.2, edgecolor='black')
  180. volume_title = 'Volume'
  181. if volume_scale:
  182. volume_title = 'Volume (%s)' % volume_scale
  183. #ax2.set_title(volume_title) # 太难看了
  184. self.ax2.set_ylabel(volume_title, fontdict=None)
  185. self.ax2.xaxis.grid(False)
  186. #plt.setp(ax.get_xticklabels(minor=False), fontsize=6)
  187. self.custom_xaxis(self.ax2)
  188. pass
  189. def annotate(self, timing):
  190. u'''在主图上标注给定的K线形态:
  191. param:
  192. timing: event of Series of k-pattern
  193. note: str, 对应于事件的标注文本
  194. example:
  195. >>> plotter.annotate(csyx) #长上影线
  196. '''
  197. #ax=plt.gca()
  198. #xx = self.action.p_DJR.index
  199. c = self.stk.ohlc.close[self.subset] if self.subset else self.stk.ohlc.close
  200. self.timing = timing[self.subset] if self.subset else timing
  201. ptn_dt = c[self.timing].index # True 逻辑选择 选出长上影线的时机(日期索引)
  202. note = self.note = self.timing.name[:3]
  203. ax = self.ax1
  204. xx = map(lambda dt: c.index.get_loc(dt), ptn_dt)
  205. yy = c * 1.1
  206. #strings = self.action['value'].values.astype(str)
  207. #strings = self.action['bonus'].values.astype(str)
  208. #strings = map(lambda x: u''+str(x), strings)
  209. for i,x in enumerate(xx):
  210. #ax.text(x, yy[i], strings[i])
  211. print i, c.index[x], x, yy[x], c[x]
  212. ax.annotate(note, xy=(x, yy[x]*1.05/1.1), xytext=(x, yy[x]+0.0),
  213. arrowprops=dict(
  214. facecolor='black',
  215. color='red',
  216. #shrink=0.05,
  217. arrowstyle='->',
  218. ),)
  219. def custom_yaxis(self):
  220. u'''
  221. # 设定 Y 轴上的刻度
  222. #==================================================================================================================================================
  223. python - Matplotlib log scale tick label number formatting - Stack Overflow
  224. https://stackoverflow.com/questions/21920233/matplotlib-log-scale-tick-label-number-formatting
  225. 每个坐标轴都有7大属性:
  226. ax1.set_yscale, ylim, ylabel, yticks, yticklabels, ybound, ymargin
  227. '''
  228. #use_expo=True;
  229. expbase=1.1 # 2 e 10
  230. yaxis= self.ax1.get_yaxis()
  231. isinstance(yaxis, matplotlib.axis.YAxis)
  232. self.ax1.set_yscale(value='log', basey=expbase)
  233. pass
  234. def custom_figure(self):
  235. u''' '''
  236. # 依据绘图数据的长度和时间轴的比例尺(比如1:16)确定图表的长度:
  237. #fig = plt.gcf()
  238. #fig.set_size_inches(18.5, 10.5)
  239. self.fig.set_size_inches(self.length/16.0, 6) # /18 /20 /16 diff time-scales
  240. title = u'%s(%s)%s周期蜡烛图'%(self.context.name, self.context.symbol, self.ptype_dict[self.context.ptype])
  241. self.ax1.set_title(title)
  242. pass
  243. def custom_xaxis(self, ax):
  244. u'''
  245. '''
  246. subset = self.subset
  247. ohlc = self.stk.ohlc[subset] if subset else self.stk.ohlc
  248. close = ohlc.close
  249. length = self.length # len(close)
  250. ax.set_xlim(-2, length+10)
  251. xaxis= ax.get_xaxis()
  252. yaxis= ax.get_yaxis()
  253. # 设定 X 轴上的主刻度/次刻度位置
  254. #==================================================================================================================================================
  255. mdindex, wdindex, sdindex= self.ohlc_find_idx_fdim(close)
  256. xMajorLocator= FixedLocator(np.array(mdindex)) # 针对主刻度,实例化一个"固定式刻度定位"
  257. xMinorLocator= FixedLocator(np.array(wdindex)) # 确定 X 轴的 MinorLocator
  258. # 确定 X 轴的 MajorFormatter 和 MinorFormatter
  259. # 自定义的刻度格式(应该是一个function)
  260. datelist = close.index.date.tolist()
  261. def x_major_formatter_1(idx, pos=None):
  262. u'''
  263. 格式函数的功能: idx 是位置location, 依据位置, 返回对应的日期刻度标签
  264. '''
  265. #return datelist[idx].strftime('%Y-%m-%d')
  266. return datelist[idx].strftime('%m\n%Y')
  267. def x_major_formatter_2(idx, pos=None):
  268. return datelist[idx].strftime('\n\n%m\n%Y')
  269. def x_minor_formatter_1(idx, pos=None):
  270. #return datelist[idx].strftime(u'\n%d') # 周一
  271. return datelist[idx].strftime(u'M\n%d') # 周一
  272. def x_minor_formatter_2(idx, pos=None):
  273. return datelist[idx].strftime('%m-%d')
  274. xMajorFormatter_1 = FuncFormatter(x_major_formatter_1)
  275. xMajorFormatter_2 = FuncFormatter(x_major_formatter_2)
  276. xMinorFormatter_1 = FuncFormatter(x_minor_formatter_1)
  277. # 设定 X 轴的 Locator 和 Formatter
  278. xaxis.set_major_locator(xMajorLocator)
  279. xaxis.set_minor_locator(xMinorLocator)
  280. xaxis.set_major_formatter(xMajorFormatter_1)
  281. if self.ax2 is None:
  282. xaxis.set_major_formatter(xMajorFormatter_2)
  283. xaxis.set_minor_formatter(xMinorFormatter_1)
  284. if self.ax2 is None: # 仅绘制主图
  285. # 设定不显示的刻度标签:
  286. if ax==self.ax1:
  287. plt.setp(ax.get_xticklabels(minor=False), visible=True) #主刻度标签 可见
  288. plt.setp(ax.get_xticklabels(minor=True), visible=True) #次刻度标签 可见
  289. elif ((self.ax1 != None) and (self.ax2 != None)): # case of 主图+成交量图
  290. if ax==self.ax2:
  291. plt.setp(ax.get_xticklabels(minor=True), visible=False) #次刻度标签 隐藏
  292. elif ax==self.ax1:
  293. plt.setp(ax.get_xticklabels(minor=False), visible=False) #主刻度标签 隐藏
  294. # 设定 X 轴主刻度和次刻度标签的样式(字体大小)
  295. for malabel in ax.get_xticklabels(minor=False):
  296. malabel.set_fontsize(12) # 6号也太小了
  297. #malabel.set_horizontalalignment('right')
  298. #malabel.set_rotation('45')
  299. # if ax == ax1 or ax2:
  300. for milabel in ax.get_xticklabels(minor=True):
  301. milabel.set_fontsize(12) # 5 太小了
  302. #milabel.set_horizontalalignment('right')
  303. #milabel.set_rotation('45')
  304. #milabel.set_fontdict=myfont
  305. #milabel.set_fontproperties=myfont
  306. #milabel.set_prop=myfont
  307. # 设置两个坐标轴上的 grid
  308. #==================================================================================================================================================
  309. #xaxis_2.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
  310. xaxis.grid(True, 'major', color='0.3', linestyle='dotted', linewidth=0.3)
  311. xaxis.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
  312. #yaxis_2.grid(True, 'major', color='0.3', linestyle='dashed', linewidth=0.2)
  313. yaxis.grid(True, 'major', color='0.3', linestyle='dotted', linewidth=0.1)
  314. yaxis.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
  315. yaxis.get_major_ticks()[2].label = \
  316. Text(0,28.1024,u'28.10 $\\mathdefault{1.1^{35}}$')
  317. def ohlc_find_idx_fdim(self, ohlc):
  318. u'''
  319. 功能: index of first trading-day in month
  320. ------
  321. - 获取每个月的第一个交易日的下标(又称0轴索引).
  322. 从数据框的时间索引里提取对应的日期, 然后检索出下标.
  323. - 另外, 也获取每个交易周的第一个交易日的下标
  324. 输入:
  325. - ohlc: pandas数据框
  326. 返回:
  327. - list
  328. 例子:
  329. -------
  330. >>> mdindex, wdindex, sdindex= ohlc_find_idx_fdim(ohlc_last60)
  331. '''
  332. #datelist= [ datetime.date(int(ys), int(ms), int(ds)) for ys, ms, ds in [ dstr.split('-') for dstr in pdata[u'日期'] ] ]
  333. #last60 = ohlc[-250:]
  334. last60 = ohlc
  335. datelist = last60.index.date.tolist()
  336. # 确定 X 轴的 MajorLocator
  337. mdindex= [] # 每个月第一个交易日在所有日期列表中的 index, 月日期索引
  338. years= set([d.year for d in datelist]) # 所有的交易年份
  339. for y in sorted(years):
  340. months= set([d.month for d in datelist if d.year == y]) # 当年所有的交易月份
  341. for m in sorted(months):
  342. monthday= min([dt for dt in datelist if dt.year==y and dt.month==m]) # 当月的第一个交易日
  343. mdindex.append(datelist.index(monthday))
  344. wdindex =[] # weekday index, 每周的第一个交易日的索引
  345. for y in sorted(years):
  346. weeknum= set([int(d.strftime('%U')) for d in datelist if d.year==y])
  347. for w in sorted(weeknum):
  348. wd= min([dt for dt in datelist if dt.year==y and int(dt.strftime('%U'))==w])
  349. wdindex.append(datelist.index(wd))
  350. #==============================================================================
  351. # wdindex= [] # 每周第一个交易日在所有日期列表中的 index, 每周的第一个交易日的索引
  352. # for d in datelist:
  353. # if d.weekday() == 0: wdindex.append(datelist.index(d))
  354. #
  355. #==============================================================================
  356. # === 检索每个季末交易日的下标: sdindex: end of season day index ===
  357. # 对ndarray or list 进行逻辑运输时, 需要用np.logical_or()方法才是正确的方法:
  358. #filter1= (months==3) or (months==6)
  359. #filter1= (months==3).tolist() or (months==6).tolist()
  360. #ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
  361. dt= last60.index.date # 得到ndarray of date,
  362. # dti= last60.index # 得到pd.ts.index.DtetimeIndex of date,
  363. months= last60.index.month #得到ndarray of month, 取值范围为: 1~12
  364. # nextbar_m= last60.index.shift(1, freq='D').month # 当移动时间下标时, 数据的频率不能为空
  365. # 这样做还是有问题的, pd的做法是: 引用未来1 Day的日期, 也就是当前的日期+1day的日期
  366. # 比如: 当前的日期是 2016-12-30, 2017-01-03
  367. # .shift(1)的日期是: 2016-12-31, 2017-01-04
  368. # ==> 误判了4季末的日期变更线坐标位置
  369. # 解决办法: 应该让freq= 'per index bar', 查询一下pd的doc吧...
  370. # 变通办法: .drop first element value or .delete(0) the first location
  371. # and then .insert one value at end, to make the same length
  372. # 变通办法之: 用 freq='BQ', 来生成一个dtindex:
  373. # pd.date_range(start=mi[0], end=mi[-1], freq='BQ') # BQ business quarter endfrequency
  374. # Time Series / Date functionality — pandas 0.19.2 documentation
  375. # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
  376. #
  377. # === 还有更简洁的办法: 就是dti.quarter属性直接提供了第几个季节 ===
  378. i_index= last60.index.delete(0)
  379. i_index= i_index.insert(-1, last60.index[-1]) # -1 表示最后一个下标位置
  380. nextbar_m= i_index.month #
  381. endMar= np.logical_and(months==3, nextbar_m==4)
  382. endJun= np.logical_and(months==6, nextbar_m==7)
  383. endSep= np.logical_and(months==9, nextbar_m==10)
  384. endDec= np.logical_and(months==12, nextbar_m==1)
  385. tmp1= np.logical_or(endMar, endJun)
  386. tmp2= np.logical_or(endSep, endDec)
  387. mask= np.logical_or(tmp1, tmp2)
  388. sdindex= [dt.tolist().index(i) for i in dt[mask] ]
  389. #print u'\n==> 季节变更坐标线:'
  390. #print u' 每个季末的x轴的位置下标: %r' % sdindex
  391. #print u' 每个季末的x轴的位置时间: %r' % last60.index[sdindex]
  392. return mdindex, wdindex, sdindex
  393. def savfig(self, savefig=False):
  394. if savefig:
  395. now = datetime.datetime.now()
  396. now_s = now.strftime('%Y%m%d_%H%M%S_')
  397. microsec = str(now.microsecond)
  398. #fn= '%s_%s_%s.pdf' %(context.name, now_s, microsec )
  399. #fig.savefig(fn, dpi=300)
  400. #print u'\n==> pdf文件被创建: %s' %fn
  401. fn= '%s_%s_%s.png' %(self.context.name, now_s, microsec )
  402. self.fig.savefig(fn, dpi=300)
  403. print u'\n==> png文件被创建: %s' %fn
  404. pass
  405. if __name__ == '__main__':
  406. pass

代码(2017.11)

  1. 主块代码
  2. 绘图模块的代码
  3. 结果展示

结果展示1:

结果展示2:

主块代码: test1_load.py


  1. # -*- coding: utf-8 -*-
  2. import pandas as pd
  3. import amipy as ami
  4. reload(ami)
  5. import do_plot as dp
  6. reload(dp)
  7. #context = ami.Context('600699.SH')
  8. context = ami.Context('000911.SZ')
  9. stk = ami.Stock(context) #None,None)
  10. stk.grab_data_tdxlday(context, num_days=None)
  11. stk.ohlc = stk.ohlc_raw
  12. stk.ma20 = ami.TTR.sma(stk.ohlc.close, 20)
  13. stk.cyc61 = ami.TTR.sma(stk.ohlc.close, 120)
  14. subset = slice(-120,None) # '2017-07' '2017'
  15. subset = '2017' #slice(-120,None) # '2017-07' '2017'
  16. datas = (context, stk, subset)
  17. # 仅绘制主图
  18. #dp.plot_candle_only(datas)
  19. # 主图+成交量图
  20. dp.plot_candle_vol(datas)

绘图模块代码 do_plot.py


  1. # -*- coding: utf-8 -*-
  2. #import sys
  3. import numpy as np
  4. import pandas as pd
  5. import matplotlib
  6. import matplotlib.pyplot as plt
  7. from matplotlib.ticker import (
  8. FixedLocator,
  9. #MultipleLocator,
  10. #LogLocator,
  11. #NullFormatter,
  12. FuncFormatter,
  13. #LogFormatter
  14. )
  15. from matplotlib.font_manager import FontProperties
  16. myfont = FontProperties(fname=r"c:\windows\fonts\msyh.ttf") #size可不用指定
  17. matplotlib.rcParams['axes.unicode_minus'] = False
  18. #import amipy as ami
  19. #==============================================================================
  20. # Python中的作用域及global用法 - Summer_cool - 博客园
  21. # https://www.cnblogs.com/summer-cool/p/3884595.html
  22. #
  23. # 函数定义了本地作用域,而模块定义的是全局作用域。
  24. # 如果想要在函数内定义全局作用域,需要加上global修饰符。
  25. #
  26. # 变量名解析:LEGB原则
  27. # 当在函数中使用未认证的变量名时,Python搜索4个作用域:
  28. # [本地作用域(L-local)(函数内部声明但没有使用global的变量),
  29. # 之后是上一层结构def或者lambda的本地作用域(E-enclosure),
  30. # 之后是全局作用域(G-global)(函数中使用global声明的变量或在模块层声明的变量),
  31. # 最后是内置作用域(B)(即python的内置类和函数等)]
  32. # 并且在第一处能够找到这个变量名的地方停下来。
  33. # 如果变量名在整个的搜索过程中都没有找到,Python就会报错。
  34. #
  35. # 补:上面的变量规则只适用于简单对象,当出现引用对象的属性时,则有另一套搜索规则:
  36. # 属性引用搜索一个或多个对象,而不是作用域,并且有可能涉及到所谓的"继承"
  37. # 补2:global修饰符在python里的一个独特现象:
  38. # 在模块层面定义的变量(无需global修饰),
  39. # 如果在函数中没有再定义同名变量,可以在函数中当做全局变量使用.
  40. # 如果在函数中要对它重新赋值的话, 则必须在本函数中事先声明为全局变量, 否则会抛出异常.
  41. #
  42. # #先声明全局本函数里用到的全局变量: 图表, 上下文, 股票对象
  43. # #使用global语句可以清楚地表明变量是在外面的块定义的, 而且在本函数内
  44. # #可以使用或者修改这些变量(前提是必须先声明为全局变量, 以便告诉python
  45. # #解释器这些变量是全局的(主块和函数块共有的)已经是在外部--主代码块里--定义好了的,
  46. # # 或者是本代码块要传递到主代码块里的变量).
  47. #==============================================================================
  48. global fig, ax1, ax2, ax3 # 模块级变量名, 分别代表: 整个图表, 子图1/2/3
  49. global context, stk, subset # 模块级变量名
  50. global candle_colors, length
  51. ax2=ax3=None #初始化 ax2/ax3 子图实例为None,
  52. #fig和ax1可以不用初始化, 因为调用layout()后总是要返回fig和ax1的
  53. ptype_dict={
  54. 'lday':u'日',
  55. 'lc5':u'五分钟'} # 这里声明的变量, 不用加global修饰符, 也是全局变量
  56. def layout(volume_bars=True):
  57. u'''
  58. '''
  59. global fig, ax1, ax2, ax3
  60. if volume_bars:
  61. fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, gridspec_kw={'height_ratios': [3,1]} )
  62. res = fig, (ax1,ax2)
  63. else:
  64. fig,ax1 = plt.subplots(1,1)
  65. res = fig, ax1
  66. return res
  67. def candles(
  68. #subset=None,
  69. col_func=None):
  70. u'''
  71. subset:
  72. slice object, slice(start,stop,step)
  73. that is:
  74. slice(100)
  75. slice(-100,None)
  76. slice(100,200)
  77. slice(-200,-100,2)
  78. '2011-09'
  79. '2017'
  80. '''
  81. global context, stk, subset
  82. global candle_colors # 可能会被以后的函数所用到(比如画成交量柱子)
  83. global length
  84. def default_col_func(index, open1, close, low, high):
  85. return 'black' if open1[index] > close[index] else 'white' # r g b cyan black white
  86. col_func= col_func or default_col_func
  87. ohlc = stk.ohlc[subset] if subset else stk.ohlc
  88. open1,high,low,close = ohlc.open, ohlc.high, ohlc.low, ohlc.close
  89. length = len(close)
  90. x = np.arange(length)
  91. candle_colors = [col_func(i, open1, close, low, high) for i in x]
  92. # 计算出 每日的开盘价/收盘价里的最大值和最小值
  93. oc_min = pd.concat([open1, close], axis=1).min(axis=1)
  94. oc_max = pd.concat([open1, close], axis=1).max(axis=1)
  95. #candles = ax1.bar(x, oc_max-oc_min, bottom=oc_min, color=candle_colors, linewidth=0)
  96. #lines = ax1.vlines(x + 0.4, low, high, color=candle_colors, linewidth=1)
  97. candles = ax1.bar(x-0.4, oc_max-oc_min, bottom=oc_min, color=candle_colors, linewidth=0.2, edgecolor='black')
  98. shadlines_up = ax1.vlines(x, oc_max, high, color=['black']* length, linewidth=0.3)
  99. shadlines_dn = ax1.vlines(x, low, oc_min, color=['black']* length, linewidth=0.3)
  100. #print candles.__class__, shadlines_up.__class__, shadlines_dn.__class__
  101. isinstance(candles, matplotlib.container.BarContainer) == True
  102. isinstance(shadlines_dn, matplotlib.collections.LineCollection)
  103. isinstance(shadlines_up, matplotlib.collections.LineCollection)
  104. custom_figure()
  105. custom_yaxis()
  106. pass
  107. def primary_curves(): #subset=None):
  108. #ohlc = stk.ohlc[subset] if subset else stk.ohlc
  109. #close = ohlc.close
  110. if (isinstance(stk.ma20, pd.Series) and isinstance(stk.cyc61, pd.Series)):
  111. ma20 = stk.ma20[subset] if subset else stk.ma20
  112. cyc61 = stk.cyc61[subset] if subset else stk.cyc61
  113. length = len(ma20)
  114. x = np.arange(length)
  115. indicators = [ma20, cyc61]
  116. for ind in indicators:
  117. ax1.plot(x, ind, 'o-', lw=0.1, markersize=0.7, markeredgewidth=0.1, label=ind.name) #带圆圈标记的实线
  118. ax1.legend()
  119. custom_xaxis(ax=ax1)
  120. def secondary_curves(ax,subset=None):
  121. # ohlc = stk.ohlc[subset] if subset else stk.ohlc
  122. pass
  123. def vol_bars():
  124. u'''
  125. '''
  126. global stk, subset
  127. ohlc = stk.ohlc[subset] if subset else stk.ohlc
  128. volume = ohlc['volume']
  129. #open1,high,low,close = ohlc.open, ohlc.high, ohlc.low, ohlc.close
  130. x = np.arange(length)
  131. volume_scale = None
  132. scaled_volume = volume
  133. if volume.max() > 1000*1000:
  134. volume_scale = u'百万股' #'M'
  135. scaled_volume = volume / 1000.0/1000.0
  136. elif volume.max() > 1000:
  137. volume_scale = u'千股'
  138. scaled_volume = volume / 1000.0
  139. ax2.bar(x-0.4, scaled_volume, color=candle_colors, linewidth=0.2, edgecolor='black')
  140. volume_title = 'Volume'
  141. if volume_scale:
  142. volume_title = 'Volume (%s)' % volume_scale
  143. ax2.set_title(volume_title)
  144. ax2.xaxis.grid(False)
  145. #plt.setp(ax.get_xticklabels(minor=False), fontsize=6)
  146. custom_xaxis(ax2)
  147. pass
  148. def custom_yaxis():
  149. u'''
  150. # 设定 Y 轴上的刻度
  151. #==================================================================================================================================================
  152. python - Matplotlib log scale tick label number formatting - Stack Overflow
  153. https://stackoverflow.com/questions/21920233/matplotlib-log-scale-tick-label-number-formatting
  154. '''
  155. #use_expo=True;
  156. expbase=1.1 # 2 e 10
  157. yaxis= ax1.get_yaxis()
  158. isinstance(yaxis, matplotlib.axis.YAxis)
  159. ax1.set_yscale(value='log', basey=expbase)
  160. pass
  161. def custom_figure():
  162. u''' '''
  163. # 依据绘图数据的长度和时间轴的比例尺(比如1:16)确定图表的长度:
  164. #fig = plt.gcf()
  165. #fig.set_size_inches(18.5, 10.5)
  166. fig.set_size_inches(length/16.0, 6) # /18 /20 /16 diff time-scales
  167. title = u'%s(%s)%s周期蜡烛图'%(context.name, context.symbol, ptype_dict[context.ptype])
  168. ax1.set_title(title)
  169. pass
  170. def custom_xaxis(ax):
  171. u'''
  172. '''
  173. global ax1, ax2, ax3
  174. ohlc = stk.ohlc[subset] if subset else stk.ohlc
  175. close = ohlc.close
  176. #length = len(close)
  177. ax.set_xlim(-2, length+10)
  178. xaxis= ax.get_xaxis()
  179. yaxis= ax.get_yaxis()
  180. # 设定 X 轴上的主刻度/次刻度位置
  181. #==================================================================================================================================================
  182. mdindex, wdindex, sdindex= ohlc_find_idx_fdim(close)
  183. xMajorLocator= FixedLocator(np.array(mdindex)) # 针对主刻度,实例化一个"固定式刻度定位"
  184. xMinorLocator= FixedLocator(np.array(wdindex)) # 确定 X 轴的 MinorLocator
  185. # 确定 X 轴的 MajorFormatter 和 MinorFormatter
  186. # 自定义的刻度格式(应该是一个function)
  187. datelist = close.index.date.tolist()
  188. def x_major_formatter_1(idx, pos=None):
  189. u'''
  190. 格式函数的功能: idx 是位置location, 依据位置, 返回对应的日期刻度标签
  191. '''
  192. #return datelist[idx].strftime('%Y-%m-%d')
  193. return datelist[idx].strftime('%m\n%Y')
  194. def x_major_formatter_2(idx, pos=None):
  195. return datelist[idx].strftime('\n\n%m\n%Y')
  196. def x_minor_formatter_1(idx, pos=None):
  197. #return datelist[idx].strftime(u'一\n%d') # 周一
  198. return datelist[idx].strftime(u'M\n%d') # 周一
  199. def x_minor_formatter_2(idx, pos=None):
  200. return datelist[idx].strftime('%m-%d')
  201. xMajorFormatter_1 = FuncFormatter(x_major_formatter_1)
  202. xMajorFormatter_2 = FuncFormatter(x_major_formatter_2)
  203. xMinorFormatter_1 = FuncFormatter(x_minor_formatter_1)
  204. # 设定 X 轴的 Locator 和 Formatter
  205. xaxis.set_major_locator(xMajorLocator)
  206. xaxis.set_minor_locator(xMinorLocator)
  207. xaxis.set_major_formatter(xMajorFormatter_1)
  208. if ax2 is None:
  209. xaxis.set_major_formatter(xMajorFormatter_2)
  210. xaxis.set_minor_formatter(xMinorFormatter_1)
  211. if ax2 is None: # 仅绘制主图
  212. # 设定不显示的刻度标签:
  213. if ax==ax1:
  214. plt.setp(ax.get_xticklabels(minor=False), visible=True) #主刻度标签 可见
  215. plt.setp(ax.get_xticklabels(minor=True), visible=True) #次刻度标签 可见
  216. elif ((ax1 != None) and (ax2 != None)): # case of 主图+成交量图
  217. if ax==ax2:
  218. plt.setp(ax.get_xticklabels(minor=True), visible=False) #次刻度标签 隐藏
  219. elif ax==ax1:
  220. plt.setp(ax.get_xticklabels(minor=False), visible=False) #主刻度标签 隐藏
  221. # 设定 X 轴主刻度和次刻度标签的样式(字体大小)
  222. for malabel in ax.get_xticklabels(minor=False):
  223. malabel.set_fontsize(12) # 6号也太小了
  224. #malabel.set_horizontalalignment('right')
  225. #malabel.set_rotation('45')
  226. # if ax == ax1 or ax2:
  227. for milabel in ax.get_xticklabels(minor=True):
  228. milabel.set_fontsize(12) # 5 太小了
  229. #milabel.set_horizontalalignment('right')
  230. #milabel.set_rotation('45')
  231. #milabel.set_fontdict=myfont
  232. #milabel.set_fontproperties=myfont
  233. #milabel.set_prop=myfont
  234. # 设置两个坐标轴上的 grid
  235. #==================================================================================================================================================
  236. #xaxis_2.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
  237. xaxis.grid(True, 'major', color='0.3', linestyle='dotted', linewidth=0.3)
  238. xaxis.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
  239. #yaxis_2.grid(True, 'major', color='0.3', linestyle='dashed', linewidth=0.2)
  240. yaxis.grid(True, 'major', color='0.3', linestyle='dotted', linewidth=0.1)
  241. yaxis.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
  242. def ohlc_find_idx_fdim(ohlc):
  243. u'''
  244. 功能: index of first trading-day in month
  245. ------
  246. - 获取每个月的第一个交易日的下标(又称0轴索引).
  247. 从数据框的时间索引里提取对应的日期, 然后检索出下标.
  248. - 另外, 也获取每个交易周的第一个交易日的下标
  249. 输入:
  250. - ohlc: pandas数据框
  251. 返回:
  252. - list
  253. 例子:
  254. -------
  255. >>> mdindex, wdindex, sdindex= ohlc_find_idx_fdim(ohlc_last60)
  256. '''
  257. #datelist= [ datetime.date(int(ys), int(ms), int(ds)) for ys, ms, ds in [ dstr.split('-') for dstr in pdata[u'日期'] ] ]
  258. last60 = ohlc[-250:]
  259. datelist = last60.index.date.tolist()
  260. # 确定 X 轴的 MajorLocator
  261. mdindex= [] # 每个月第一个交易日在所有日期列表中的 index, 月日期索引
  262. years= set([d.year for d in datelist]) # 所有的交易年份
  263. for y in sorted(years):
  264. months= set([d.month for d in datelist if d.year == y]) # 当年所有的交易月份
  265. for m in sorted(months):
  266. monthday= min([dt for dt in datelist if dt.year==y and dt.month==m]) # 当月的第一个交易日
  267. mdindex.append(datelist.index(monthday))
  268. wdindex =[] # weekday index, 每周的第一个交易日的索引
  269. for y in sorted(years):
  270. weeknum= set([int(d.strftime('%U')) for d in datelist if d.year==y])
  271. for w in sorted(weeknum):
  272. wd= min([dt for dt in datelist if dt.year==y and int(dt.strftime('%U'))==w])
  273. wdindex.append(datelist.index(wd))
  274. #==============================================================================
  275. # wdindex= [] # 每周第一个交易日在所有日期列表中的 index, 每周的第一个交易日的索引
  276. # for d in datelist:
  277. # if d.weekday() == 0: wdindex.append(datelist.index(d))
  278. #
  279. #==============================================================================
  280. # === 检索每个季末交易日的下标: sdindex: end of season day index ===
  281. # 对ndarray or list 进行逻辑运输时, 需要用np.logical_or()方法才是正确的方法:
  282. #filter1= (months==3) or (months==6)
  283. #filter1= (months==3).tolist() or (months==6).tolist()
  284. #ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
  285. dt= last60.index.date # 得到ndarray of date,
  286. # dti= last60.index # 得到pd.ts.index.DtetimeIndex of date,
  287. months= last60.index.month #得到ndarray of month, 取值范围为: 1~12
  288. # nextbar_m= last60.index.shift(1, freq='D').month # 当移动时间下标时, 数据的频率不能为空
  289. # 这样做还是有问题的, pd的做法是: 引用未来1 Day的日期, 也就是当前的日期+1day的日期
  290. # 比如: 当前的日期是 2016-12-30, 2017-01-03
  291. # .shift(1)的日期是: 2016-12-31, 2017-01-04
  292. # ==> 误判了4季末的日期变更线坐标位置
  293. # 解决办法: 应该让freq= 'per index bar', 查询一下pd的doc吧...
  294. # 变通办法: .drop first element value or .delete(0) the first location
  295. # and then .insert one value at end, to make the same length
  296. # 变通办法之: 用 freq='BQ', 来生成一个dtindex:
  297. # pd.date_range(start=mi[0], end=mi[-1], freq='BQ') # BQ business quarter endfrequency
  298. # Time Series / Date functionality — pandas 0.19.2 documentation
  299. # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
  300. #
  301. # === 还有更简洁的办法: 就是dti.quarter属性直接提供了第几个季节 ===
  302. i_index= last60.index.delete(0)
  303. i_index= i_index.insert(-1, last60.index[-1]) # -1 表示最后一个下标位置
  304. nextbar_m= i_index.month #
  305. endMar= np.logical_and(months==3, nextbar_m==4)
  306. endJun= np.logical_and(months==6, nextbar_m==7)
  307. endSep= np.logical_and(months==9, nextbar_m==10)
  308. endDec= np.logical_and(months==12, nextbar_m==1)
  309. tmp1= np.logical_or(endMar, endJun)
  310. tmp2= np.logical_or(endSep, endDec)
  311. mask= np.logical_or(tmp1, tmp2)
  312. sdindex= [dt.tolist().index(i) for i in dt[mask] ]
  313. #print u'\n==> 季节变更坐标线:'
  314. #print u' 每个季末的x轴的位置下标: %r' % sdindex
  315. #print u' 每个季末的x轴的位置时间: %r' % last60.index[sdindex]
  316. return mdindex, wdindex, sdindex
  317. def plot_candle_only(datas):
  318. u'''仅绘制主图
  319. '''
  320. global context, stk, subset
  321. global fig, ax1, ax2, ax3
  322. global candle_colors, length
  323. context, stk, subset = datas
  324. layout(volume_bars=False)
  325. candles()
  326. primary_curves()
  327. #fig #在ipython console里显示整个图表
  328. def plot_candle_vol(datas):
  329. u'''主图+成交量图
  330. '''
  331. global context, stk, subset
  332. global fig, ax1, ax2, ax3
  333. global candle_colors, length
  334. context, stk, subset = datas
  335. layout(volume_bars=True)
  336. candles()
  337. primary_curves()
  338. vol_bars()
  339. pass
  340. if __name__ == '__main__':
  341. pass

用matplotlib制作的比较满意的蜡烛图的更多相关文章

  1. [Swift通天遁地]三、手势与图表-(8)制作股市中常用的蜡烛图表

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  2. arcgis制作风或水流速流向图

    制作风或水流速流向图 风速风向图或流速流向图相信大家都已经见过不少,但不知道有多少人会制作这样炫的专题图,下面这边文章向我们展示了当基本数据U和V矢量被存储时,怎样计算风或水流的速度和方向和对其进行符 ...

  3. 分支-15. 日K蜡烛图

    /* * Main.c * 分支-15. 日K蜡烛图 * Created on: 2014年6月18日 * Author: Boomkeeper ****测试通过***** */ #include & ...

  4. 使用JavaScript制作一个好看的轮播图

    目录 使用JavaScript制作出好看的轮播图效果 准备材料 1.图片若干张(包括轮播图和按钮的图片) 2.将按钮的图片应用到按钮上的CSS样式文件 3.实现轮播和点击跳转的JavaScript代码 ...

  5. 用CSS伪类制作一个不断旋转的八卦图?

    前言 介绍一下如何制作一个不断旋转的八卦图.快速预览代码及效果,点击:八卦图 代码如下: HTML部分 <!DOCTYPE html> <html> <head> ...

  6. 2个快速制作完成一幅思维导图的iMindMap思维导图用法

    随着思维导图的流行,与其相关的思维导图制作软件如雨后春笋,纷纷进入我们的视野中,更让人难以选择.那想要入门的萌新该如何开始这个新的旅途呢? 各式各样的思维导图制作软件当中,有一个软件得到了大家一致的好 ...

  7. 日K蜡烛图

    股票价格涨跌趋势,常用蜡烛图技术中的K线图来表示,分为按日的日K线.按周的周K线.按月的月K线等.以日K线为例,每天股票价格从开盘到收盘走完一天,对应一根蜡烛小图,要表示四个价格:开盘价格Open(早 ...

  8. Python+Matplotlib制作动画

    注: 在"实验设计与数据处理"的课后作业中,有一个数据可视化的作业,利用课程上学习的某种方法找一个二维函数的最大值,并将这个寻找的过程可视化.在作业里面利用了Matplotlib的 ...

  9. Python 绘图与可视化 matplotlib 制作Gif动图

    参考链接:https://blog.csdn.net/theonegis/article/details/51037850 官方文档:https://matplotlib.org/3.1.0/api/ ...

随机推荐

  1. Express模版引擎hbs备忘

    最近几天折腾了下express,想找个合适的模版引擎,下面是一些折腾过程的备忘 选择标准 选择一门模版语言时,可能会考虑的几点 语法友好(micro tmpl那种语法真是够了) 支持模版嵌套(子模版的 ...

  2. Linux shell (6)

    1.linux shell函数: 将一组命令集或语句形成一个可用的块,这些语句块成为函数. 2.shell 函数的组成:  函数名:函数的名字,注意一个脚本中函数名要唯一,否则会引起调用函数紊乱  函 ...

  3. [转]申瓯 JSY2000-06 程控电话交换机呼叫转移设置

    说明:若申瓯程控电话交换机分机有事不在位置上或遇忙分机正忙时为使某些重要来话不丢失,可设置将呼入本机的电话转移至其他分机及公网固定电话或手机.电话交换机使用了本功能不管分机用户在什么地方都能接听到办公 ...

  4. linux下SpringBoot Jar包自启脚本配置

    今天整理服务器上SpringBoot项目发现是自启的,于是想看看实现.翻看离职同事的交接文档发现一个***.service文件内容如下 [Unit] Description=sgfront After ...

  5. mongodb lock 出毛病时解决方法

    错误信息: Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145 解决办法: sudo r ...

  6. Invalid AABB inAABB UnityEngine.Canvas:SendWillRenderCanvases()的解决办法

    我遇到这个问题的情况是, 在Start()中直接使用WWW价值本地图片,可能是加载图片相对比较耗时,就出现了这个错误. 解决的办法是使用协程: // Use this for initializati ...

  7. 【MOOC EXP】Linux内核分析实验五报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 分析system_call中断处理过程 ...

  8. Linux内核分析 笔记二 操作系统是如何工作的 ——by王玥

    一.知识要点 1.计算机是如何工作的?(总结)——三个法宝 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算 ...

  9. 第二个Spring冲刺周期团队进展报告

    第一天:找识别不了的原因 第二天:继续找识别不了的原因 第三天:找文字库,找到tessdata语言包,放到手机SD卡根目录 第四天:了解OCR引擎 第五天:将导入tess-two导入到项目中,并进行测 ...

  10. 四则运算app总结

    程序有难度和单项练习,但设计了每次只出5到题,如果做错的话会把错题加入到数据库中,然后通多错题巩固选项可以对错题进行训练. 代码: 普通选项代码: package com.example.szys; ...